How NAT Works A Deep Dive - cover image

How NAT Works: A Deep Dive

NAT - Network Address Translation - lets your entire home or office network share a single public IP address. It is the reason billions of devices can access the internet despite IPv4 having only 4.3 billion addresses for roughly 8 billion people and far more devices. NAT is practical, widely deployed, and fundamentally changes how network connections work.

Why NAT Exists

IPv4 uses 32-bit addresses, giving a theoretical maximum of 4,294,967,296 unique addresses. After reserving addresses for private networks, multicast, loopback, and other special purposes, the usable pool is closer to 3.7 billion. That was more than enough in 1981 when IPv4 was designed, but it is nowhere near enough for a world with smartphones, laptops, smart TVs, IoT sensors, and servers all needing addresses simultaneously.

NAT solves this by allowing private IP addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to be used on internal networks while sharing one or a few public addresses for internet access. Your home router has a single public IP assigned by your ISP, and all devices on your home network use private addresses that the router translates on the fly.

RFC 1918 defined the private address ranges in 1996. These addresses are not routable on the public internet - routers drop packets with private source or destination addresses. NAT handles the translation between private and public addresses at the network boundary.

PAT/NAPT - Port Address Translation

The most common form of NAT is PAT (Port Address Translation), also called NAPT (Network Address Port Translation) or sometimes "NAT overload." This is what your home router does.

PAT maps each outbound connection to a unique combination of the public IP address and a translated source port. When device 192.168.1.50 sends a packet from port 12345 to a web server, the router replaces the source IP (192.168.1.50) with its public IP (e.g., 203.0.113.1) and replaces the source port (12345) with a new port (e.g., 50001). The web server sees the request coming from 203.0.113.1:50001.

When the web server responds to 203.0.113.1:50001, the router looks up port 50001 in its translation table, finds the mapping back to 192.168.1.50:12345, and forwards the packet to the internal device with the original addressing restored.

Since port numbers are 16-bit (0-65535), a single public IP can theoretically support around 65,000 simultaneous connections. In practice, the limit is lower because some port ranges are reserved, but it is more than enough for a typical household.

sequenceDiagram
    participant D1 as Device 1 - 192.168.1.50
    participant D2 as Device 2 - 192.168.1.51
    participant NAT as NAT Router - Public 203.0.113.1
    participant WEB as Web Server - 93.184.216.34
    D1->>NAT: Src 192.168.1.50:12345 Dst 93.184.216.34:443
    NAT->>NAT: Translate - 192.168.1.50:12345 to 203.0.113.1:50001
    NAT->>WEB: Src 203.0.113.1:50001 Dst 93.184.216.34:443
    D2->>NAT: Src 192.168.1.51:54321 Dst 93.184.216.34:443
    NAT->>NAT: Translate - 192.168.1.51:54321 to 203.0.113.1:50002
    NAT->>WEB: Src 203.0.113.1:50002 Dst 93.184.216.34:443
    WEB->>NAT: Src 93.184.216.34:443 Dst 203.0.113.1:50001
    NAT->>NAT: Reverse translate - 50001 to 192.168.1.50:12345
    NAT->>D1: Src 93.184.216.34:443 Dst 192.168.1.50:12345
    WEB->>NAT: Src 93.184.216.34:443 Dst 203.0.113.1:50002
    NAT->>NAT: Reverse translate - 50002 to 192.168.1.51:54321
    NAT->>D2: Src 93.184.216.34:443 Dst 192.168.1.51:54321

Figure 1 - PAT translating two internal devices through one public IP using different port mappings

The Translation Table

The NAT translation table is the core data structure that makes everything work. It is a stateful mapping of internal (private IP:port) to external (public IP:port) for every active connection.

A typical entry looks like:

Internal            External            Destination         Protocol  Timeout
192.168.1.50:12345  203.0.113.1:50001  93.184.216.34:443   TCP       300s
192.168.1.51:54321  203.0.113.1:50002  93.184.216.34:443   TCP       300s
192.168.1.50:12346  203.0.113.1:50003  8.8.8.8:53          UDP       30s

The table is populated when outbound connections are initiated and entries are removed when connections close (TCP FIN/RST) or when the timeout expires (critical for UDP, which has no connection state).

This stateful tracking means NAT consumes memory proportional to the number of active connections. Devices that open many simultaneous connections (torrent clients, gaming servers, busy web servers) can exhaust the translation table, causing new connections to fail even when bandwidth is available.

Connection Initiation and Port Forwarding

NAT is inherently asymmetric. Outbound connections (internal to external) work seamlessly because the outbound packet creates the translation table entry. But inbound connections (external to internal) fail by default because there is no existing table entry to tell the router which internal device should receive the packet.

If someone on the internet sends a packet to 203.0.113.1:8080 and there is no mapping for port 8080 in the translation table, the router drops the packet. It has no way to know which internal device (if any) should receive it.

Port forwarding solves this by creating static entries in the translation table. You configure the router to always forward traffic arriving on a specific external port to a specific internal IP and port. For example: "Forward external port 8080 to 192.168.1.100:80." This allows external devices to initiate connections to internal servers.

UPnP (Universal Plug and Play) and NAT-PMP (NAT Port Mapping Protocol) allow applications to programmatically create port forwarding rules without manual configuration. Gaming consoles and P2P applications use these protocols to make themselves accessible from the internet. The security tradeoff is that any application on the network can open ports, which is why many security-conscious users disable UPnP.

NAT Types

Not all NAT implementations behave the same way. RFC 3489 originally defined four types based on how strictly the router filters incoming packets after an outbound mapping is created:

Full Cone NAT. Once a mapping exists (internal:port to external:port), any external host can send packets to the external port and they will be forwarded to the internal device. The least restrictive type.

Restricted Cone NAT. Only external hosts that the internal device has previously sent packets to can send packets back through the mapping. The external IP must match, but any port from that IP is accepted.

Port Restricted Cone NAT. Only the specific external IP:port combination that the internal device communicated with can send packets through the mapping. More restrictive than Restricted Cone.

Symmetric NAT. A new mapping is created for every unique destination. If the internal device sends packets to server A and server B, two different external ports are used. External responses must come from the exact destination IP:port that the mapping was created for. This is the most restrictive type.

graph TD
    subgraph "Full Cone"
        FC1[Internal 192.168.1.50:5000] -->|mapped to| FC2[External 203.0.113.1:50000]
        FC3[Any external host] -->|can reach| FC2
    end
    subgraph "Restricted Cone"
        RC1[Internal sends to Server A] -->|mapping created| RC2[External port 50001]
        RC3[Server A - any port] -->|allowed| RC2
        RC4[Server B] -->|blocked - never contacted| RC2
    end
    subgraph "Port Restricted Cone"
        PRC1[Internal sends to Server A port 443] -->|mapping created| PRC2[External port 50002]
        PRC3[Server A port 443] -->|allowed| PRC2
        PRC4[Server A port 80] -->|blocked - wrong port| PRC2
    end
    subgraph "Symmetric"
        SYM1[Internal to Server A] -->|mapped to| SYM2[External port 50003]
        SYM1B[Internal to Server B] -->|mapped to| SYM3[External port 50004]
        SYM4[Different mapping per destination] --> SYM5[Hardest for P2P]
    end

Figure 2 - The four NAT types ranked from least restrictive (Full Cone) to most restrictive (Symmetric)

Why NAT Breaks P2P

Peer-to-peer communication requires both sides to accept incoming connections. With NAT, neither side can reach the other directly because both are behind translation tables that only have entries for outbound connections.

STUN (Session Traversal Utilities for NAT) helps two peers discover their public IP:port mappings. Each peer sends a request to a STUN server, which responds with the external address it sees. The peers exchange this information through a signaling channel, then try to send packets directly to each other's public addresses. If both NATs are Cone-type, the outbound packets from each side create the necessary mappings and communication succeeds. This is called "hole punching."

Symmetric NAT defeats STUN. Because symmetric NAT creates a new mapping for each destination, the mapping created for the STUN server is different from the mapping that would be created for the peer. The external port the STUN server reports is not the port that the peer will see. Hole punching fails.

TURN (Traversal Using Relays around NAT) is the fallback. A relay server with a public IP address acts as an intermediary - both peers connect to the relay (outbound, which works through any NAT), and the relay forwards traffic between them. This always works but adds latency and requires relay server infrastructure.

WebRTC uses the ICE (Interactive Connectivity Establishment) framework, which tries direct connection first, falls back to STUN hole punching, and only uses TURN as a last resort.

Hairpin NAT

Hairpin NAT (also called NAT loopback or NAT reflection) handles a specific edge case: accessing your own public IP from inside the network.

Suppose you have a web server at 192.168.1.100 with port 80 forwarded from the public IP 203.0.113.1. When someone on the internet visits 203.0.113.1, port forwarding routes them to your server. But what happens when a device on your own network tries to access 203.0.113.1:80?

Without hairpin NAT, the packet goes to the router, the router recognizes its own public IP, and either drops the packet or routes it incorrectly. The internal device cannot reach the server using the public address.

With hairpin NAT, the router recognizes that the destination is a forwarded port, rewrites both the source and destination addresses, and delivers the packet to the internal server. The server sees the request as coming from the router's internal IP, responds to the router, and the router forwards the response back to the requesting device.

Not all consumer routers support hairpin NAT. If yours does not, internal devices must use the server's private IP (192.168.1.100) instead of the public address.

IPv6 Eliminates NAT

IPv6 uses 128-bit addresses, providing 3.4 x 10^38 unique addresses - enough to give a unique address to every atom on the surface of the Earth and still have addresses left over. With this abundance, NAT is unnecessary. Every device gets a globally routable address.

This simplifies the network stack (no translation tables, no port mapping, no hairpin issues) but shifts the security model. Without NAT hiding internal addresses, firewalls become the sole barrier between internal devices and the internet. The implicit protection NAT provided - blocking unsolicited inbound connections by default - must be explicitly configured in firewall rules.

The transition from IPv4 to IPv6 has been slow, with both protocols running in parallel on most networks. Understanding NAT remains essential because IPv4 and NAT will be with us for years to come.

Get the BLEShark Nano - $36.99+
Back to blog

Leave a comment