Different types of NAT and hole punching for peer to peer connections

Disclaimer

This article is unfinished and I’m still learning about NAT hole punching. In particular the mentions of port remapping may be incorrect. I’m investigating how to create a test lab setup so I can validate everything on this page. I’ll include the code snippets here once that validation is complete.

Types of NAT

Formal NAT definitions can be found in RFC 3489 section 5.

Types of NAT defined in the RFC:

  • Full cone
  • Restricted cone
  • Port restricted cone
  • Symmetric

Assumptions

In all of these examples we assume that the hosts behind each type of NAT have contacted a STUN server and the STUN server knows their public IP addresses and their remapped outbound ports. These values, along with their private IPs and original outbound ports for completeness, for all examples are:

Host A

  • Private IP address: 192.168.1.5
  • Outbound port: 9999
  • Public IP address: 78.22.53.7
  • Remapped outbound port: 43825

Host B

  • Private IP address: 10.0.4.3
  • Outbound port: 9999
  • Public IP address: 66.5.12.33
  • Remapped outbound port: 23432

Symmetric NAT

Symmetric NAT is the most problematic and requires the router to allocate ports in a predictable way so the next value can be “guessed” by the destination.

There is a paper that discusses this called “Symmetric NAT Traversal using STUN” but requires significantly more effort to get it working so we won’t cover it here.

Full cone NAT

Full cone is the easiest NAT to work with. Host A simply sends UDP packets to host B’s public IP address and remapped outbound port. Host B sends UDP packets to host A’s public IP address and remapped outbound port for the return path.

When performing full cone NAT host A’s router makes a mapping between 192.168.1.5:9999 and 78.22.53.7:43825. All packets send to 78.22.53.7:43825 go to 192.168.1.5:9999 regardless of where they originated.

Restricted cone NAT

Restricted cone NAT requires an initial step to get packets flowing from one host to another. It requires that host A has sent at least one packet, on any port, to host B’s public IP address.

Let’s assume host A is waiting for a packet from host B. If host B sends a packet to host A’s public IP address and remapped outbound port it will be dropped. However, once host A sends a single packet to host B’s public IP address, on any port, its restricted cone NAT will allow host B to send packets to it.

When working behind restricted cone NAT each host should be resilient against the initial packets being lost and should try multiple times to connect. This makes sure the restricted cone NAT unblocks the hosts so they can establish communication.

The flow would look like this (diagram generated by sequencediagram.org):

image

Sequence diagram source:

title Restricted cone NAT sequence

participant Host A
participant Network A router
participant Network B router
participant Host B
Host A->Network A router
Host A->Network B router:Packet A1 (port 23432) [dropped]
Host B->Network A router:Packet B1 (port 43825) [dropped]
Host A->Host B:Packet A2 (port 23432)
Host B->Host A:Packet B2 (port 43825)

Port restricted cone NAT

Port restricted cone NAT is slightly stricter than restricted cone NAT.

Let’s assume host A is waiting for a packet from host B. If host B sends a packet to host A’s public IP address and remapped outbound port it will be dropped. However, once host A sends a single packet to host B’s public IP address, on port 9999 in our case, its restricted cone NAT will allow host B to send packets to it.

The flow would look like this (diagram generated by sequencediagram.org):

image

Sequence diagram source:

title Port restricted cone NAT sequence

participant Host A
participant Network A router
participant Network B router
participant Host B
Host A->Network A router
Host A->Network B router:Packet A1 (port 9999) [dropped]
Host B->Network A router:Packet B1 (port 9999) [dropped]
Host A->Host B:Packet A2 (port 23432)
Host B->Host A:Packet B2 (port 43825)