6

Well, I have been trying to use SOCKS proxy on android. Too much I am struggled and I failed to use it correctly.

Basically I do want to get a content of a page over a SOCKS proxy using HttpURLConnection (is a must).

The code I am using is this:

    String proxyHost = "192.168.2.2";
    int proxyPort = 1999;
    InetSocketAddress proxyAddr = new InetSocketAddress(proxyHost, proxyPort);
    Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxyAddr);

    URL request = new URL("http://requestb.in/sgjga5sg");

    HttpURLConnection urlConnection = (HttpURLConnection) request.openConnection(proxy);
    urlConnection.setDoInput(true);
    urlConnection.setConnectTimeout(36000);
    urlConnection.setReadTimeout(44000);

    InputStream is = urlConnection.getInputStream();

    for (int x = is.read(); x >= 0; x = is.read()) {
        System.out.print((char) x);
    }
    System.out.println();

I do get SocketTimeOutException, here is the stack trace:

java.net.SocketTimeoutException
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
at java.net.PlainSocketImpl.socksReadReply(PlainSocketImpl.java:440)
at java.net.PlainSocketImpl.socksRequestConnection(PlainSocketImpl.java:340)
at java.net.PlainSocketImpl.socksConnect(PlainSocketImpl.java:326)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:181)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:456)
at java.net.Socket.connect(Socket.java:887)
at com.android.okhttp.internal.Platform.connectSocket(Platform.java:174)
at com.android.okhttp.Connection.connect(Connection.java:152)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:276)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:332)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:199)
at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:210)
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:25)
at com.guness.testsocks.MainActivity.doTheThing(MainActivity.java:81)

Some curious things:

  • The proxy points to my SSH tunnel (apparently tested on other devices using firefox socks proxy feature).
  • When I change Proxy.Type to HTTP and choose an appropriate HttpProxy from internet it works, but I need socks.
  • Don't mind System.out.print and the loop, it is there for test purpose.
  • Test device is a C6603 model and Android version 5.1.1

Edit: It seems that SOCKS proxy does not work with HttpURLConnection on android. Some references: This thread and this thread claims so. I want to be sure if there is a way without using 3rd party libraries.

guness
  • 6,336
  • 7
  • 59
  • 88
  • 1
    You are using okhttp. That's a 3rd party library. I don't know what version of the library you are using, but okhttp just added SOCKS support recently. Have you tried using the version of `HttpURLConnection` that is built into Android? – David Wasser Mar 30 '16 at 16:24
  • 1
    Well, I am not using okhttp myself, the native `HttpURLConnection` and `HttpsURLConnection` are used on my code. maybe android internally using okhttp, not sure. – guness Mar 31 '16 at 09:41
  • I don't think so. What device are you testing on? – David Wasser Mar 31 '16 at 10:14
  • Maybe you are suing another 3rd party library that relies on okhttp? – David Wasser Mar 31 '16 at 10:17
  • @DavidWasser: Google has been using OkHttp internally for handling `HttpURLConnection` since around Android 4.4. – CommonsWare Apr 02 '16 at 20:36
  • @guness: I have used SOCKS with `HttpURLConnection` successfully, but on `localhost` through Orbot. My guess is that your problem is more specific to your proxy implementation. – CommonsWare Apr 02 '16 at 20:39
  • @CommonsWare, so you are saying if I let `proxyHost` be `localhost` instead of `127.0.0.1` I would be happy huh? Because I was trying to use Orbot and the above code did not accept `127.0.0.1`. – guness Apr 02 '16 at 21:51
  • @guness: Sorry, I was working from memory. I use `127.0.0.1`. [This project](https://github.com/commonsguy/cw-omnibus/tree/master/Internet/HTTPStacks) represents a proof-of-concept of adding NetCipher/Orbot support to various HTTP stacks (HURL, Apache HttpClient, OkHttp3, Volley). It's large, but a bunch of that code will (slowly) migrate into NetCipher itself. I got SOCKS working with Orbot on everything but OkHttp3, because they don't support SOCKS at all. – CommonsWare Apr 02 '16 at 21:57
  • @CommonsWare, so that would be the answer I guess. – guness Apr 03 '16 at 07:41
  • OkHttp3 is not what Android uses for `HttpUrlConnection`. Android uses a fork off of the original OkHttp code, lightly maintained. Again, I have `HttpURLConnection` (a.k.a., HURL) working with Orbot via a SOCKS proxy connected over `127.0.0.1`, using whatever port Orbot wound up choosing (obtained via a NetCipher broadcast). – CommonsWare Apr 03 '16 at 11:59
  • @CommonsWare I have applied your HURL implementation and nothing changed as far as I can tell. However when I have switched to `Marshmallow`, all was working like charm. – guness Apr 27 '16 at 01:57

1 Answers1

2

I have found the problem, and solution partially. As stated in my question, the device was Lollipop(5.1.1). When I use an emulator to check Marshmallow(6.0) it was working like charm, without any change. Emulator check also fails for Lollipop.

So for the future reference:

Android did not support socks proxy natively(using HURL) on devices previous than Marshmellow.

guness
  • 6,336
  • 7
  • 59
  • 88