11
votes

The SOCKS5 protocol, described by RFC1928 provides support for UDP.

To summarize, a client wishing to relay UDP packets through a SOCKS5 server must, at least:

  • open a TCP connection to the SOCKS5 server;
  • send a UDP ASSOCIATE request (cf section 4);
  • receive from the server the address and port where it must send UDP packets to be relayed;
  • send datagrams (UDP) to that address, encapsulated with some headers (cf section 7).

Here are some relevant quotations, from section 6:

A UDP association terminates when the TCP connection that the UDP ASSOCIATE request arrived on terminates.

In the reply to a UDP ASSOCIATE request, the BND.PORT and BND.ADDR fields indicate the port number/address where the client MUST send UDP request messages to be relayed.

and section 7:

A UDP-based client MUST send its datagrams to the UDP relay server at the UDP port indicated by BND.PORT in the reply to the UDP ASSOCIATE request.

Why so much complexity? Why not just sending UDP packets in the pre-existing TCP connection?

EDIT: To clarify, I am expecting the SOCKS proxy to receive UDP packets over a TCP stream and then transmit them to the target using actual UDP. And then receive UDP packets from the target and send them back down the TCP stream.


Here is some context.

My goal is to implement reverse tethering, so that an Android device may use the internet connection of the computer it is plugged on, without requiring root access both on the device and the computer (SimpleRT works but requires root access on the computer).

My first idea was to start a simple SOCKS5 server with ssh -D on the computer, so that I only needed to implement the client. The packets would be transmitted from the device to the computer over adb, thanks to remote port forwarding provided by adb reverse

Unfortunately, OpenSSH SOCKS server does not support UDP. But it was just a limitation from the implementation, I could have used another SOCKS server instead.

However, adb reverse does not support UDP forwarding either.

Hence my question about SOCKS5 protocol.

I am currently writing a PoC implementing my own (simple) protocol over TCP, which is able to relay UDP packets, but I am disappointed not to be able to use a standard protocol (and benefit from existing implementations).

1
You can't send datagrams over a TCP connection. TCP is a byte-stream protocol. The question want make sense.user207421
I mean, of course, a UDP packet wrapped over a TCP stream, as payload.rom1v
@rom1v: If UDP packets were wrapped in a TCP stream, it would not be UDP anymore, it would be TCP. Existing UDP software behind the proxy won't know to do the TCP wrapping. One scenario that comes to mind is one app connects to the SOCKS proxy and opens the UDP relay port, and then another app does the actual sending of UDP packets through the proxy. Because UDP is connectionless, there is nothing to prevent this. Nothing requires the app opening the UDP port and the app sending to the UDP data to be the same app. TCP, on the other hand, would not allow that.Remy Lebeau
@rom1v: are you expecting the SOCKS proxy to receive UDP packets over a TCP stream and then transmit them to the target using actual UDP? And then receive UDP packets from the target and send them back down the TCP stream?Remy Lebeau
@Remy Lebeau Exactly. I edited my question to add your formulation, which is perfect ;-)rom1v

1 Answers

7
votes

I am answering to my own question: it's probably to avoid TCP mechanisms (packet retransmission, head-of-line blocking…).

For a local reverse tethering tool, it is not a problem though, so I implemented UDP over TCP without using SOCKS.