Network Address Translation (NAT) and port forwarding are foundational techniques that allow private networks to communicate with the public internet. On Linux systems, these functions are implemented in the kernel via the netfilter framework and configured using iptables.
This article provides a packet-level view of how Linux performs NAT, how SNAT and DNAT differ, and how port forwarding is actually enforced in the forwarding path.
🔁 IP Forwarding: The Prerequisite #
By default, a Linux system behaves as an endpoint host. Packets not destined for the local machine are dropped. To act as a router, the kernel must be explicitly instructed to forward packets between interfaces.
Temporary enablement (until reboot):
sysctl -w net.ipv4.ip_forward=1
Permanent enablement:
# /etc/sysctl.conf
net.ipv4.ip_forward = 1
Apply the configuration:
sysctl -p
Without IP forwarding enabled, NAT rules may match, but packets will never traverse from one interface to another.
🔄 Source NAT (SNAT) and Masquerading #
Source NAT (SNAT) modifies the source IP address of outbound packets. This is typically used when hosts on a private LAN need to access the public internet.
When an internal packet exits the router, its private source address is replaced with a public-facing address. Return traffic is automatically de-translated using connection tracking.
SNAT vs MASQUERADE #
-
SNAT
- Used when the external IP address is static
- More efficient, as the kernel does not need to re-evaluate the interface address per packet
- Example:
iptables -t nat -A POSTROUTING -o eth0 \
-j SNAT --to-source 203.0.113.10
-
MASQUERADE
- Designed for dynamic IP environments (DHCP, PPPoE)
- The source IP is derived from the outgoing interface
- Slightly higher overhead
- Example:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Both operate in the POSTROUTING chain, after the routing decision has been made.
🎯 Destination NAT (DNAT) and Port Forwarding #
Destination NAT (DNAT) rewrites the destination IP address of inbound packets. This is the mechanism behind traditional port forwarding.
DNAT allows external clients to reach services hosted on private internal systems.
Packet Flow Overview #
- Packet arrives on the public interface
- Destination IP/port matches a DNAT rule
- Kernel rewrites the destination to an internal host
- Packet is routed and forwarded to the LAN
Example: Forward public TCP port 80 to an internal web server.
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
-j DNAT --to-destination 192.168.1.10:80
Forwarding Must Be Explicitly Allowed #
DNAT alone is not sufficient. The packet must also be permitted by the FORWARD chain in the filter table:
iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 80 -j ACCEPT
If the FORWARD chain drops the packet, the NAT translation still occurs—but the packet is discarded afterward.
📊 SNAT vs DNAT at a Glance #
| Aspect | SNAT | DNAT |
|---|---|---|
| Address Modified | Source IP | Destination IP |
| Traffic Direction | Outbound | Inbound |
| Iptables Chain | POSTROUTING | PREROUTING |
| Common Use Case | LAN internet access | Hosting internal services |
🧪 Troubleshooting NAT on Linux #
When NAT or port forwarding does not behave as expected, the following checks are essential:
-
Verify IP Forwarding
cat /proc/sys/net/ipv4/ip_forwardThe value must be
1. -
Inspect NAT Rules and Counters
iptables -t nat -L -n -vPacket counters help confirm whether rules are being matched.
-
Check Forwarding Policy
iptables -L FORWARD -nA default DROP policy is a common cause of silent failures.
-
Trace Packet Flow Use
tcpdumpon both external and internal interfaces to verify ingress and egress behavior.
🧠 Architectural Perspective #
Linux NAT is not a separate subsystem but an extension of packet filtering combined with connection tracking. NAT rules rewrite headers, while the conntrack engine ensures bidirectional consistency across flows.
Understanding where SNAT and DNAT occur in the packet lifecycle—PREROUTING, routing, FORWARD, POSTROUTING—is the key to designing reliable and secure Linux-based routers and firewalls.