20

Can anyone give an example of a UDP Hole Punching ?

Actually, I want to write a chat program with which people can chat when they know each other's IP. But both the machines will be behind a firewalled router. So, I need to punch a hole in order to communicate.

I would like a function such that on calling the function, a hole would have been punched and future communications would move on easily - if that's not too much to ask for :)

  • 1
    Possible dupe of: http://stackoverflow.com/questions/8523330/programming-p2p-application/8524609#8524609 – selbie Jan 18 '12 at 10:55
  • There is no simple function that you can just call that will solve all your NAT traversal problems. See the link above for a longer discussion on NAT traversal and P2P. – selbie Jan 18 '12 at 11:12

2 Answers2

27

Short Answer: it can't be done reliably.

Long Answer:

"Hole Punching" refers to triggering automatic NAT rules of a router in order to allow inbound traffic. When you send a UDP packet out, the router (usually) creates a temporary rule mapping your source address and port to the destination address and port, and vice versa. UDP packets returning from the destination address and port (and no other) are passed through to the original source address and port (and no other). This rule will timeout after some minutes of inactivity.

Getting this to work when both end-points are behind NATs or firewalls would require that both end-points send packets to each-other at about the same time. This means that both sides need to know each-other's public IP addresses and port numbers and need to communicate this to each-other by some other means.

There is no way for a program to directly determine its own public IP address if it is behind an NAT (it will only see its private address, such as 192.168.x.x). But since you are assuming that the humans involved know each-other's IP addresses, those humans can just type in the other's address.

But the real catch is that there is also no way for a program to directly determine what port number the router is using on the public side. Your program may be bound to 12345 on the local machine, but the router can map that to almost any port on the public side. (Imagine two computers on your local network both sending out from port 12345, obviously the router will have to map one of them to a different number.) So even though you and the humans may know what local port number you are bound to, there's no way to know what port number the router will show to the world.

Seth Noble
  • 3,233
  • 19
  • 31
  • 14
    Seth - You outline the problems of NAT traversal very well, but you make it seem like it is an impossible problem to solve. But in reality, a combination of STUN, TURN, ICE, and a reliable signaling service make P2P connectivity very reliable. Putting it another way - servers on the public internet help nodes get directly connected. – selbie Jan 18 '12 at 10:58
  • 1
    You are correct that the problem largely goes away *if* you can reliably reach a third-party relay. @c.adhityaa did not actually say direct communication was a requirement, so I should have asked. Also, if you relax the reliability requirement, then having both peers simultaneously send each-other a few datagrams a second apart may work much of the time. I'm used to dealing with corporate firewalls, so I may be overly pessimistic about what the network will allow. – Seth Noble Jan 18 '12 at 22:10
8

Lidgren's networking library has this functionality built-in. After adding the library to your application, you would instantiate a NetServer, have two NetClients connect, and call NetServer.Introduce().

Link to Lidgren: https://github.com/lidgren/lidgren-network-gen3

mturilli
  • 47
  • 4
Jason
  • 6,878
  • 5
  • 41
  • 55