Jump to content

SOCKS5 support in uTorrent is broken [thread includes a fix]


cjard

Recommended Posts

OK, I chased down the bug in uT.. I'd made some wrong assumptions in the other topic so i deleted them.

Using a modified proxy I wrote for my university diss (when I was writing a SOCKS proxy of my own), i watched the traffic flowing in slow-time..

Here is the normal process of negotiation with a socks 5 server, using user/password auth assuming everything goes ok. All values are in hex, with a bold translation into english:

ut> 05 02 00 02 socks v5, i know of 2 auth methods, no auth, userpassword auth

proxy> 05 02 socks v5, use method 02 userpass

ut> 01 01 65 01 65 userpass subneg v1, username is 1 byte long, username is A, password is 1 byte long, password is A

proxy> 01 00 userpass subneg v1, userpass is ok

ut> ... some bytes that make it do a connection ...

Where UT breaks is the part where the proxy says "01 00" (user/pass is ok).

RFC1929 is the spec for user/pass auth, and it says that the response must be:

VER, RES

where ver is the version (of the sub neg i.e. 0x01)

and res is the result (ie.e 0x00=user pass ok, any other value is failure)

I got the feeling that Ludde has implemented it thinking that the VERsion must be the socks version in use.. but we are still in the sub-negotiation.. However, it looks like other socks proxy programmers are just as confused by this if the claim is true that some proxies work and some proxies dont.. (it means some proxies return 5 and some return 1)

I added some code to my app to change the 01 byte that my proxy (FreeProxy 3.92) returns, into an 05, before it passes it on to UT, and UT started working fine.. If, when I prove this app a little more, anyone else out there would like to test my app and see if it makes UT work for you, then post a reply here

So, in summary:

UT reports bad potocol version because it is expecting the server to say byte[]{05, 00} meaning "proxy username/password is ok" when it should be expecting byte[]{01, 00}

Ultimately, UT shouldnt really care about this byte, as it is less important than the second octet of 00 meaning u/p is ok.. UT can be programmed to accept either 01 or 05 here, so long as it heeds the 00 that follows, and uses the proxy accordingly..

OK, i've edited a few bits about my app to make it a bit less of a dirty hack - its stable enough and uTorrent used the socks proxy all night without bother, so if anyone is experiencing "Bad Protocol Version" and wants to see if my app makes uT work for them.. drop a reply in this thread or pm your email address and I'll send it to you..

.. and anyone moaning that it's a .NET2 app and takes 4 times more memory than uTorrent does will be given a refund for the full amount they paid me for it :D

Link to comment
Share on other sites

Thank you!

Since you seem to be knowledgeable with the SOCKS5 protocol. What would you say happens if I send a BIND command with DST.ADDR and DST.PORT both set to zero? Would that mean that I can accept incoming connection from any address?

And the next question, is there any way to hint the socks proxy on which port it should listen?

The reason why I'm asking is because I'm interested in whether it would be possible to get incoming connections through a socks5 proxy. My guess is that it would be pretty much a no though.

Link to comment
Share on other sites

bind 0.0.0.0 port 0 should cause the socks server to bind a randomly chosen port to all interfaces. The problem arising thus, however, is that the server may have multiple interfaces and not know which interface is connected to the outside world, hence which interface should the client report to the remote, hence it makes BIND 0.0.0.0,0 pretty useless.

Example:

A server has 3 network cards, two of which have "real" ip addresses:

1.2.3.4

2.3.4.5

10.0.0.1

issuing a bind 0.0.0.0 makes the server bind a port to all 3, but it has no way of knowing which ip to send back to the client.

Obviously a bind would be useful for someone connecting from remote foreign ip 9.8.7.6.. and suppose this ip would be routed over the 1.2.3.4 interface - the server doesnt know this: it doesnt know that the company firewall will choose to send the incoming conenction to 1.2.3.4 interface; it could just as easily send it to 2.3.4.5

So, given that it doesnt know what to reply back to the client, it will probably say it has bound 0.0.0.0

Now, the client is suppsoed to be in dialogue with the remote (FTP) server and say "i've opened a port 12345 on ip a.b.c.d" - this would be the ip of the socks server, but the socks server didnt know which IP to give, and the client doesnt know what IPs the socks has either.

Infact, the client NEVER gets to know what IPs the server has, unless it's published in e.g. a text file by the socks admin and can be set in the prefs of your client (that is using the socks proxy)

Overall, I dont think BIND was particularly well thought through

BIND should have been implemented like this:

client> BIND your ip 0.0.0.0, your port 0, relay to myip 10.0.0.49, myport 12345

server> OK, i have bound IP 1.2.3.4, port 12121

server> OK, i have bound IP 2.3.4.5, port 12121

server> OK, i have bound IP 10.0.0.1, port 12121

(client drops connection)

(client then picks one of the likely ip addresses, sends it to the remote client or ftp server)

(remote ftp server connects to socks)

(socks creates new connection to 10.0.0.49 my ip, port 12345)

(socks relays traffic)

(socks drops conenction)

client> UNBIND 12121

server> OK, unbound 12121 (or error: you dont own that port binding)

It needs a little more thought im sure, but this would have made it useful. I wonder if I would get a response if I wrote to the author of RFC1928.. Or maybe submit an rfc of my own?

also see the discussion im having with alus in Feature Requests

Link to comment
Share on other sites

Are you saying that the DST.ADDR and DST.PORT fields in the bind command tells the proxy what address to bind its listen port to?

I wouldn't say the RFC is very clear on this point, the field are called destination address after all. Do you know how openssl implements BIND?

That would indeed be strange, since the client doesn't have a clue on the proxy's external IP. However, it could still be useful to set it to 0 and specify the listen port, say 6881, and wait for an incoming connection.

As soon as an incoming connection is accepted, another connection is opened to the proxy, issuing another BIND command to listen on the same port (assuming the proxy will close the listen socket when one connection is accepted on it). That way, one could simulate proper port forwarding quite closely.

Link to comment
Share on other sites

mmm, the more I re-read the FAQ the more I think I remember this being the part that was too confusing to bother implementing when I wrote my SOCKS server. Now that you ask, I can se eit being a reasonable assumption that BIND might take the remote ip and the port - the server can then use the ip to determine if it will be allowed.. as to what use the remote port specification is, I have no idea.. How would the local client know what remote port will be the startpoint of the TCP transmit?

Let me take a look into this by actually probing my SOCKS server and seeing what it says; maybe the author of freeproxy knew more about it. Incidentally, I've written to the author of the RFC..

Link to comment
Share on other sites

Well, The author of my proxy has let me take a look at some of his code, and the puzzling thing is, what I see is not what his code would imply.. He's got a slightly different take on it than I. The author of the rfc hasnt responded.. Might be time to ask Permeo..

Edit:

I didnt see this mentioned in any of the Version Changes history, but I can confirm that this bug now appears to be fixed as of 1.7.1703 - This version works great with the SOCKS5 implementation offered by FreeProxy 3.92+

Thanks for looking at it!

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...