Network Address Translation

Network Address Translation, sometimes called Network Address Translator (NAT), was first described in RFC 1631 in 1994. The authors of that document were trying to solve the then imminent problem of running out of IPv4 addresses. They proposed a simple but brilliant solution. Their idea was to allow devices on the inside of a network to use the standard pool of unregistered IP addresses that are currently defined in RFC 1918. Then the router or firewall at the boundary between the internal private network and the external public network would have software that rewrites the internal IP addresses in every packet, replacing them with valid registered addresses.

There are four kinds of addresses: inside local, inside global, outside local, and outside global. Inside and outside pretty much depend on where you're standing, if you're just connecting two private networks. But if you are connecting a private network to the public Internet, then the Internet is outside. A local address is generally the private address, while the global address is the globally unique public address.

To help make these terms more clear, suppose you are connecting a network that uses RFC 1918 private addresses to the public Internet. Inside your network you have private addresses, such as 192.168.1.0/24. These are the inside local addresses. NAT will translate these addresses to globally unique registered addresses. These are the inside global addresses. The addresses on the public Internet are outside global. These external network addresses are all registered in this case, so there is no need to translate them, but if you did need to, you would translate an outside global to an outside local address.

To put this another way, the address that internal devices uses to communicate with other internal devices is the inside local address. The address that an internal device uses to communicate with external devices is the outside local address. The address that external devices use to communicate with internal devices is the inside global address. And external devices communicate with one another using outside global addresses.

NAT makes it possible to have a huge internal network with thousands of local addresses represented by a handful of global addresses or perhaps a single global address. This is why NAT is often credited with alleviating the address shortage problem. But it only really solves this problem if most people who use it have more local than global addresses.

In practice, there is a huge range of possibilities. You can map local addresses uniquely to individual global addresses. You can share one global address among several local addresses. You can allocate global addresses from a pool as they are requested. Or you can have a single global address and map all local addresses to this one address. And you can even define a combination of these different alternatives.

When a device sends a packet out from the private to the public network, the translator replaces the local source address with a registered address, and then routes the packet. For an inbound packet, the translator replaces the global address with the local address and routes the packet into the internal network. The translator has a much more difficult job with inbound packets than outbound. This is because it has to figure out which internal device to send the packet to. Since many internal devices could be using the same global address, the translator has to keep a state table of all of the devices that send or receive packets to or from the external network.

Suppose, for example, that two internal users are both using HTTP to view information on the public network. The translator has to be able to separate out which packets are intended for which internal device. It isn't sufficient to just look at the external device's IP address because both of these users could be looking at the same web page. They would both wind up with severely scrambled screens, if the translator couldn't tell which packets to send to which internal user.

This particular example is made somewhat easier by the fact that HTTP uses TCP. Since it is a connection-based protocol, there is a well-defined session initiation and termination that helps the translator to sort out the inbound flows, since these two users will have different TCP source ports. However, for UDP and ICMP packets, it can be more difficult. For example, if two internal users both PING the same external site at the same time, the translator has to assume that it will receive the responses in the same order that they were sent. Fortunately, this rarely presents real problems in production networks. But it is worth remembering that running NAT requires the router to keep track of a lot of state information that routers don't usually care about. Further, because IP addresses are included in both IP and TCP checksums, the translator must recalculate these checksum values. So NAT always consumes more CPU and memory resources on the router or firewall that it runs on, and this amount increases rapidly with both the number of packets and the number of different flows.

The other important thing to remember about NAT is that some protocols include IP address information in the payload of the packet as well as in the IP header. For example, the ubiquitous FTP protocol has a PORT command that contains an IP address encoded in ASCII. In this case, the FTP protocol is well understood and NAT implementations can look out for this. But it is relatively easy to see that in other less popular protocols, there can be strange problems. And, if a server happens to run FTP on a nonstandard TCP port, you must tell NAT about the change so that it can rewrite the payload addresses appropriately.

SNMP also includes IP addresses in packet payloads. For example, IP address information is part of the standard interface MIB because it is an important piece of information about the interface. However, rewriting addresses in the payloads of SNMP packets is a much more difficult problem than for FTP because the address could be anywhere in the payload. Further, it is possible for the addresses in the payload to refer to different interfaces than the address in the header. And, to make the problem more difficult still, there is no common standard format for IP addresses in SNMP packets. They are sometimes transmitted as dotted decimal ASCII strings, as packed hex bytes, or a variety of other formats, depending on the specific MIB. Consequently, Cisco routers do not attempt to rewrite IP addresses in the payloads of SNMP packets.

We have also seen custom built applications that make life very hard for NAT by encoding IP addresses and port numbers in the data segment of a packet, and then using this information to attempt to open new connections. It can be difficult to get NAT to work in cases like this. Often the only workaround is to encapsulate the ill-behaved application in a tunnel.