How to tunnel TCP over reliable UDP?
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.
- Client establishes a reliable UDP connection to server.
- 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.
- 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.
- 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.
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
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.
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.
精彩评论