Network Address Translation (NAT)
In the previous chapter, we learned that connection tracking gives Linux memory. Instead of treating every packet independently, the kernel remembers network flows and their state.
This memory enables one of the most widely used networking technologies in the world: Network Address Translation (NAT).
Today, almost every network uses NAT in some form. Your home router uses it. Cloud providers use it. Kubernetes nodes use it. Virtualization platforms use it. Firewalls and gateways use it.
Despite its widespread use, NAT is often misunderstood. Many engineers think of it as simply "changing IP addresses." While that is technically true, it misses the bigger picture.
NAT is a mechanism that rewrites packet headers while preserving communication between two endpoints.
In this chapter, we'll learn why NAT exists, how it works, why it depends on connection tracking, and how Linux performs address translation.
Why NAT Exists
Imagine the Internet without NAT.
Every device would need its own globally unique public IP address.
Laptop Public IP
Phone Public IP
TV Public IP
Printer Public IP
Camera Public IP
That worked when the Internet was small.
As millions—and later billions—of devices came online, the available IPv4 address space became insufficient.
IPv4 provides approximately 4.3 billion addresses.
Although that sounds like a large number, many addresses are reserved, and the remaining addresses are far fewer than the number of internet-connected devices today.
The networking community needed a solution.
Two technologies emerged:
- IPv6, which dramatically increases the address space.
- NAT, which allows many devices to share fewer public addresses.
While IPv6 is the long-term solution, NAT remains one of the most common technologies in IPv4 networks.
Public and Private Addresses
To understand NAT, you first need to understand the difference between public and private IP addresses.
Public addresses are globally routable on the Internet.
Private addresses are not.
The most common private IPv4 ranges are:
| Network | CIDR |
|---|---|
| 10.0.0.0 | /8 |
| 172.16.0.0 | /12 |
| 192.168.0.0 | /16 |
If your laptop has the address:
192.168.1.50
that address only has meaning inside your local network.
Internet routers will not forward packets with that source address.
Therefore, before a packet leaves your home network, something must replace the private address with a public one.
That "something" is usually NAT.
What NAT Actually Does
At its core, NAT modifies packet headers.
Suppose your laptop sends:
Source : 192.168.1.20
Destination : 8.8.8.8
The packet cannot travel across the Internet with that private source address.
Before the packet leaves your router, Linux changes it:
Before NAT
Src: 192.168.1.20
Dst: 8.8.8.8
↓
After NAT
Src: 203.0.113.15
Dst: 8.8.8.8
Only the source address changed.
Everything else about the communication remains the same.
The destination server never sees the private address.
Instead, it believes the packet originated from:
203.0.113.15
This process is called translation because Linux translates one network address into another.
NAT Is Transparent
One of NAT's most useful properties is transparency.
Neither the application nor the remote server knows that translation occurred.
The application simply calls:
connect()
The server simply receives packets.
Neither side explicitly requests NAT.
The kernel performs translation while forwarding packets.
This transparency explains why NAT is so widely deployed. Applications usually require no modification.
Types of NAT
Although NAT is often discussed as a single technology, there are several forms.
The two most important are:
- Source NAT (SNAT)
- Destination NAT (DNAT)
Another common form is Port Address Translation (PAT), often called masquerading.
Source NAT (SNAT)
Source NAT changes the source address of outgoing packets.
Original packet:
Src: 192.168.1.20
Dst: 8.8.8.8
After translation:
Src: 203.0.113.15
Dst: 8.8.8.8
The destination remains unchanged.
This is the type of NAT used by most home routers.
Thousands of internal devices can share a single public address.
Typical Uses of SNAT
SNAT is commonly used for:
- Home networks
- Enterprise gateways
- Cloud virtual machines
- Kubernetes worker nodes
- Virtual machines accessing external networks
Whenever private hosts need internet access, SNAT is usually involved.
Destination NAT (DNAT)
Destination NAT changes the destination address instead.
Imagine a packet arriving from the Internet:
Src: 198.51.100.20
Dst: 203.0.113.15
Linux rewrites the destination:
Src: 198.51.100.20
Dst: 192.168.1.10
The packet is then forwarded to the internal server.
DNAT is commonly used for:
- Port forwarding
- Reverse proxies
- Load balancers
- Publishing internal services
Port Address Translation (PAT)
What happens if hundreds of internal devices all use one public IP?
Changing only the IP address is not enough.
Consider two laptops:
Laptop A
192.168.1.20:53000
Laptop B
192.168.1.30:53000
Both connect to the same website.
If Linux translated only the IP address:
203.0.113.15:53000
203.0.113.15:53000
the replies would become ambiguous.
Linux solves this by translating ports as well.
Before
192.168.1.20:53000
↓
After
203.0.113.15:41001
Another connection becomes:
192.168.1.30:53000
↓
203.0.113.15:41002
Now every flow is unique.
This technique is called Port Address Translation (PAT).
Many Linux systems refer to this as masquerading, although masquerading is actually a specific implementation of source NAT that automatically uses the outgoing interface's address.
Why Connection Tracking Is Required
A common question is:
If Linux changes the source address, how does it know where to send the reply?
Suppose the outgoing packet becomes:
203.0.113.15:41001
Later the server replies:
Dst: 203.0.113.15:41001
How does Linux know that this reply actually belongs to:
192.168.1.20:53000
The answer is connection tracking.
When the first packet leaves the machine, conntrack creates an entry similar to:
Original
192.168.1.20:53000
↓
8.8.8.8:443
Translated
203.0.113.15:41001
↓
8.8.8.8:443
When the reply returns, Linux performs a lookup in the conntrack table.
The stored translation tells the kernel exactly:
- which internal machine originated the flow,
- which original source port was used,
- and how to restore the packet before delivery.
Without this state information, NAT would only work for the first outgoing packet.
The return traffic would have nowhere to go.
Following a Packet Through NAT
Let's follow a complete packet exchange.
Laptop
192.168.1.20
↓
Linux Router
Public IP:
203.0.113.15
↓
Internet
The laptop sends:
192.168.1.20:53000
↓
8.8.8.8:443
The router performs source NAT:
203.0.113.15:41001
↓
8.8.8.8:443
The server replies:
8.8.8.8:443
↓
203.0.113.15:41001
The router consults connection tracking.
It restores:
8.8.8.8:443
↓
192.168.1.20:53000
The laptop receives exactly what it expects.
Neither endpoint knows translation occurred.
Where NAT Happens
NAT is part of the netfilter framework.
Conceptually, translation happens at two different stages of the packet path.
Destination NAT
Destination NAT happens before the kernel makes its forwarding or local-delivery decision.
Why?
Because after changing the destination address, Linux must route the packet using its new destination.
Source NAT
Source NAT happens just before the packet leaves the machine.
At this point, Linux already knows:
- which interface will transmit the packet,
- which route it will use,
- and which source address should be translated.
This ordering keeps routing decisions consistent while allowing the packet to leave with the correct public address.
In later chapters, you'll see exactly how iptables and nftables attach NAT rules to these stages.
Common NAT Scenarios
Home Router
Many private devices share one public address.
Laptop
Phone
TV
Game Console
↓
Router (NAT)
↓
Internet
Cloud Virtual Machine
Private cloud instances access the Internet through a public gateway performing source NAT.
Port Forwarding
External users access an internal web server through destination NAT.
Internet
↓
Public IP
↓
Internal Web Server
Container Platforms
Container runtimes frequently use NAT so containers can communicate outside their private network.
Although the exact implementation differs between platforms, the underlying concept is the same.
Limitations of NAT
Although NAT solved the IPv4 address shortage, it also introduced complexity.
Some drawbacks include:
- breaks true end-to-end addressing,
- makes troubleshooting more difficult,
- complicates peer-to-peer communication,
- requires additional kernel state,
- increases dependence on connection tracking.
For these reasons, IPv6 was designed so that widespread NAT would not be necessary.
Even so, NAT remains essential in today's IPv4 networks.
Observe NAT on a Home Network
If your Linux machine is behind a typical home router, compare your local IP address with your public IP.
First, inspect your local address:
ip addr show
Then determine your public address using any public IP lookup service from a web browser.
You will notice that they are different.
This difference exists because your router is performing source NAT before packets reach the Internet.
Observe Connection Tracking During NAT
Generate some outbound traffic:
curl https://example.com
Then inspect the connection tracking table:
sudo conntrack -L
Look for an entry matching your connection.
Although you have not configured any NAT rules yourself, this demonstrates that connection tracking is maintaining flow state that NAT depends upon.
Compare Private and Public Routes
Inspect your routing table:
ip route
Notice that your machine routes traffic toward a gateway using private addresses.
The gateway—not your host—is responsible for translating packets before they enter the public Internet.
This reinforces an important idea:
Routing decides where packets go. NAT changes how they appear while they travel.
NAT Is Not Routing
Routing and NAT are closely related, but they solve different problems.
Routing answers:
Where should this packet go?
NAT answers:
Should this packet's addresses or ports be rewritten before it continues?
A packet may be routed without NAT.
A packet may also undergo NAT while following the same route.
They are independent operations that happen at different stages of packet processing.
Summary
- NAT rewrites packet headers while preserving communication between endpoints.
- It was introduced primarily to allow many devices to share a limited number of IPv4 addresses.
- Source NAT modifies source addresses; destination NAT modifies destination addresses.
- Port Address Translation (PAT) allows many simultaneous connections to share a single public IP address by translating ports.
- Connection tracking is essential because it remembers how translated packets map back to their original flows.
- Source NAT and destination NAT occur at different points in the packet-processing pipeline.
- NAT is widely used in home networks, cloud platforms, virtualization systems, and container environments.
- NAT is not routing; routing determines the path, while NAT rewrites packet headers along that path.
In the next chapter, we will finally begin configuring packet-processing policy directly by learning iptables, the traditional userspace interface for the Linux netfilter framework.