如何在Java中使用SOCKS?

发布于 2024-11-01 15:28:49 字数 639 浏览 2 评论 0原文

我使用 100% 正常工作的 SOCKS,但无法通过我的应用程序进行连接:

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 则不行。

I use 100% working SOCKS and I can't connect through my application:

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);
}

So what am I doing wrong? If I use HTTP with some HTTP proxy all is working, but not with SOCKS.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

等数载,海棠开 2024-11-08 15:28:50

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

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

它看起来像这样:

public class MyProxySelector extends ProxySelector {
        ...

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

然后你使用你的选择器:

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

Or this answer: https://stackoverflow.com/a/64649010/5352325

If you know which URIs need to go to proxy, you can also use the low layer ProxySelector: https://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html where for each Socket connection that is made, you can decide what proxies are to be used.

It looks something like this:

public class MyProxySelector extends ProxySelector {
        ...

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

Then you make use of your selector:

public static void main(String[] args) {
        MyProxySelector ps = new MyProxySelector(ProxySelector.getDefault());
        ProxySelector.setDefault(ps);
        // rest of the application
}
攒一口袋星星 2024-11-08 15:28:50

全局代理

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

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1234 Application

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

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

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

每个连接代理

这是设置代理的最灵活的方法,因为您可以基于每个连接进行设置。以下是使用 Java 11 HttpClient 和旧版 HttpURLConnection 进行按连接代理的示例:

public static void java11Http(String url) throws Exception {
    ProxySelector proxySelector = new ProxySelector() {
        @Override
        public List<Proxy> select(URI uri) {
            return List.of(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 1234)));
        }
        @Override
        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
            ioe.printStackTrace();
        }
    };

    HttpClient client = HttpClient.newBuilder()
            .proxy(proxySelector)
            .build();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    System.out.println(response.body());
}

private static void legacyJavaHttp(String url) {
    SocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", 1234);
    Proxy pr = new Proxy(Proxy.Type.SOCKS, proxyAddr);

    try {
        HttpURLConnection con = (HttpURLConnection) URI.create(url).toURL().openConnection(pr);
        con.setConnectTimeout(5000);
        con.setReadTimeout(5000);
        con.connect();
        System.out.println(con.getResponseMessage());
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

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

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

Global Proxy

You can pass JVM arguments to setup a SOCKS proxy that will be applied to all JVM network traffic:

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1234 Application

A more flexible approach is to set it using system properties during runtime:

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

Setting the proxy via JVM arguments or system properties is best used when you need to ensure the entire application is using a proxy. For example, when you need to proxy a Spring Boot application to connect to a database or something like that.

Per-Connection Proxy

This is the most flexible way of setting up proxies, as you can set it on a per-connection basis. Here is an example of per-connection proxying with the Java 11 HttpClient and the legacy HttpURLConnection:

public static void java11Http(String url) throws Exception {
    ProxySelector proxySelector = new ProxySelector() {
        @Override
        public List<Proxy> select(URI uri) {
            return List.of(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 1234)));
        }
        @Override
        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
            ioe.printStackTrace();
        }
    };

    HttpClient client = HttpClient.newBuilder()
            .proxy(proxySelector)
            .build();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    System.out.println(response.body());
}

private static void legacyJavaHttp(String url) {
    SocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", 1234);
    Proxy pr = new Proxy(Proxy.Type.SOCKS, proxyAddr);

    try {
        HttpURLConnection con = (HttpURLConnection) URI.create(url).toURL().openConnection(pr);
        con.setConnectTimeout(5000);
        con.setReadTimeout(5000);
        con.connect();
        System.out.println(con.getResponseMessage());
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

This approach is most useful when you want to isolate proxying to specific requests or dynamically switch proxies during runtime. You can also mix global proxying with per-request proxying, so you can set a global proxy, but send specific requests trough a different proxy.

You can read more on Java proxying here: https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html

恰似旧人归 2024-11-08 15:28:49

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

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

It's really easy. You just need to set the relevant System Properties and just get on with your regular HttpConnection.

System.getProperties().put( "proxySet", "true" );
System.getProperties().put( "socksProxyHost", "127.0.0.1" );
System.getProperties().put( "socksProxyPort", "1234" );
薆情海 2024-11-08 15:28:49

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

例如

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

Inform the "socksProxyHost" and "socksProxyPort" VM arguments.

e.g.

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
千笙结 2024-11-08 15:28:49

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

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

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;
}

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

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

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

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

Deep down, HttpClient is used in HttpURLConnection.

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;
}

On line 476, you can see that the only acceptable proxy is an HTTP proxy. It makes a direct connection otherwise.

Weirdly there's is no support for SOCKS proxy using HttpURLConnection. Even worse, the code doesn't even t using an unsupported proxy and just ignores the proxy!

Why there isn't any support for SOCKS proxies after at least 10 years of this class' existence cannot be explained.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文