Skip to content

UDP hole punching

We may not need any UDP hole punching code considering how the current code is set up?

  • Peer A will connect to root peers, which will provide the info (IP:Port, Public Key) of other peers (Peer B)
  • Peer A will directly connect to those other peers. Local binding is on the same port/socket where it receives data. Therefore reaching out keeps the UDP port for the response in. Peer A connects to Peer B.
  • Peer B takes the incoming connection details (public key, IP:Port), stores it in its peer list and shares it etc.

In this case we already have a UDP hole punching by default?

We'll send every 10 seconds a ping/pong to make sure it remains open, but otherwise there should not be any problems?


  • edited February 25

    I see what you mean here, and you've identified that some clients can communicate without the need for UDP hole-punching, as you've pointed out they already have a hole in the firewall to communicate with the network.

    The trouble here is that the network is not just one peer, but is made of many different peers. Punching a hole in the firewall to one single IP address does not necessarily allow all traffic from all IP addresses to pass through the firewall. In my experience the NAT on a home router will only allow UDP packets originating from hosts which were previously sent UDP packets in the last minute or so. It will create a temporary "firewall rule" in its routing table which maps packets destined for the router's public IP address on a particular UDP port from a particular node (node A) to a client behind the firewall (node B) which it has seen send traffic on that UDP port to node A recently.

    This allows only point-to-point communication; the hole in the firewall is not universally traversable.

    The particulars here can be worked out with due effort and do not affect many parts of a PeerNet MVP. But it's enough to say that being "connected to the network" behind a NAT will involve a hole-punch for each client involved in a network event, e.g. neighbor peering, direct file transfer, network query etc.

  • Makes sense. So in this case it means that both peers need to simultaneously try to connect to each other.

    That should not be tricky; when Peer C sends back a list of peers (including Peer B) to Peer A, that Peer C will send a special message to Peer B letting it know about it. In turn, Peer B will try to establish a connection to Peer A to make sure its NAT will allow it.

    In this case it makes sense to create a new message command that informs a Peer once its information has been shared (and triggers it to send a dummy packet to that peer).

    Another thing to figure out is how to automate the check whether peers have their port forwarded already, in which case the hole punching is not needed. Once thing that we could include in the protocol is the listening local port number, and peers can check if it is equal to the public one. If it is, it's a strong indicator that the port is forwarded or the public IP directly assigned (mostly servers).

  • Here are potential implementations/scenarios to add it to the protocol:

    #1: Add "Internal Port" to the packet structure. The receiver can check if the port matches with the port from the actual connection. If it does not, it indicates there's a NAT (or other port mapping) and flags the peer as such.

    #2: Each peer itself could check if its port is firewalled or NATted and provide a flag.

    When exchanging peer lists there must be either,

    • a flag whether the peer is directly accessible or needs UDP hole punching or
    • passing on the internal port number and the receiving peer will make the determination itself.

  • This should do the trick - a new Traverse message. This is going to be included in the upcoming Whitepaper 0.8.

Sign In or Register to comment.