How NAT works
How network address translation lets many devices share one public IPv4 address, how NATs map and filter traffic, and how STUN, TURN and ICE still connect two devices that are both behind one.
The internet was designed so that every device has its own IP address and any device can send packets to any other. But IPv4 has only about 4.3 billion addresses, not enough for every device that wants to be online. Network address translation (NAT) is the workaround that lets a whole home or office, or even many customers of an internet provider, share a single public IPv4 address.
NAT works so well for ordinary browsing that most people never notice it. But it changes what the internet can do: a device behind NAT can easily reach out, yet it cannot simply be reached. This article explains how translation works, how NATs behave, and how protocols such as STUN, TURN and ICE still connect two devices that are both behind one, which is what video calls and many games need. All addresses in the examples are reserved for documentation (RFC 5737).
A short-term solution that stayed
NAT was described in RFC 1631 in May 1994 as a stopgap: “Until the long-term solutions are ready an easy way to hold down the demand for IP addresses is through address reuse.” The long-term solution was a successor to IPv4 with larger addresses; the IETF chose its design in January 1995, and it became IPv6 (RFC 1752). The same RFC 1631 already named the price: NAT “has the disadvantage of taking away the end-to-end significance of an IP address, and making up for it with increased state in the network.”
Its successor, RFC 3022 (2001), describes two forms of what it calls traditional NAT:
- Basic NAT translates only IP addresses, mapping a group of private addresses to a group of public ones.
- Network Address Port Translation (NAPT) also translates TCP and UDP port numbers, so that many devices can share one public address. This is what a typical home router does, and what the word NAT usually means today.
The devices behind it use the private address ranges of RFC 1918, such as 192.168.0.0/16,
which anyone may use inside a network but which are not routed on the public internet.
How translation works
Suppose a laptop with the private address 192.168.1.20 opens a connection to a web server at
198.51.100.10, port 443. The home router’s public address is 203.0.113.7.
- The laptop sends a packet from
192.168.1.20:51000to198.51.100.10:443. - The router picks a free public port, say 49170, and records a mapping in its table:
192.168.1.20:51000 ↔ 203.0.113.7:49170. - It rewrites the packet’s source to
203.0.113.7:49170and sends it on. The server only ever sees the router’s public address. - The server replies to
203.0.113.7:49170. The router finds the mapping, rewrites the destination back to192.168.1.20:51000, and delivers the packet to the laptop.
Rewriting addresses means more than changing a few bytes. The TCP and UDP checksums also cover the IP addresses, so the router must update them as well. And protocols that write IP addresses inside their data, such as FTP, need extra help from the NAT, an application level gateway that rewrites those addresses too (RFC 3022).
A mapping exists only because a device inside sent something out. A packet that arrives from the internet and matches no mapping has nowhere to go, which is why devices behind NAT cannot be reached from outside unless the router is told to forward a port to them.
How NATs behave
NATs are built by many vendors, and for years they behaved in different ways. RFC 4787 (for UDP) and RFC 5382 (for TCP) gave the behaviors names and set requirements, later updated by RFC 7857. Two questions describe a NAT best.
Mapping: does a device keep the same public port for every destination?
- Endpoint-independent mapping: one internal address and port always get the same public address and port, whatever destination they send to.
- Address-dependent mapping: the same public port is reused only for the same destination address.
- Address and port-dependent mapping: each destination address and port gets its own mapping.
RFC 4787 and RFC 5382 require endpoint-independent mapping. Without it, an address that a device learns from one server is useless for talking to anyone else, and the techniques described below fail.
Filtering: which incoming packets does a NAT let through to a mapping?
- Endpoint-independent filtering: any packet sent to the mapped public address and port.
- Address-dependent filtering: only packets from addresses the device has sent to.
- Address and port-dependent filtering: only packets from addresses and ports the device has sent to.
Here RFC 4787 leaves a choice: endpoint-independent filtering if letting applications work matters most, and address-dependent filtering if stricter filtering does.
Timeouts. A NAT cannot keep mappings forever, so it removes those that stay idle. For UDP, a mapping must not expire in less than two minutes, and RFC 4787 recommends a default of five minutes or more. For an established TCP connection, the idle timeout must be at least 2 hours and 4 minutes (RFC 5382). Applications that keep connections open with little traffic therefore send small keepalive messages, so that their mappings do not quietly disappear.
Hairpinning. When two devices behind the same NAT talk to each other using their public addresses, the NAT must pass the traffic back inside. RFC 4787 requires NATs to support this.
Carrier-grade NAT
With IPv4 addresses running out, some internet providers no longer give each customer a public
address. Instead, a carrier-grade NAT (CGN) in the provider’s network translates the traffic of
many customers into a shared pool of public addresses. If the customer’s own router also does NAT,
packets pass through two layers of translation. RFC 6598 reserved the range 100.64.0.0/10 as the
shared address space between the two.
RFC 6888 sets requirements for these large NATs. A CGN must be able to limit how many public ports each customer gets, so that one customer cannot use them all, and it must offer customers a way to control their mappings, preferably the Port Control Protocol (PCP, RFC 6887), which lets a device ask a NAT to forward incoming traffic to it. As RFC 6888 notes, CGNs “introduce substantial limitations in communications between subscribers and with the rest of the Internet”: some applications need substantial changes, and some may not work at all.
NAT is not a firewall
Because unknown incoming packets are dropped, NAT is often seen as a security feature. RFC 4864 puts it plainly: “The act of translating address bits within the header does not provide security in itself.” The protection people associate with NAT comes from keeping state, admitting only traffic that belongs to a connection started from inside, and that is what a stateful firewall does without rewriting any addresses. RFC 4864 adds that IPv6 “was designed with the intention of making NAT unnecessary”: with enough addresses, every device can have its own, behind a firewall.
Connecting two devices behind NAT
A video call ideally sends audio and video directly between the two devices, without a detour through a server. If both are behind NAT, neither can simply send to the other: each only knows its own private address, and neither NAT has a mapping that lets the other side in. Three protocols solve this together.
STUN: what does the outside world see?
STUN (Session Traversal Utilities for NAT, RFC 8489) answers one question: which public address and port does my NAT use for me? A device sends a STUN Binding request to a STUN server on the public internet, by default on port 3478 (5349 for STUN over TLS or DTLS). The request passes through the NAT, which rewrites its source, so the server sees the device’s public address and port, its reflexive address, and sends it back in the response.
The server does not copy the address as it is. It sends it in an attribute called
XOR-MAPPED-ADDRESS, combined with a fixed value, the magic cookie 0x2112A442, using XOR.
For the address in our example:
port 49170 = 0xC012 XOR 0x2112 = 0xE100
address 203.0.113.7 = 0xCB007107 XOR 0x2112A442 = 0xEA12D545
The reason is a lesson in how NATs behave: some NATs searched the data of packets for a binary copy of their own public address and “helpfully” rewrote it, which broke STUN. The scrambled value no longer looks like the address, so it arrives untouched, and the client simply applies the same XOR again to recover it.
STUN is a tool, not a complete solution. It also serves to check connectivity and as a keepalive that keeps mappings open.
Hole punching
Knowing their public addresses, two devices can try to connect directly with hole punching (RFC 5128). Both first register with a rendezvous server that both can reach, which tells each of them the other’s public address and port. Then both send packets to each other at about the same time.
Each outgoing packet creates a mapping and a filter entry in the sender’s own NAT that admits packets from the other side. The first packets may be dropped by the other NAT, which has not yet seen any outgoing traffic, but once both sides have sent, packets pass in both directions and the rendezvous server is no longer involved. Hole punching relies on endpoint-independent mapping: if a NAT gives a new public port for every destination, the port learned through the server is not the one used toward the peer, and the attempt fails.
TURN: relaying when nothing else works
When no direct path can be found, the devices need a relay. TURN (Traversal Using Relays around NAT, RFC 8656) lets a device ask a TURN server for an allocation: an address and port on the server, the relayed address, that peers can send to. The server forwards everything between the peers and the device.
A TURN server does not relay for just anyone. The client must authenticate, the allocation lasts 10 minutes by default unless it is refreshed, and the server only accepts packets from peers for which the client has created a permission, which expires after 5 minutes unless refreshed, imitating the filtering of a NAT. Relaying works almost always, but every packet crosses the server, which needs a lot of bandwidth, so TURN is the last resort.
ICE: trying everything, in the best order
ICE (Interactive Connectivity Establishment, RFC 8445) combines these pieces. Each device gathers candidates, addresses it might be reachable at:
| Candidate | Where it comes from | Recommended type preference |
|---|---|---|
| Host | An address of the device’s own network interface | 126 |
| Peer-reflexive | An address discovered during the checks themselves | 110 |
| Server-reflexive | The public address seen by a STUN or TURN server | 100 |
| Relayed | An address allocated on a TURN server | 0 |
The two devices exchange their candidate lists through a signaling channel, for example a server that sets up the call. Each device then pairs its candidates with the other side’s and tests the pairs with STUN requests, the connectivity checks, starting with the highest priority. The preferences favor direct paths over paths through NATs and relays, so a relay is used only if nothing better works. Finally, one device, the controlling agent, nominates a working pair, and the data flows over it.
Key points
- NAT lets many devices share one public IPv4 address by rewriting addresses and ports and remembering each mapping. It began in 1994 as a stopgap and is now everywhere.
- Devices behind NAT can reach out, but cannot be reached unless a mapping exists; unused mappings time out, so long-lived connections need keepalives.
- RFC 4787 and RFC 5382 require endpoint-independent mapping, which keeps the same public port for every destination and makes traversal possible.
- Carrier-grade NAT adds a second layer in the provider’s network, using
100.64.0.0/10. - NAT is not a firewall: the protection comes from its state, which a firewall also provides.
- STUN reveals a device’s public address, hole punching opens a direct path, TURN relays when that fails, and ICE tries all candidate pairs in order of preference.
Sources
- Traditional IP Network Address Translator (Traditional NAT) (RFC 3022)P. Srisuresh, K. Egevang, RFC Editor, 2001Accessed
- The IP Network Address Translator (NAT) (RFC 1631)K. Egevang, P. Francis, RFC Editor, 1994Accessed
- The Recommendation for the IP Next Generation Protocol (RFC 1752)S. Bradner, A. Mankin, RFC Editor, 1995Accessed
- Network Address Translation (NAT) Behavioral Requirements for Unicast UDP (RFC 4787)F. Audet, C. Jennings, RFC Editor, 2007Accessed
- NAT Behavioral Requirements for TCP (RFC 5382)S. Guha, K. Biswas, B. Ford, S. Sivakumar, P. Srisuresh, RFC Editor, 2008Accessed
- Updates to Network Address Translation (NAT) Behavioral Requirements (RFC 7857)R. Penno, S. Perreault, M. Boucadair, S. Sivakumar, K. Naito, RFC Editor, 2016Accessed
- Common Requirements for Carrier-Grade NATs (CGNs) (RFC 6888)S. Perreault, I. Yamagata, S. Miyakawa, A. Nakagawa, H. Ashida, RFC Editor, 2013Accessed
- IANA-Reserved IPv4 Prefix for Shared Address Space (RFC 6598)J. Weil, V. Kuarsingh, C. Donley, C. Liljenstolpe, M. Azinger, RFC Editor, 2012Accessed
- Address Allocation for Private Internets (RFC 1918)Y. Rekhter, B. Moskowitz, D. Karrenberg, G. J. de Groot, E. Lear, RFC Editor, 1996Accessed
- IPv4 Address Blocks Reserved for Documentation (RFC 5737)J. Arkko, M. Cotton, L. Vegoda, RFC Editor, 2010Accessed
- Local Network Protection for IPv6 (RFC 4864)G. Van de Velde, T. Hain, R. Droms, B. Carpenter, E. Klein, RFC Editor, 2007Accessed
- Port Control Protocol (PCP) (RFC 6887)D. Wing, S. Cheshire, M. Boucadair, R. Penno, P. Selkirk, RFC Editor, 2013Accessed
- Session Traversal Utilities for NAT (STUN) (RFC 8489)M. Petit-Huguenin, G. Salgueiro, J. Rosenberg, D. Wing, R. Mahy, P. Matthews, RFC Editor, 2020Accessed
- State of Peer-to-Peer (P2P) Communication across Network Address Translators (NATs) (RFC 5128)P. Srisuresh, B. Ford, D. Kegel, RFC Editor, 2008Accessed
- Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN) (RFC 8656)T. Reddy, A. Johnston, P. Matthews, J. Rosenberg, RFC Editor, 2020Accessed
- Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal (RFC 8445)A. Keranen, C. Holmberg, J. Rosenberg, RFC Editor, 2018Accessed