I'm trying to connect directly (without 3rd party server) my computer to a friend's computer. We are both behind a ISP router, and would like (as a challenge!) to connect without modifying the router configuration.

As suggested here and here, we tried both TCP hole punching:

myself$ nc -p 7777 public-ip-friend 8888
friend$ nc -p 8888 public-ip-myself 7777

and UDP hole punching:

myself$ nc -u -p 7777 public-ip-friend 8888
friend$ nc -u -p 8888 public-ip-myself 7777

but none of them worked.

How to solve this?

Note: VPS (not behind a NAT) <--> my home computer (still behind router) works with the same method.

  • How are you synchronizing the requests? Do you see anything over tcpdump, e.g. RST packets? – cherdt Feb 2 '18 at 16:52
  • Where should I do tcpdump @cherdt? On each one's computer? On the router (I don't know if it's possible to do that?)? What tcpdump command would you do in this example? – Basj Feb 3 '18 at 12:05
  • pwnat uses an interesting technique of setting up a TCP connection in a client-server style where the server is behind a NAT and doesn't require a third-party host to set up the connection as it uses ICMP messages. – Torin Feb 5 '18 at 10:29
  • @TorinCarey do you confirm that this is the reason why it didn't work? How does pwnat works then to guess that srcip 7777 is rewritten to 55183 (in my example) by the NAT? – Basj Feb 5 '18 at 11:03
  • @Basj AFAIK your answer is spot on. As for pwnat, the main objective is for the server to learn the IP address and port of a connecting client. The server periodically sends an ICMP echo to a non-existent address, which the client creates an ICMP packet looking like a response to this echo in the eyes of the router, containing the client's IP address. – Torin Feb 5 '18 at 11:11

Sometimes the commands given in the question will work, but sometimes it won't.

Here is the reason.

Let's say:

  • my computer IP on my local network:
  • my home public IP:
  • my friend's public IP:

When doing this on my computer:

myself$ nc -u -p 7777 8888

we have, before NAT translation:

srcip          srcport         destip            destport   7777       8888

but after the home router NAT translation we have:

srcip          srcport         destip            destport   55183(*)     8888

i.e. the source IP is rewritten by the NAT but also the source port.

So a "hole" will indeed be created in my home firewall (accepting traffic from my friend, but for port 55183, and not for port 7777.

This explains why it fails when my friend does:

friend$ nc -u -p 8888 7777

Note (*): In some cases the router might keep srcport=7777 instead of rewriting it to a random port like 55183. It this case, the solution given in the question might work. But this is random behaviour!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.