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:

NetworkCIDR
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.