Skip to main content

NAT: How Many Devices Share One Public Address

Step a packet through a home router to see how NAT rewrites addresses and ports, what it breaks, how hole punching and NAT-T work around it, and why it is not security.

Does NAT help VPNs, or do VPNs help NAT? Neither, really. They are separate tools that meet in a few specific places. NAT lets many devices share one public address. A VPN builds an encrypted tunnel between two points. This page explains NAT, including the one place where it clashes directly with a VPN protocol. The tunnel itself is explained in how a VPN works.

Why NAT exists

An IPv4 address is 32 bits, so there are about 4.3 billion of them. That is fewer than the number of phones, laptops, TVs and servers that want to be online, and the addresses ran out years ago.

So a home or small office usually gets a single public address from its provider. Every device inside uses a private address instead, from ranges set aside for that purpose by RFC 1918, such as 192.168.0.0/16 and 10.0.0.0/8. Private addresses are never routed on the public internet, which means every home can reuse the same ones. Your laptop and your neighbor's laptop can both be 192.168.1.10.

The router in the middle makes this work. It is the only device with a public address, and it rewrites packets on their way through so that, from outside, all traffic seems to come from the router itself. That rewriting is Network Address Translation.

IPv6 has enough addresses to give every device its own, which removes most of the need for NAT. Much of the internet still runs only on IPv4, so NAT is still everywhere.

How NAT rewrites a packet

The figure uses a home network 192.168.1.0/24 with a laptop, a phone and a TV behind a router whose public address is 203.0.113.7. Step through it and watch the packet card and the table beneath the scene.

NAT packet journey: Plain NAT

Step a packet through a home router and watch it rewrite addresses and keep a translation table.

Step 1 / 6

The Laptop sends a packet to a web server from its private address 192.168.1.10.

Home LAN

packet here
  • 192.168.1.0/24
  • Laptop 192.168.1.10
  • Phone 192.168.1.11
  • TV 192.168.1.12

Router

  • public 203.0.113.7

Internet

  • server 198.51.100.20:443
PacketTCP
src192.168.1.10:51000
dst198.51.100.20:443

Router translation table

insideoutsideremote
no rows yet
Authored illustration. Addresses come from documentation ranges; ports and timings are illustrative, not a packet capture.

The laptop at 192.168.1.10 opens a connection to a web server at 198.51.100.20:443, using source port 51000. On the way out, the router rewrites the source address and the source port: 192.168.1.10:51000 becomes 203.0.113.7:40001. Many routers keep the original source port when it is free and change it only when two inside devices would clash; this router picks a new one, which makes the rewrite easy to see. It records the mapping as a row in its translation table with three columns:

  • inside: the private address and port, 192.168.1.10:51000
  • outside: the public address and port the router chose, 203.0.113.7:40001
  • remote: who the packet went to, 198.51.100.20:443

The server sees a packet from 203.0.113.7:40001 and replies there. When the reply arrives, the router looks for a row whose outside endpoint matches the reply's destination and whose remote endpoint matches the reply's source. It finds the laptop's row, rewrites the destination back to 192.168.1.10:51000 and forwards it. The laptop never sees the rewriting.

The port is what makes sharing possible. Pick the phone with the Sending device buttons: it also uses source port 51000, talking to the same server. If the router only rewrote addresses, both replies would arrive at 203.0.113.7:51000 and it could not tell them apart. Instead it gives the phone a different outside port, 40002, so each reply matches exactly one row.

What NAT breaks

The table is the whole trick, and also the whole problem. A packet from outside gets in only if a row already expects it, and rows are created only by packets going out. Anything that does not fit that pattern needs help.

Unsolicited inbound packets

The laptop already has a connection open, so the router holds one row: outside 203.0.113.7:40001, remote 198.51.100.20:443. The server's reply matches and passes.

NAT packet journey: Unsolicited inbound

Step a packet through a home router and watch it rewrite addresses and keep a translation table.

Step 1 / 4

The laptop has already opened a connection to the server, so the router holds one row for it.

Home LAN

  • 192.168.1.0/24
  • Laptop 192.168.1.10
  • Phone 192.168.1.11
  • TV 192.168.1.12

Router

packet here
  • public 203.0.113.7

Internet

  • server 198.51.100.20:443
  • stranger 192.0.2.50

No data packet on this step.

Router translation table

insideoutsideremote
192.168.1.10:51000203.0.113.7:40001198.51.100.20:443
Authored illustration. Addresses come from documentation ranges; ports and timings are illustrative, not a packet capture.

Now a stranger at 192.0.2.50 sends a packet to that same public port, 203.0.113.7:40001. The port is in use, but no row lists 192.0.2.50 as the remote, so the router has nowhere to send the packet and drops it. A packet to a port with no row at all is dropped the same way.

This is why you cannot reach a machine at home from outside just by knowing your public address. Nothing inside asked for that packet, so there is no row for it. The manual fix is port forwarding: you tell the router to send everything arriving on a chosen public port to one inside device.

Hole punching

Two people who are each behind their own NAT have a harder problem. Neither router will accept the first packet from the other side, because neither has a row for it. Peer-to-peer apps solve this by getting both sides to send outward first, so each router creates a row before the other side's packet arrives.

NAT packet journey: Hole punching

Step a packet through a home router and watch it rewrite addresses and keep a translation table.

Step 1 / 7

Peer A at home A contacts the rendezvous server, and its router opens a mapping to that server.

Home A

  • peer A 192.168.1.10

Router A

packet here
  • public 203.0.113.7

Rendezvous server

  • 192.0.2.10:3478

Router B

  • public 198.51.100.33

Home B

  • peer B 192.168.1.20
PacketUDP
srcwas 192.168.1.10:41641now 203.0.113.7:40001
dst192.0.2.10:3478

router A

insideoutsideremote
192.168.1.10:41641203.0.113.7:40001192.0.2.10:3478

router B

insideoutsideremote
no rows yet
Authored illustration. Addresses come from documentation ranges; ports and timings are illustrative, not a packet capture.

The figure has two homes. Peer A is 192.168.1.10 behind router A (203.0.113.7). Peer B is 192.168.1.20 behind router B (198.51.100.33). Both use port 41641, and both are on 192.168.1.0/24, which is fine because private ranges are reused everywhere.

  1. Both peers contact a rendezvous server at 192.0.2.10:3478. Each router creates a row for that conversation, and the server learns each peer's public address and port: A is at 203.0.113.7:40001, B is at 198.51.100.33:40001.
  2. The server tells each peer the other's public address and port.
  3. Peer A sends straight to B. Router A keeps the same outside port it already picked for 192.168.1.10:41641, and adds a row that expects B. Router B has no row for A yet, so it drops the packet.
  4. Peer B sends straight to A. Router B now gets a row that expects A, and router A already expects B, so this packet passes.
  5. Both routers now hold a row for the other side. Packets flow directly, and the rendezvous server is out of the path.

This is how Tailscale and other WireGuard meshes connect two laptops directly, and how video calls avoid routing every frame through a server. It does not always work: some routers pick a new outside port for every destination. The public address stays the same, but the port the rendezvous server saw is not the one the router uses toward the peer, so the peer aims at the wrong port. When hole punching fails, traffic goes through a relay server instead, which works but adds a hop.

IPsec and NAT traversal

This is the place where NAT and a VPN protocol collide directly. IPsec VPNs start with a key exchange called IKE, which runs over UDP, and then carry the actual traffic in ESP packets. ESP sits directly on IP. It has no ports at all.

NAT packet journey: IPsec vs NAT

Step a packet through a home router and watch it rewrite addresses and keep a translation table.

NAT traversal
Step 1 / 6

The laptop and the VPN gateway run IKE to agree on keys, then switch to ESP, which has no ports at all.

Home LAN

  • 192.168.1.0/24
  • Laptop 192.168.1.10
  • Phone 192.168.1.11

Router

  • public 203.0.113.7

VPN gateway

packet here
  • 198.51.100.80

No data packet on this step.

Router translation table

insideoutsideremote
no rows yet
Authored illustration. Addresses come from documentation ranges; ports and timings are illustrative, not a packet capture.

With NAT-T off, the laptop's ESP traffic to a VPN gateway at 198.51.100.80 still works. The router has no port to rewrite, so it swaps the source address and remembers the address pair: laptop, gateway. Many home routers do exactly this and call it "IPsec passthrough". With one device using the gateway, the address pair is enough to route replies.

Then the phone connects to the same gateway. Its row has the same public address and the same remote address as the laptop's. When the gateway replies, the reply matches both rows. A router that tracks only the address pair cannot tell which device it belongs to, so one of the connections breaks. There is no port to tell them apart.

IPsec's other protocol, AH, breaks even with one device, because its integrity check covers the IP addresses that NAT rewrites, so any rewritten packet looks tampered with.

NAT traversal (NAT-T) fixes ESP. During the IKE handshake, both ends compare the addresses and ports they see on the packets with the ones the other side says it sent from. If they do not match, a NAT is in the path, and both ends switch to wrapping ESP inside UDP on port 4500. Now each device's traffic has a port, and the router treats it like any other UDP flow: the laptop gets outside port 40001, the phone gets 40002, and each reply matches exactly one row. Turn NAT-T on in the figure to see both connections work.

NAT is not security

Because a NAT drops unsolicited inbound packets, people often treat it as a firewall. It is not one. The router drops those packets because it has no row telling it where they go, not because a rule says they are unwanted. That is a side effect of address sharing. It does not stop anything a port forward lets in, and it does not stop a compromised device inside from opening a connection out.

A firewall is the actual policy: rules that say which traffic is allowed in and out, whether or not NAT is involved. Most home routers run both, which is why they are easy to confuse.

NAT also does nothing to the contents of a packet. It rewrites addresses and ports in the headers and leaves the payload exactly as readable, or as encrypted, as it already was. A VPN adds the two things NAT never provides: encryption, so nobody between you and the VPN server can read the traffic, and authentication, so each end knows who it is talking to.

NAT and VPNs

Back to the opening question. NAT and VPNs meet in three places:

  • Internet-exit VPN servers often use NAT on the way out. In a typical consumer VPN, the server rewrites your private tunnel address to its public exit address, much as a home router does. The VPN page covers this along with the tunnel itself; other VPNs can route traffic without NAT.
  • NAT-T lets IPsec cross a NAT. ESP has no ports, so IKE detects the NAT and wraps ESP in UDP 4500.
  • Hole punching lets peer-to-peer VPNs connect directly. Mesh VPNs built on WireGuard use it to open a direct path between two devices that are each behind a NAT, and fall back to a relay when it fails.

So NAT does not help VPNs, and VPNs do not help NAT. NAT gets in the way of some VPN traffic, VPN protocols have learned to work around it, and VPN servers use NAT for the same reason everyone else does.

If you found this explanation helpful, consider sharing it with others.

Mastodon