Articles - NAT Isn't a Security Feature

Section Index:

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.

How does NAT work?

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

Now, the workstation wants to connect to TCP port 80 (HTTP) on the
server which has a global scope address of 5.6.7.8. 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:

Source address

10.0.0.1

Source port

2000

Destination address

5.6.7.8

Destination port

80

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 1.2.3.4
(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:

Source address

1.2.3.4

Source port

6789

Destination address

5.6.7.8

Destination port

80

Action

Start a new connection

When this modified packet arrives at the server, a reply is sent:

Source address

5.6.7.8

Source port

80

Destination address

1.2.3.4

Destination port

6789

Action

Connection started

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:

Source address

5.6.7.8

Source port

80

Destination address

10.0.0.1

Destination port

2000

Action

Connection started

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.

Doesn't that make NAT a great security tool too?

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.

So what's the solution?

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.

Why shouldn't I use NAT as well?

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.

Are there any problems with using connection tracking?

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.

What about the future?

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.