views:

797

answers:

3

Assume I have a reliable UDP library, and want to tunnel arbitrary TCP connections over it. This is my current approach to doing so, but I feel that it may not be very efficient. Any suggestions are very welcome.

  1. Client establishes a reliable UDP connection to server.
  2. Client runs a local SOCKS5 proxy, which receives data from any app that connects to it and forwards it through the reliable UDP connection. Each packet includes a 4-byte id unique to each SOCKS connection.
  3. Server receives data. If the 4-byte id is new, it makes a new connection to its local TCP socket and sends the data, and spawns a new thread which receives any replies from the server and forwards them through the reliable UDP connection with the appropriate id. If the 4-byte id is old, it simply sends the data over the existing TCP connection.
  4. Client receives data, sending it over the existing SOCKS connection to whatever app started it.

Right now, this seems to work for making simple HTML requests from a browser, but since the server isn't directly connected to the client, it is unable to tell when the client terminates a connection. Is there a better way to do this?

EDIT: No, this is not homework. And please don't bother replying if you aren't aware of the advantages of reliable UDP libraries, or for that matter, haven't heard of them before. Thanks.

+5  A: 

there are a few ready to use options:

  • OpenVPN: tunnels either IP or ethernet Frames on top of UDP
  • Teredo: tunnels IPv6 on top of UDPv4, manages both NAT traversing and full compatibility with IPv6
  • UDT: non-standard, reliable, high-performance, multi-transport, TCP-like protocol on top of UDP. Optionally lets you manage NAT traversal and then takes it from there
Javier
Thanks, but I am already aware of libraries related to what I'm doing. I'm specifically attempting to implement tunneling *using* a reliable UDP library.
oskar
A: 

The most efficient way is when the two endpoints directly communicate to each other. If they communicate with different protocols, you need at least one proxy / gateway / traffic converter / whatever. In this case, there is no way around two of these converters, as you now have 3 parts involved: End point client, network traffic, endpoint server. I don't see how you could make it more efficient under the given circumstances.

As for the terminated connections, if you use a tunnel then use it for all traffic, i.e. communicate all kinds of requests of both client and server to the other side. If a termination can't be communicated to the server, then the problem is sitting on the client side -- the client end point does not communicate its termination to the client tunnel entry. If it would, then you can transfer this termination to the server.

Secure
I'm not quite sure how to transfer infomation beyond simply the data contained within the packets. I use a simple process in which I recv() data with one protocol, then send() it using the other protocol. Forwarding control information such as ACK packets aren't necessary because the UDP library I'm using provides that already.
oskar
@oskar: if you are already maintaining a map of connections, can't you send a 'connection abort' to clients that are indirectly connected?
0A0D
I was actually thinking about doing just that; essentially, writing my own "abort" message. The only reason I haven't is because it seems inelegant to invent my own protocol, but perhaps that's the best option.
oskar
@oskar: I think it will work if you don't build in anymore ACK/NAK.. then you are essentially recreating TCP.
0A0D
I think the problem is that you have a half-baked mixed approach between a tunnel and a client-server communication (as for a database). It is not really a tunnel because it filters obviously important messages, and it is not really a client-server approach because it is too strictly connected to the transport medium. Maybe you should decide for one side and stick to it?
Secure
A: 

You're going to have to communicate the loss of the client TCP connection to the server side across your UDP tunnel (and the opposite, if the server should happen to close the connection first).

Otherwise, quite apart from the fact that the HTTP server doesn't know the client has disconnected, you will be leaking connections on the side that didn't initiate the connection closure.

One way to do this would be to reserve a special value of your 32 bit connection ID field - say 0x00000000 or 0xffffffff - as representing a control packet rather than connection data. Following that is another 4-byte field representing a connection ID, and following that is an opcode field. The first opcode you could define is "Connection terminated".

  • If your client-side of the tunnel detects that the client application has closed its TCP connection, it sends a Connection-Terminated packet for the corresponding connection ID over the tunnel;
  • If your client-side of the tunnel gets a "Connection terminated" opcode from the server side, then it closes its connection with the client application;

and similar for the server-side of the tunnel.

caf