NAT

NAT is a confusing technology. Many people have difficulties understanding it. Myself included. This causes problems during configuration and troubleshooting. This post is for me to put everything in order and help myself understand NAT.

Terminology

When using NAT you work with several terms:

  • Inside Local
  • Inside Global
  • Outside Local
  • Outside Global

Inside Local

The inside local address is an address on the inside of your network. Most of the time these are RFC1918 addresses and are not routable on the internet. For example, the IP address of the computer I’m typing this is 192.168.2.4. That’s my inside local address.

Inside Global

Inside local is an easy one. The inside global address is a bit more tricky. This is the address that your computer tries to reach. For example the Google DNS server 8.8.8.8. This can be an inside global address. What makes it more confusing is that this inside global address could be a translated address. For example, 192.168.2.89. This could lead me to the same Google address, but in this case that’s not clear by looking at the address.

Outside Local

The outside local address is a routable address on the outside of your network. In most cases this is a globally routable address. But it could also be a non routable address in the event that NAT is used to interconnect two companies directly. The outside local address must at least be reachable by some systems that are not under your control.

Outside Global

This is the actual outside IP address that you’re trying to reach. It is the untranslated outside address.

Types of NAT

There are a lot of different types of NAT. The type depends on what you’re trying to achieve.

  • Static NAT
    • Static PAT
  • Dynamic NAT
    • Overload NAT using access-lists
    • Dynamic NAT using route-maps
    • Reversible NAT
  • TCP Load distribution

And several others, but for now I’m focussing on these as the post will get long enough as it is.

Static NAT

This is the easiest NAT to configure. It’s a static mapping between IP addresses. This is often used when an outside device needs to access an inside device. For example when you have a e-mail server which you want to publish on the internet.

Static NAT also has some downsides. Because it’s a static mapping it requires manual configuration for all NAT entries. It also requires an external IP address for all translated internal addresses. The mapping is permanent and this makes it possible to reach the system from the internet. So if you want to use NAT to prevent systems from being reachable from the internet, static NAT is not the solution.

Say for example, my webserver has the IP address 192.168.2.78. This is of course an unroutable address on the Internet, but I do want this server to be reachable. I have a small subnet of routable addresses, 100.64.32.32/27. (I know 100.64.0.0/10 is unroutable on the internet, but it’s a nice range for demo purposes). I pick one of the addresses and create a static NAT rule to make my webserver reachable.

interface g 0/0
 ip address 192.168.2.1 255.255.255.0
 ip nat inside
!
interface g 0/1
 ip address 100.64.32.33 255.255.255.224
 ip nat outside
!
ip nat inside source static 192.168.2.78 100.64.32.34

This configuration statically binds the IP address 192.168.2.78 to 100.64.32.34. As of now the webserver is reachable. We can verify the NAT translation using the show ip nat translations command.

sh ip nat trans
Pro Inside global      Inside local       Outside local      Outside global
--- 100.64.32.34         192.168.2.78          ---                ---

The biggest pitfall of this is that it’s a static mapping. This means that you need a one on one mapping between outside and inside addresses. This is fine when you have enough outside addresses and not a lot of servers you want reachable from the internet.

You can do this configuration the other way around too. In this case you translate an outside address to an inside address. Say for example that I don’t want systems in my network to access the internet, but I do want them to get time synchronization data from the internet. I could do this using all kinds of filters. I can also just not give the systems the routing information required to access external addresses. To let those systems access the NTP server I can translate the outside global IP address of the NTP server to an outside local address.

ip nat outside source static 80.127.152.30 100.64.32.35

Now I configure my systems to use 100.64.32.35 as NTP server and that will be translated to the (actual) NTP server address of 80.127.152.30. The systems do need to have access to your own outside local addresses.

Static PAT

Static PAT is almost the same as regular static NAT. Except for static PAT you define port numbers. This can be used to offer a service to the outside world on a different port than on the inside. This is useful when you have only one IP address, but need to make two web servers available from the outside.

An example configuration is where I offer the telnet service on port 2323:

ip nat inside source static tcp 192.168.54.4 23 192.168.65.4 2323 extendable

The extendable keyword is added by the parser. You can enter the command without the extendable keyword. This option makes it possible to create multiple static NAT entries with the same IP address.

One of the ‘problems’ with this configuration is that you can now ping the 192.168.65.4 address, even though it’s not configured on any interface, and I only configured tcp ports 2323 on the outside. This is because IOS automatically creates an IP alias on the router to answer to traffic destined for 192.168.65.4

R5(config)#do sh ip alias
Address Type             IP Address      Port
Interface                5.5.5.5
Interface                192.168.54.5
Dynamic                  192.168.65.4
Interface                192.168.65.5
Interface                192.168.85.5
Interface                192.168.95.5
R5(config)#


R6#ping 192.168.65.4
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.65.4, timeout is 2 seconds:
!!!!!

You might not want that. So let’s get rid of that automatic alias. This is very simple, just add the no-alias keyword in your NAT statement. As you can see the alias is gone and the ping no longer works. The telnet on port 2323 fortunately still works:

ip nat inside source static tcp 192.168.54.4 23 192.168.65.4 2323 extendable no-alias

R5(config)#do sh ip alias
Address Type             IP Address      Port
Interface                5.5.5.5
Interface                192.168.54.5
Interface                192.168.65.5
Interface                192.168.85.5
Interface                192.168.95.5
R5(config)#

R6#ping 192.168.65.4       
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.65.4, timeout is 2 seconds:
.....

R6#telnet 192.168.65.4 2323
Trying 192.168.65.4, 2323 ... Open

Dynamic NAT

Dynamic NAT offers much more flexibility. It can dynamically create NAT entries when needed. It will also remove them after a short time when no longer necessary. You can still create a one to one mapping between local and global addresses, but this is no longer necessary. You can create ‘overload’ NAT rules. These overload rules make it possible to map many internal addresses to a single global address.

The biggest downside of dynamic NAT is that it’s more complex and there are several ways to configure it. Lets demonstrate several of them and take note of some pitfalls. The following methods of configuring dynamic NAT will be discussed in this post:

  • Overload NAT using access-lists
  • Dynamic NAT using route-maps
  • Reversible NAT

Overload NAT using access-Lists

Overload NAT is what you’re probably doing at home. You probably have a router at home with a single public IP address and a RFC 1918 range for your PC, phone etc. In such a case, all traffic originating from the inside subnet must be translated to the single external IP address. The systems on the inside are connecting to the outside global address, but the outside global address returns the traffic to the outside local address. On the router the outside local is translated into the inside local address.

When you have 10 pc’s on the inside, how will the router know to which inside local address to send the traffic? It does this based on the source port.

This type of dynamic NAT is the easiest to configure. You’ll need to do three things:

  • Define NAT interfaces
  • Define interesting traffic
  • Define the NAT rule

Defining NAT interfaces is something we’ve done before. Interesting traffic could be anything. For this example we’re looking at traffic originating from 1.1.1.1. The configuration is as follows:

ip nat inside source list 10 interface GigabitEthernet0/0.32 overload
access-list 10 permit 1.1.1.1

It’s that simple. Of course you can also use extended access-lists and do some more complicated matching. In the case of your home router it’s a simple any rule, defining all inside traffic.

So, you’re not on a simple home internet connection, but an actual business internet line. You have some public IP addresses, but not enough for all your users. You can use these addresses to perform NAT using NAT pools. Luckily, even when using NAT pools you can still overload them. This is useful if you have more than 64000 simultaneous sessions. The configuration is stated below:

ip nat pool MY_POOL 192.168.32.10 192.168.32.20 prefix-length 24
ip nat inside source list NAT pool MY_POOL overload
ip access-list extended NAT
 permit ip host 1.1.1.1 host 3.3.3.3

Here I created a NAT pool first. This pool contains the addresses 192.168.32.10 to 192.168.32.20 which is part of a /24 subnet. This pool is then used in the NAT statement. In the previous example I specified an interface. Now I specify a pool.

The observant reader might have noticed I swapped the access list for an extended access-list allowing traffic from 1.1.1.1 to 3.3.3.3.

Dynamic NAT using route-maps

Let’s say you have two ISPs. Both ISPs are connected to a single router using their own interfaces. In some cases ISP A might offer a better route to a destination and in some cases ISP B might know the best route. You don’t have your own IP space you can advertise to both ISPs. So you’re stuck with the public IP addresses they have given you. This is a problem, because sometimes you need to NAT to the ISP A public address and sometimes to the ISP B public address.

This issue can be fixed using route maps. Route maps will offer you the flexibility to match an outgoing interface. So you can have multiple outside interfaces for NAT and based on your routing decision translate to a specific outside local address.

The configuration for this is fairly simple. We have R1 connected to R2 and R3. R1 knows that to get to the loopback of R2 it has to use Gi 0/1 and to get to R3’s loopback it has to use Gi 0/2. Yet, the only addresses R2 and R3 have for R1 are their directly connected interfaces.

R1:
interface g 0/1
 ip nat outside
interface g 0/2
 ip nat outside
!
route-map TO_R2 permit 10
 match interface g0/1
route-map TO_R3 permit 10
 match interface g0/2
!
ip nat inside source route-map TO_R2 interface g0/1 overload
ip nat inside source route-map TO_R3 interface g0/2 overload

In this example I’m only matching on the outgoing interface, but you can also match the source IP addresses using an access-list (prefix-lists are not supported). To verify I’m sending pings from the loopback address of R1 to the loopback addresses of R2 and R3 while I enabled debug ip nat. As you can see the source IP address of the traffic is translated based on the outgoing interface.

R1#ping 2.2.2.2 so lo0  
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 2.2.2.2, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/9 ms
R1#
*Mar  8 02:39:10.674: NAT: s=1.1.1.1->192.168.12.1, d=2.2.2.2 [20]
*Mar  8 02:39:10.683: NAT*: s=2.2.2.2, d=192.168.12.1->1.1.1.1 [20]
[SNIP]

R1#ping 3.3.3.3 so lo0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 3.3.3.3, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 2/2/3 ms
R1#
*Mar  8 02:39:21.217: NAT: s=1.1.1.1->192.168.13.1, d=3.3.3.3 [25]
*Mar  8 02:39:21.219: NAT*: s=3.3.3.3, d=192.168.13.1->1.1.1.1 [25]
[SNIP]

Reversible NAT

When you configure a static NAT entry this entry can be used both inside out and outside in. This means that systems on the internet can reach the internal system on the outside local address. Dynamic NAT does not create an entry that can be used to send traffic from the outside in by default. Sometimes you might want to do this. Some applications need the server to set up a connection to the client on a different port. Because of this it is possible to make a dynamic NAT entry reversible.

Some limitations, apply. The scalability of this solution is limited to the amount of outside addresses you have available, like static NAT. For every reversible entry you use an IP address. When you use overload you can set up more sessions than there are IPs in the pool. But reverse traffic will not work for these extra sessions. These will be forwarded to the device that set up the first session for that IP.

The rest of setting up reversible NAT is simple. It’s the same command as usual, but ends with the keyword reversible.

ip access-list standard NAT_ADDRESSES
 permit 192.168.3.3
!
route-map REV_NAT permit 10
 match ip address NAT_ADDRESSES
!
ip nat pool POOL 192.168.1.100 192.168.1.200 prefix-length 24
!
ip nat inside source route-map REV_NAT pool POOL reversible

TCP load distribution

This is a fun one. You can use NAT as a simple load balancer to distribute load across multiple servers.

So I’ve got two telnet servers. Both are running on the inside of my network. I want my NAT router to round-robin the traffic between these two servers. The configuration is as follows:

ip nat pool TELNET 192.168.1.2 192.168.1.3 prefix-length 24 type rotary
ip access-list standard NAT_ROTARY
 permit 192.168.10.10
!
ip nat inside destination list NAT_ROTARY pool TELNET
!
ip alias 192.168.10.10 23

Because the router doesn’t know it has to listen on the address 192.168.10.10 on port 23 you need to define a static ip alias for this to work. You use the NAT pool to define the IP addresses of the servers and specify the type rotary for this pool. If you don’t do this it won’t create a round-robin like scheme. You then define a destination NAT with the access-list defining the outside local address.

The result will be splendid:

SW1#telnet 192.168.10.10       
Trying 192.168.10.10 ... Open
R2>exit

[Connection to 192.168.10.10 closed by foreign host]
SW1#telnet 192.168.10.10
Trying 192.168.10.10 ... Open
R3>