2

I wrote a program that sets-up peer-to-peer links. The programm, which can be found at http://basyl.co.uk/code/punch/doc/files/Readme-txt.html, is in two parts: a server that runs on a public host; and a client that is used by each end of the desired peer-to-peer link.

I have access to two public servers: 'bonn' (home.contextshift.co.uk) and 'entropy' (home2.contextshift.co.uk)

  • If the server is on bonn and clients are run on bonn, entropy and my home PC (behind NAT), a punched connection from entropy can talk to my PC without problem. However, a connection from bonn to the PC fails; data from the PC reaches bonn, but data from bonn back through the NAT hole never arrives.

  • If the server is on entropy and again, clients are run on bonn, entropy and my PC, punched connections work fine between all clients.

This is confusing as the server is not involved in the peer-to-peer data flow. If you are still with me, here is the flow:

  • Client-A connects to Server on a TCP link and gets a unique token;
  • Client-B connects to Server on a TCP link and gets a unique token;

  • Client-A and Client-B receive updates over their TCP link telling them who else is attached;

  • Client-A (or B) sends a request to the Server over a newly created UDP link passing its token and the name of Client-B;

  • The Server identifies Client-A from the token and forwards the request to Client-B over its TCP link, including A's UDP address/port number in the request;

  • Client-A (or B) sends a confirmation to the Server over a newly created UDP link, passing its token and the name of Client-A;

  • The Server identifies Client-B from the token and forwards the request to Client-A over its TCP link, including B's UDP address/port number in the request;

  • A and B now have the UDP address/port of the other and can ping each other and exchange data.

As you can see, the Server never talks on the UDP links created by the Clients for their requests, only on the TCP links.

So in summary, the client doesn't work on a particular host when the server is on the same host. Any suggestions for reasons for this behaviour or for ways I could investigate this further?

Note that this test is artificial because the point of the hole punching is to talk between two hosts both behind NAT. This in fact works, wherever the server is, so the problem might be considered academic.

Note also that before writing the program, I tried using a public app called 'NatCheck'. This also failed in a similar way, although I didn't investigate it much - it required three public hosts and I modified it to use just my two. When it failed to work, I assumed that I had screwed up in some way and discarded the app.

Any comments on the code also highly welcome (I will probably post it on the code review site).

William Morris
  • 3,554
  • 2
  • 23
  • 24

3 Answers3

4

I can't quite follow all that, but it sounds like you want to use an intermediary server to discover the source UDP ports for Clients A and B so that A and B can simultaneously send UDP datagrams at each-other, thereby opening NAT rules and (eventually) allowing the traffic through.

Here's the problem: NAT can map the source port to whatever it wants. When B sends a datagram to the server, there's no guarantee that the source port seen by the server will be the same one that is used when B sends a datagram to A.

There are a lot of reasons why the NAT might change the port number, and a security conscious one will randomize just to prevent what you are trying to do. So while you may be able to make double punching (NAT to NAT) work sometimes, you cannot do so every time.

Seth Noble
  • 3,233
  • 19
  • 31
  • thanks, your summary is correct. However, from what I have read, well behaved NATs these days do behave consistently (they maintain the port number). Moreover, in my failure case, A and the server are the same - in other words, client A is running on the same public host as the server. The port number is maintained correctly (A receives data from the same B-port as the server) and data gets through to A ok. But A cannot send back to B (which is behind NAT). Moving server and client A to another public host works as expected. And with both A and B behind NAT, it works. Strange! – William Morris Mar 08 '12 at 02:32
  • Some NATs will preserve the port number... when they can. Consider two hosts behind the same NAT both sending out on port 12345. The first one will get 12345, but the second must be assigned a different number because 12345 is already taken on the public IP address. My point is that there will always be cases where the punch-out fails, even where it works most of the time. So its worth considering whether you need and can design a fallback scenario, such as relaying the data through the central host. Hopefully that will be rare enough to not be a burden. But it is necessary for reliability. – Seth Noble Mar 08 '12 at 15:27
1

So in summary, the client doesn't work on a particular host when the server is on the same host. Any suggestions for reasons for this behaviour

Could it be that the server sees clientA as being on 127.0.0.1 (or maybe a non-routable LAN address?) and not its public IP-address?

If clientB tries to contact clientA using the wrong address, it's obvious why the UDP-datagram doesn't get to the intended recipient.

or for ways I could investigate this further?

Some output from tcpdump from both the server (AKA clientA) and clientB would help a lot. You might want to use -i any and maybe -s 0.

stderr
  • 11
  • 1
  • 1
    Thanks for the suggestions. I checked the addresses and port numbers in the clients and they were correct. Unfortunately I don't have the necessary privileges on the server to run tcpdump. – William Morris Apr 06 '12 at 15:20
0
the client doesn't work on a particular host when the server is on the same host

In some corner cases, NATs only accept traffic from the target IP address:port used to punch the hole. Since it is not the one of the remote NAT-ed peer, they block the traffic from it. This could explain your issue.

Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453