NAT is not evil

I'm sick and tired of IPv6 haters saying that the removal of NAT in IPv6 just makes it "less secure", because everything has a public IP address now. And I'm sick and tired of the people who say that the only purpose of NAT is to conserve IP addresses. But fundamentally, NAT is a connection tracking mechanism.

In my understanding of NAT, there are "real" and "virtual" IP addresses. "Real" addresses are assigned to a host, whereas "Virtual" addresses are handled by an intermediate router.

  • SNAT converts a "real" source IP address to a "virtual" IP address. When you connect to the Internet over IPv4, your "real" IP address of your computer (e.g. 192.168.1.2) is converted to a "virtual" public IP address, such as 198.51.100.48, and is converted back to your "real" IP address in the reply.
  • On the other hand, DNAT converts a "virtual" destination IP address to a "real" IP address. When you use port forwarding, your ISP's public ("virtual") IP address is converted to the private, real IP address you defined for your forwarded service, and the source IP is converted back to your "virtual" IP address on reply.
  • Virtual IP addresses are valid on a given network segment whenever there is a static route (including the default route) in that network segment to the IP address, and where such route leads to the device which defines the virtual IP address. This path can be as short as internal to the client host itself, in the case of nat rules in the INPUT and OUTPUT chains.
  • "Real" IP address ranges reserve .0 for network and .255 for broadcast. On the other hand, virtual IP ranges do not have such restrictions.

The following iptables rule defines an outbound "virtual" address that is used whenever an outbound Internet connection is made through the specified outbound interface:

iptables -t nat -A POSTROUTING -o [outbound network interface] -j SNAT --to [virtual IP address]

On the other hand, the following rule defines an inbound "virtual" address that is used whenever an inbound Internet connection is made to an internal server:

iptables -t nat -A PREROUTING -i [inbound network interface] -d [virtual IP address] -j DNAT --to [real IP address]

The most important aspect of this is that it can be defined on the port level:

iptables -t nat -A PREROUTING -i eth0 -d 192.0.2.1 -p tcp --dport 80 -j DNAT --to [IP address of web server 1]
iptables -t nat -A PREROUTING -i eth0 -d 192.0.2.2 -p tcp --dport 80 -j DNAT --to [IP address of web server 2]
iptables -t nat -A PREROUTING -i eth0 -d 192.0.2.2 -p tcp --dport 25 -j DNAT --to [IP address of mail server 1]

Here, mail server 1 and web server 2 share the same public IP address for their services, but the services may be processed on different physical hosts.

Virtual IP addresses may also manifest themselves in local routing (ip route add local 192.0.2.0/24 dev lo), described in Snippets:Nginx geo local server address

A networking plan can opt for all IPv4 addresses being virtual, defined by a set of iptables rules rather than by the networking infrastructure.

Many business Internet plans offer 1, 5, or 13 IP addresses. These are 2^n-3 figures, where n is a positive integer, because with conventional networking architecture, .0, .1, and the broadcast address are reserved. However, in our setup, these are not, since the IP addresses are all virtual. We can use 4, 8, or 16 addresses instead of 1, 5, or 13 without any loss of efficiency during subnetting.

In IPv4, addresses are scarce. Organizations may only have around one or two IP addresses, making the requirement for NAT necessary.

In IPv6, this is not the case. Addresses are much more plentiful compared to IPv4. No more NAT is necessary. In fact, organizations can be assigned several /64's and even up to /48.

See also