2

I am trying to build a simple TCP and UDP proxies. No problem with the TCP proxy, however the UDP is a little more complex to handle. The classic proxy scenario would be like this.

  1. Listen for incoming packets from clients
  2. When packet is received send it to destination (server)
  3. Listen for possible response packets from server
  4. Send response packets back to the clients

Ok this should be simple. But when trying to implement this using Synapse or Indy I have a problem. when I receive a packet from a client, I make an internal UDP client, to forward the packet to the destination. Then I have to listen to the possible responses from the destination. Now the question is what is the best implementation for this? There is no single request / response like in TCP. Destination can response with multiple answers over time, or does not respond at all. If I continue to listen for response over one client packet, then I will miss other future packets from this or other clients.

I am looking for a good design to this problem. Here is a sample communication for the reference. Note the multiple responses from the destination at one point

- bind UDP port 40222 on interface 0.0.0.0
- ready
- add 127.0.0.1:4569

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 00 00 00 00 00 03 00 00 06 01 0b 02 00 02   ................
02 0a 37 30 30 35 35 35 31 32 31 32 04 0d 4e 6f   ..7005551212..No
74 20 41 76 61 69 6c 61 62 6c 65 09 04 00 00 00   t Available.....
08 08 04 00 00 00 08 06 06 31 36 31 34 30 31 01   .........161401.
08 34 31 33 31 33 39 34 37 0d 08 34 31 33 31 33   .41313947..41313
39 34 37                                          947

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 00 09 00 01 06 08 0e 02 00 03   ..C.............
0f 09 34 31 38 32 32 31 37 38 33 06 06 31 36 31   ..418221783..161
34 30 31                                          401

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 29 e7 00 00 00 4f 01 01 06 09 10 20 39 36   ..)....O..... 96
64 66 37 31 32 38 61 62 35 39 39 37 65 36 37 36   df7128ab5997e676
65 62 38 63 61 30 33 39 38 66 33 34 30 65         eb8ca0398f340e

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 00 56 01 02 06 07 09 04 00 00   ..C....V........
00 08                                             ..

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 29 e7 00 00 00 56 02 02 06 04               ..)....V....

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 02 85 02 02 04 0e               ..C.........

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 02 96 03 02 02 08 54 54 54 54   ..C.........TTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54               TTTTTTTTTTTT

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 29 e7 00 00 02 96 02 04 06 04               ..).........

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 aa 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 be 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 d2 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 e6 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 fa 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

EDIT:

For the record. Maybe the UDP proxy is just to messy to implement, for it to be usable. This is a strong probability, while theoretically it is certainly doable. But I will try just for the fun of it. If I get a stable working solution, then even better. Otherwise I will learn something new and admit defeat.

In no way I am trying to be stubborn and going with my head through the wall. I am still hoping somebody has a good idea :)

Thom A
  • 88,727
  • 11
  • 45
  • 75
Runner
  • 6,073
  • 26
  • 38
  • Just a note - TCP is not a request/response protocol either. You can send something and get nothing in response as well. It's probably an application-level protocol you are debugging your proxy with, which is request/response one. – Eugene Mayevski 'Callback Mar 23 '11 at 15:18
  • Yes I agree, but if you get nothing back then you know that there is no response. In contrast to UDP where you can get a "response" back after a minute delay. – Runner Mar 23 '11 at 16:08
  • I can't agree with your here -- TCP doesn't regular responses either. You never know when the server responds. Usually the parties (mostly the clients) of application-level protocols (such as FTP) have a separate timeout value, usually 60-120 seconds. So again TCP and UDP are on the same position here. – Eugene Mayevski 'Callback Mar 23 '11 at 16:15

2 Answers2

1

It's not just proxies that have this problem with UDP - network devices such as stateful firewalls and NAT devices run into it too.

The typical way that it's dealt with is to have a timeout. Once no UDP traffic between the proxied client and server has been observed for the length of the timeout, the "connection" is torn down. When traffic is seen, the timeout is reset.

Also, having one current proxied connection shouldn't prevent another one from being opened simultaneously - your proxy should be able to handle that.

caf
  • 233,326
  • 40
  • 323
  • 462
  • Yes, I have came to exactly the same conclusion :) A new internal client from a pool of clients for each new packet. Then listen for response for a certain amount of time and then release the client. Could be a problem with the number of free ports though. – Runner Mar 23 '11 at 11:01
  • That's precisely why I say a generic solution is not possible. I've been fortunate / unfortunate enough to deal with a lot of SIP traffic, that's UDP, and the Linux iptables for NAT: Iptables can handle it, but it has a *specific* conntrack module for the SIP protocol! I'm not saying it can't be done if the *iptables* guys didn't do it, but it's a good sign it's going to be difficult. – Cosmin Prund Mar 23 '11 at 11:12
  • @Cosmin Prund, Yes I am sure it is difficult. But that makes it even more interesting for me :) The packets shown in my question belong to IAX protocol. That is the other protocol, besides SIP, that Asterisk VOIP supports. That is why I want to try and do it. If I fail, no harm will be done. – Runner Mar 23 '11 at 12:06
  • 1
    @Runner, for what it's worth, IAX is easier to NAT then SIP, probably easier to proxy. Have fun! – Cosmin Prund Mar 23 '11 at 12:48
0

A typical UDP client-server communication might look like this:

  • Client sends UDP packet to port 1000
  • Server receives packet and sends back response to port 1001 (or port 1000!)

Your proxy should simply listen to packets on both port 1000 and 1001. When a packet gets in on port 1000, send it to port 1000 on the server. When a packet arrives on port 1001, it's from the server and needs to be sent on port 1001 to the appropriate client. This is pretty much where the fun ends. UDP offers nothing in terms of session or connection management: It all depends on the specific UDP protocol you're trying to proxy. If you received UDP packets from 2 different clients, and you receive a "response" packet from the server, there's nothing in UDP itself to tell you where to forward that packet. Protocols built on top of UDP might or might not have some way of maintaining state.

A generic solution is not possible, you get to read the RFCs, and you get to implement specific helpers for each and every UDP protocol you want to support.

Cosmin Prund
  • 25,498
  • 2
  • 60
  • 104
  • It think a generic solution is possible. I could have a client pool and each client would bind on a different internal port. But the problem is I could run out of ports or bind to already connected ports. Yes UDP should be simple, but it makes a proxy implementation a hell. Now I know why SSH tunneling only supports TCP. :) I am hoping somebody has a brilliant and simple solution :) – Runner Mar 23 '11 at 10:18
  • Let's say you decide to bind to ports 6000-6099 to handle 100 different clients. How do you convince client 1 to send to 6000 and client 2 to send to 6001, when both clients would much prefer to send to port 1000 since that's in the RFC for the protocol being implemented over UDP? – Cosmin Prund Mar 23 '11 at 10:29
  • If you have one app you would like to proxy, you start the proxy and listen on port 6000 for instance. The App connects to localhost on port 6000. For each packet the proxy receives it internally creates a UDP client on new port and send the data to destionation. then it listens for responses for a period of time. You always have a single local port on which you listen and single IP / Port destination. If you need more you start more proxies on different ports. – Runner Mar 23 '11 at 10:51
  • I have tested such a solution so I know it is possible. http://linux.softpedia.com/get/Internet/Proxy/Simple-UDP-proxy-pipe-11521.shtml – Runner Mar 23 '11 at 10:54
  • And no I cannot use this, because I would like to have encryption between two such proxies :) – Runner Mar 23 '11 at 10:59