Thomas Vale
Thomas Vale

Reputation: 45

Failing to perform TCP hole punching using STUN

I have two hosts A and B. They're in different networks, behind different NATs and ISPs. I'm trying to set up a p2p connection between them by using hole punching. I use a STUN server to obtain mapped IP addresses and ports for both A and B. It goes on like this:

For A:

.\stunclient.exe --mode behavior stunserver.stunprotocol.org 3478
Binding test: success
Local address: 192.168.0.110:54709
Mapped address: 186.233.160.141:28769
Behavior test: success
Nat behavior: Endpoint Independent Mapping

For B:

.\stunclient.exe --mode behavior stunserver.stunprotocol.org 3478
Binding test: success
Local address: 192.168.3.1:57015
Mapped address: 45.70.35.52:12870
Behavior test: success
Nat behavior: Endpoint Independent Mapping

Then I try to perform the TCP hole punching technique (using netcat) by executing these two lines simultaneously and multiple times on A and B:

On A:

ncat -p 54709 45.70.35.52 12870
Ncat: TIMEOUT.

On B:

ncat -p 57015 186.233.160.141 28769
Ncat: TIMEOUT.

I always get "Ncat: Timeout" as output (not immediatelly, it takes some time), however, I could make a direct connection between A and B via UDP hole punching by running the following commands three times:

On A:

ncat -u -p 54709 45.70.35.52 12870

On B:

ncat -u -p 57015 186.233.160.141 28769

So the problem is TCP hole punching isn't working. Any ideas why?

Upvotes: 0

Views: 922

Answers (1)

selbie
selbie

Reputation: 104514

Many issues that might be making this a challenge.

First, stunclient defaults to UDP whereas ncat defaults to TCP. So your first issue is that you aren't passing the flag (-u on most systems) to tell ncat to run as UDP. Or, you can try running stunclient in tcp mode. (e.g. stunclient --protocol tcp stunserver.stunclient.org), but TCP NAT traversal is much less reliable than UDP - especially with rudimentary command line tools )

I don't understand how your output above can have Host A and Host B behind the same NAT, yet both machines appear to have the same local IP address, using the same local port, but printing the same local ip address 192.168.3.3. How is this a thing? Is this just a typo? Or is one machine a VM host of the other and they are sharing an IP?

The behavior you are trying to achieve, having two hosts behind the same NAT connect via the public ip address is called hairpinning. This relies on the NAT to be smart enough to see that an outbound packet is really meant for a host behind the router itself and to loop it back through its own routing table instead of going out on the WAN adapter. Not all NATs support hairpinning. So what you have to do is try connecting through to both the local and remote ip addresses.

Also, try to avoid picking hardcoded ports like 20000. Let stunclient.exe pick a randomly available port for you. (i.e. don't specify --localport parameter). Then when you issue the ncat command, use the local port it picked to connect to the remote mapped port of the other ip address.

Hypothetical usage:

Host A

stunclient.exe stunserver.stunprotocol.org
Binding test: success
Local address: 192.168.1.2:1111
Mapped address: 45.70.35.52:2222

Host B

stunclient.exe stunserver.stunprotocol.org
Binding test: success
Local address: 192.168.1.3:3333
Mapped address: 45.70.35.52:4444

Address candidates passed from A to B: {45.70.35.52:2222, 192.168.1.2:1111}

Address candidates passed from B to A: {45.70.35.52:4444, 192.168.1.3:3333}

Host A then runs these command in parallel. But oops, ncat may not allow sharing the socket port between two running programs. Look at the documentation to see if the SO_REUSEADDR flag is exposed implicitly as a command line param. It may do this implicitly.

ncat -u -p 1111 45.70.35.52 4444
ncat -u -p 1111 192.168.1.3:3333

Host B then does this in two separate consoles:

ncat -u -p 3333 45.70.35.52 2222
ncat -u -p 3333 192.168.1.2:1111

In other words, try all 4 combinations of A to B and B to A.

I was about to mention making sure you don't have address dependent mapping by running the behavior test. (i.e. "symmetric NAT"). Symmetric NATs make p2p connectivity very difficult for the connection to "go direct". But you've got endpoint independent, which is good.

Upvotes: 0

Related Questions