如何在Java中使用SOCKS?

问题描述 投票:0回答:5

我使用 100% 工作袜,但无法通过我的应用程序进行连接。

        SocketAddress proxyAddr = new InetSocketAddress("1.1.1.1", 12345);
        Proxy pr = new Proxy(Proxy.Type.SOCKS, proxyAddr);

    try
    {
        HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(pr);
        con.setConnectTimeout(proxyTimeout * 1000);
        con.setReadTimeout(proxyTimeout * 1000);
        con.connect();

        System.out.println(con.usingProxy());
    }
    catch(IOException ex)
    {
        Logger.getLogger(Enter.class.getName()).log(Level.SEVERE, null, ex);
    }

那么我做错了什么?如果我将 HTTP 与某些 HTTP 代理一起使用,则一切都可以工作,但不能与 SOCKS 一起使用。

java http proxy socks
5个回答
27
投票

这真的很容易。您只需要设置相关的系统属性,然后继续使用常规的 HttpConnection 即可。

    try
    {
        HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(pr);
        con.setConnectTimeout(proxyTimeout * 1000);
        con.setReadTimeout(proxyTimeout * 1000);
        con.connect();

        System.out.println(con.usingProxy());
    }
    catch(IOException ex)
    {
        Logger.getLogger(Enter.class.getName()).log(Level.SEVERE, null, ex);
    }

9
投票

告知“socksProxyHost”和“socksProxyPort”VM 参数。

例如

System.getProperties().put( "proxySet", "true" );
System.getProperties().put( "socksProxyHost", "127.0.0.1" );
System.getProperties().put( "socksProxyPort", "1234" );

2
投票

http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/net/www/http/HttpClient.java/?v=source

深层来说,HttpClient 是用在 HttpURLConnection 中的。

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main

在第 476 行,您可以看到唯一可接受的代理是 HTTP 代理。否则它会直接连接。

奇怪的是,不支持使用 HttpURLConnection 的 SOCKS 代理。更糟糕的是,代码甚至没有使用不受支持的代理,只是忽略代理!

无法解释为什么在该类存在至少 10 年之后没有任何对 SOCKS 代理的支持。


1
投票

或者这个答案:https://stackoverflow.com/a/64649010/5352325

如果你知道哪些URI需要去代理,你还可以使用底层ProxySelector:https://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html其中for每个建立的 Socket 连接,您可以决定使用哪些代理。

它看起来像这样:

if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
   sun.net.www.URLConnection.setProxiedHost(host);
   privilegedOpenServer((InetSocketAddress) proxy.address());
   usingProxy = true;
   return;
} else {
   // make direct connection
   openServer(host, port);
   usingProxy = false;
   return;
}

然后使用选择器:

public class MyProxySelector extends ProxySelector {
        ...

        public java.util.List<Proxy> select(URI uri) {
        ...
          if (uri is what I need) {
             return list of my Proxies
          }
        ...
        }
        ...
}
 

0
投票

全球代理

您可以传递 JVM 参数来设置将应用于所有 JVM 网络流量的 SOCKS 代理:

public static void main(String[] args) {
        MyProxySelector ps = new MyProxySelector(ProxySelector.getDefault());
        ProxySelector.setDefault(ps);
        // rest of the application
}

更灵活的方法是在运行时使用系统属性来设置它:

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1234 Application

当您需要确保整个应用程序都使用代理时,最好使用通过 JVM 参数或系统属性设置代理。例如,当您需要代理 Spring Boot 应用程序以连接到数据库或类似的东西时。

每连接代理

这是设置代理的最灵活的方式,因为您可以基于每个连接进行设置。以下是使用 Java 11

System.getProperties().put("socksProxyHost", "127.0.0.1");
System.getProperties().put("socksProxyPort", "1234");
和旧版
HttpClient
进行每连接代理的示例:

HttpURLConnection

当您想要隔离特定请求的代理或在运行时动态切换代理时,此方法最有用。您还可以将全局代理与按请求代理混合,这样您就可以设置全局代理,但通过不同的代理发送特定请求。

您可以在此处阅读有关 Java 代理的更多信息:https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html

© www.soinside.com 2019 - 2024. All rights reserved.