On Wed, Feb 12, 2014 at 11:01 AM,
Post by Josh SteinerInteresting, I'll see what I can dig up on that. If HttpURLConnecction* is
better in this regard, would you prefer to drop Apache support or to keep
both as an option? It is nice to have both if you are integrating with 3rd
party libs where you can't control what they decided to use, but if its a
gaping security hole we might not want to endorse it.
This may be useful information:
Last year I evaluated Android HTTP client libraries looking for one that
worked with Tor via SOCKS to connect to a Tor Hidden Service (referenced by
.onion domain name). At the time, none of OkHttp, stock HttpUrlConnection,
or stock Apache HttpClient worked. I specifically wanted SOCKS since I did
not want to run an HTTP proxy in front of Tor's SOCKS (which I believe
would work).
Digging deeper, I believe that these libraries rely on the SOCKS support
built into Java's Socket class. There are a couple of issues with this:
1. To take advantage of remote host name resolution with the SOCKS support
built into Java's Socket class, the InetAddress you pass to
Socket.connect() ought to be constructed using createUnresolved[1].
Otherwise, the InetAddress instance resolves the host name using the system
resolver in its constructor. If I recall correctly, none of the above
libraries appeared to defer to the SOCKS proxy in this way, although they
do make use of the SOCKS support in the Socket class (for example, check
out this use in OkHttp: [2]).
2. Android's "Apache Harmony" Socket implementation differs from the
standard Java runtime in its SOCKS support. If you look what I believe to
be the Android code for Socket[3], it's totally different than the Oracle
Socket code[4] and it only supports SOCKS4, not SOCKS4a or SOCKS5. So
remote domain resolution with SOCKS is actually not supported at all with
Socket on Android (standard/Oracle Java does support SOCKS4a and SOCKS5
with remote resolution when createUnresolved() is used). What happens in
practice is that Android's Socket.connect() throws an exception when
presented with the unresolved InetAddress.
If you use one of these libraries and your system resolver can resolve the
host address, they will appear to work but you may be leaking DNS info
outside of Tor. If you need to resolve a .onion address you'll notice an
explicit error if they fail.
Ultimately, what I did (see: [5]) was use Apache HttpClient because it
allowed me to provide my own socket factory, in which I explicitly perform
the SOCKS4a protocol, sending the unresolved host name to Tor.
[1]
http://developer.android.com/reference/java/net/InetSocketAddress.html#createUnresolved%28java.lang.String,%20int%29
[2]
https://github.com/square/okhttp/blob/master/okhttp/src/main/java/com/squareup/okhttp/Connection.java#L87
[3]
https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/net/PlainSocketImpl.java
[4]
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/net/SocksSocketImpl.java
[5]
https://github.com/rod-hynes/ploggy/blob/master/AndroidApp/src/ca/psiphon/ploggy/WebClient.java#L331