Blog

NAT, egress, and why your whole office has one IP address

Forty people, one address on the allowlist, and a firewall rule that works. What NAT is actually doing, why egress is a direction rather than a technology, and the availability trap hiding in an IP allowlist.

Everyone in the office reaches the production servers. Those servers allow exactly one IP address. Forty laptops, one entry on the allowlist, and it works.

That is NAT, and once you can see it clearly a lot of other things stop being mysterious — why your home router has two addresses, why an AWS NAT Gateway is billed the way it is, and why an IP allowlist quietly becomes an availability risk.

First: egress is a direction, not a product

“Our office IP is connected via egress” gets said a lot, and it blurs two separate things.

Egress just means traffic leaving a network. Ingress is traffic arriving. That is the whole definition. It is a direction, like north — not a technology you install.

NAT is the mechanism that rewrites addresses as traffic crosses a boundary. They get conflated because the moment egress traffic crosses that boundary, NAT is what makes it work.

So a dedicated line with a static IP gives you a stable egress identity — every packet leaving your office presents the same source address, no matter which laptop sent it. That is what the server’s firewall rule matches on.

What the router actually does

Your laptop has a private address — 192.168.0.20 or similar. That address is not unique in the world; millions of networks use it simultaneously. It cannot be routed on the internet, and that is deliberate.

PRIVATE — 192.168.0.0/24 laptop 192.168.0.20 phone 192.168.0.31 desktop 192.168.0.44 not unique in the world, not routable on the internet ROUTER LAN 192.168.0.1 WAN 203.0.113.7 rewrites source address and source port TWO addresses, one box The internet sees 203.0.113.7 for every device above

TRANSLATION TABLE — how replies find their way back 192.168.0.20:51431 → 203.0.113.7:62104 → 142.250.185.78:443 192.168.0.31:49882 → 203.0.113.7:62105 → 142.250.185.78:443

The port number is what makes this work. Two devices contacting the same server are told apart by the translated source port, not by address.

When your laptop opens a connection, the router:

  1. Rewrites the source address from 192.168.0.20 to its own public address
  2. Rewrites the source port to something it has allocated
  3. Records that mapping in a translation table

The reply comes back to 203.0.113.7:62104, the router looks up the entry, rewrites the destination back to 192.168.0.20:51431, and delivers it. The laptop never knows.

That port rewriting is why this is properly called PAT — Port Address Translation, or NAT overload. Address translation alone would let one internal host use the public address at a time. Ports are what let hundreds share it.

Your router has two addresses, which is the detail people usually miss: a private one facing the LAN (your default gateway) and a public one facing the ISP. That is what makes it a boundary rather than just another host.

NAT is stateful, and that has consequences

The translation table is state. It has entries, timeouts, and a maximum size — and three practical consequences follow.

Inbound connections have nowhere to go. A packet arriving unsolicited matches no table entry, so the router does not know which internal host to deliver it to and drops it. This is why port forwarding exists: a static, pre-made table entry.

It looks like a firewall but is not one. The inbound protection is a side effect of not knowing where to route, not a policy decision. It inspects nothing, logs nothing, and applies no rules. Plenty of networks have been compromised by traffic that a host requested — NAT is entirely happy to deliver the reply.

The table can fill. Which brings us to the cloud version.

The AWS NAT Gateway version

Same mechanism, managed service. Instances in private subnets have no public address, so their outbound traffic goes through a NAT Gateway sitting in a public subnet, which presents its Elastic IP as the source.

Two things worth knowing before you deploy one:

Use one per availability zone, not one shared. A single shared gateway quietly undoes multi-AZ: lose the zone holding it and the surviving zone also loses outbound connectivity. Paying for the second one is the difference between multi-AZ and the appearance of it.

There is a connection ceiling. A NAT Gateway supports roughly 55,000 simultaneous connections to a single destination IP and port. A fleet all calling the same external API can hit it. It surfaces as the ErrorPortAllocation CloudWatch metric — worth an alarm, and a direct consequence of the translation table being finite.

Back to the office, and the trap

So: one static IP, one allowlist entry, forty people working. Clean.

Now follow the failure through. The primary ISP link goes down. The office fails over to the reserve connection — which is the entire reason it exists. Everybody’s traffic now leaves from a different, unregistered address.

Every person in that office is locked out of every managed server, at exactly the moment something has already gone wrong.

And the fix requires reaching the management system to add the new address — which you now cannot reach from the office.

Worth being precise about why the reserve link fails, because the obvious explanation is usually the wrong one. People assume it is because the reserve address is dynamic. Often it is simply that it is a different address and nobody added it. Two distinct problems:

ProblemFixable?
Reserve IP is different and not allowlistedYes — register it in advance
Reserve IP is dynamicNo, not by IP allowlisting at all

Test which one you have: fail over to the reserve link, run curl -4 ifconfig.me, and do it again next week. The same answer twice means it is static and you simply need to register it.

Pre-register the reserve link’s egress address alongside the primary. It costs two extra allow rules and removes a single point of failure that only appears during an incident. This is the cheapest availability fix I know of, and almost nobody has done it.

Where the model runs out

IP allowlisting works well for a fixed office with a static line. It fails for home and remote workers, for two reasons.

Home connections are usually dynamic — the address changes and the allowlist goes stale.

Worse, many are behind CGNAT (carrier-grade NAT), where the ISP runs a second layer of NAT above your router and hundreds of customers share one public address. Allowlisting that address would admit every one of them.

Check in two steps: read the WAN address from your router’s admin page, then run curl -4 ifconfig.me. If they differ and the router shows something in 100.64.0.0/10 — a range reserved specifically for CGNAT — you are behind it. Port forwarding cannot work no matter what you configure, because you do not own the public address.

This is the structural reason the industry is moving from “which address is this?” to “which identity is this?” — VPNs with certificate-based auth, SSO-gated access proxies, workload identity between services. An address is a location, and locations change. The allowlist model was never really about the address; it was using the address as a stand-in for “someone in our office”, and that proxy eventually breaks.

Worth trying once

curl -4 ifconfig.me     # IPv4 — your router's public address, after NAT
curl -6 ifconfig.me     # IPv6 — often your DEVICE's own global address

If the second one returns something, look at what it means. IPv6 has enough addresses that NAT is generally unnecessary, so your laptop holds a globally unique address and the website sees the real thing. Seeing both side by side is the clearest possible demonstration that NAT is a workaround for IPv4 scarcity, not a design goal — and a reminder that the inbound protection you get from it was always a side effect.

References

← All posts