Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java HttpURLConnection uses SOCKS proxy instead of HTTP

I have a very simple code that uses HttpURLConnection to access some web site via proxy

    System.setProperty("java.net.useSystemProxies", "true");
    System.out.println("Proxy: " + ProxySelector.getDefault().select(new URI(urlS)));
    URL url = new URL(urlS);
    HttpURLConnection ic = (HttpURLConnection)url.openConnection();

    ic.connect();

For some reason, Java thinks that I need SOCKS proxy, not http, throwing the following exception:

ERROR: Can't connect to SOCKS proxy:Connection timed out: connect
like image 494
Demiurg Avatar asked Apr 15 '26 21:04

Demiurg


2 Answers

If you are having this issues on Windows, you may run into a Java bug.

Java treats any system proxy setting as SOCKS. You have to either disable useSystemProxies or don't use proxy in Windows.

If proxy is needed, try to uncheck "Use the same proxy server for all protocols", making sure the field for the SOCKS proxy is blank. That fixed our problem.

like image 96
ZZ Coder Avatar answered Apr 17 '26 10:04

ZZ Coder


The real problem is that Java assumes that the "Use the same proxy server for all protocols" check affects SOCKS proxy too (I don't know the logic behind this dialog in Windows, but it is, at least, confusing) If the check is set, you get proxies enabled for both HTTP and SOCKS, wich is very unlikely to be the desired configuration. One way to solve it is unchecking the check and leaving blank the SOCKS field.

I finally solved it creating a ProxySelector wich first calls the default selector and if it finds the same configuration for HTTP and SOCKS connections, it omits the SOCKS proxy.

   public class SocksFixerProxySelector extends ProxySelector {

    ProxySelector base;

    public SocksFixerProxySelector() {
         base = ProxySelector.getDefault();
    }

    @Override
    public List<Proxy> select(URI uri) {

        List<Proxy> baseList = base.select(uri);

        try {
            if (uri.getScheme().equals("socket")) {

                Proxy socksProxy = findByType(baseList, Type.SOCKS);
                if (socksProxy != null) {

                    URI httpTestUri = new URI("http", uri.getHost(), uri.getPath(), uri.getFragment());
                    Proxy httpProxy = findByType(base.select(httpTestUri), Type.HTTP);

                    if (httpProxy != null && socksProxy.address().equals(httpProxy.address())) {
                        // Quitamos SOCKS
                        List<Proxy> filteredList = new ArrayList<>(baseList);
                        filteredList.remove(socksProxy);
                        return filteredList;
                    }
                }
            }
        } catch (Exception e) {

        }
        return baseList;

    }

    @Override
    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
        base.connectFailed(uri, sa, ioe);

    }

    private Proxy findByType(List<Proxy> proxies, Proxy.Type type) {
        for (Proxy proxy : proxies) {
            if (proxy.type() == type)
                return proxy;
        }

        return null;
    }

Maybe a better solution would be to inspect the registry and detect the right settings, but I didn't want to mess with Windows specific code (and all those script settings looked bad, too )

like image 41
Juan Calero Avatar answered Apr 17 '26 10:04

Juan Calero



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!