Ok, I'm going to get this out of the way first: Network Address Translation (NAT) is a kludge to work around the fact that we don't have enough IPv4 addresses to go around. NAT is not a security feature.
I'll go into a bit of background on how NAT works - look at the diagram. As you can see, we've got a workstation with a site-local scope (RFC1918) address of 10.0.0.1 connected to the internet by a router which will do NAT. The router has the site-local scope address of 10.0.0.254 and a global scope address of 220.127.116.11.
Now, the workstation wants to connect to TCP port 80 (HTTP) on the server which has a global scope address of 18.104.22.168. Since the workstation's address is only valid locally, it cannot be used to talk to the server (the routers on the internet wouldn't know where to send data for a site-local scope address). So, the workstation sends a data packet with an arbitrary source port (this is how TCP works - we'll pick port 2000 for this example) and the rest of the packet filled in with known values as follows:
|Action||Start a new connection|
As the packet passes through the router, it sees that it is a new connection and records these four parameters in an internal database. This is known as connection tracking. The router then changes the source address of the packet to 22.214.171.124 (its own global scope address) and may also modify the source port number (we'll pick port 6789 for this example). The new address and port number is also noted in the internal database. The router transmits the packet onto the internet with the packet now looking like this:
|Action||Start a new connection|
When this modified packet arrives at the server, a reply is sent:
This packet gets back to the router which looks up the source and destination addresses and ports in its connection tracking database. The entry in the database also contains the source address and port of The original "start new connection" packet so it uses these values to modify the destination address and port of this "connection started" packet before sending it on to the workstation. So the reply packet the workstation finally sees looks like:
This looks to the workstation as if it was routed to the server and back again without any modification and the rest of the connection proceeds in a similar way except the router keeps the entry in the connection tracking table so the translated address and port stay the same throughout the whole connection. Once the "connection closed" packet is seen by the router at the end of the connection the entry is removed from the connection tracking database.
Note: The above description wasn't an entirely accurate description of the way a TCP handshake works - TCP actually uses a slightly more complex three-way handshake but that doesn't really change the way that NAT works so I'm simplifying things a little.
Ok, so a lot of people look at this and say "well since all the machines on our LAN have got site-local scope addresses, we can use NAT as a security device since it lets us route out to the internet but people can't route back to site-local scope addresses." Whilest in general terms this can be true, you shouldn't rely on it and the use of NAT in this exercise is completely pointless in any case since you already have a good way of securing the network in any case.
The use of NAT for security relies on the assumption that someone on the other side of your router actually can't route data to your site-local network. Back to the diagram, and imagine that the server is very close (in terms of logical network size) to your router - maybe it's actually on the same internet service provider (ISP).
If your ISP has its internal routers set up to send traffic with a destination address of 10.0.0.1 to your router, the server can now happilly make random connections to the workstation since anything from the server destined to 10.0.0.1 will be sent out to the ISP who will then send it to your router. No NAT will be needed and so the security you think you had is gone.
Admittedly it's pretty unlikely that the ISP will have their routers misconfigured like this. However in the world of security, making assumptions is a very bad thing; especially when your assumptions are about the configuration of someone else's systems that you have absolutely no control over.
Remember back when I talked about how NAT works I mentioned that the router needs to keep a connection tracking database in order to translate the addresses on the reply packets? Well this is the solution.
You can maintain a connection tracking database without modifying the packets at all. Under Linux this is handled by the "ip_conntrack" kernel module and the packets can be filtered based on this connection tracking information using the "state" iptables module.
So the router maintains a database of current connections so that traffic is always allowed through for them, and you can tell it to filter all new connections made from the internet whilest allowing all new connections made from inside the local network. This means that noone can make a connection from the internet to one of your workstations, even though they can route to its address.
Well you can still use NAT if you need to, and you can add in the proper stateful filtering described aobve to avoid the security problem. The whole point of this article is to explain that NAT in itself isn't a security feature - any router that is doing NAT will be doing connection tracking anyway (except in a few specialist cases). So NAT gives you no security benefit on top of that.
If you don't need to use NAT then it's better to avoid it - i.e. if you have a single PC plugged into the internet then there is no need to use NAT at all. NAT causes headaches as soon as you want to do anything more interesting than just surfing the web:
A number of (IMHO badly designed) protocols pass information about ports and IP addresses within the data part of the packets. For example, when doing FTP running in port mode, the client asks the server to make a connection back to a specific port on the client. Obviously the server will end up getting asked to make a connection to a site-local scope address which isn't going to work. A number of internet telephony protocols such as SIP and H.323 suffer the same problems.
Yes, there are problems but these affect NAT in exactly the same way since NAT relies on connection tracking too.
If both ends of the TCP connection are disconnected from the network while the TCP connection is open, the connection termination packets will never be sent. This means the router doesn't know that the connection in its database is nolonger valid. The work around for this is that connection tracking systems keep a note of how long a TCP connection has been idle and decide it's dead after a certain length of idle time. This may be anything from a few seconds (a really bad idea) up to hours or days (much better). The connection tracker can't know if it's nuking a valid session that's just been idle too long or a legitimately dead session. Many applications can send regular keep-alive packets to avoid having their connections terminated so this is less of an issue these days.
Protocols such as UDP, 6-in-4, ESP, AH, etc are connectionless, so the connection tracker cannot know when it's safe to remove the connection from its database - the only solution is a short timeout and hope you don't nuke something that's still in use.
As I mentioned at the start of this article, NAT is a kludge to work around the lack of IPv4 address space. IPv4 has served us well in the 25 years since it was invented but unfortunately it's getting a bit dated. The replacement for IPv4 is known as IPv6 but it looks like we'll be stuck with IPv4 for a while.
IPv6 takeup is currently quite slow despite the ease with which it can be set up these days. There are very few ISPs who provide native IPv6 networking, but anyone with a global scope IPv4 address can (and should) IPv6 enable their network uuing the 6to4 tunnelling protocol. Under Fedora Core 3 it's as easy as setting "IPV6_DEFAULTDEV=tun6to4", "IPV6INIT=yes" and "IPV6TO4INIT=yes" in the network configuration. IPv4 can run concurrently with IPv6 so there is no danger of breaking the network.
Even Windows XP Service Pack 2 ships with an IPv6 stack although at the time of writing most of the services are still stuck with IPv4.
IPv4 gives us an address space of 4 billion addresses whilest IPv6 provides a whopping 340 undecillion addresses (3.4×1038). Anyone who uses the 6to4 tunnelling protocol to provide an IPv6 internet connection automatically gets a /48 global scope network providing you with 1.2 septillion (1.2×1024) globally routable addresses for your local network.
Once IPv6 has replace IPv4 there will be no more need for NAT and all the problems it causes.
Would you like to submit a comment about this article?