Debugging NAT cp22

Debugging NAT

Problem

You want to debug a NAT problem.

Solution

Cisco routers include a simple but useful debug facility for NAT. The basic form of the command is debug ip nat:

Router#debug ip nat

You can also add the detailed keyword to this command to get more information on each NAT event:

Router#debug ip nat detailed

It is often useful to use an access-list with the debug command. You can do this by simply specifying the number of the access-list. This will allow you to just look at NAT events for particular IP addresses that are permitted by the access-list:

Router#debug ip nat 15

You can also combine an access-list with the detailed keyword for more focused debugging:

Router#debug ip nat 15 detailed

Discussion

The following shows some typical log entries:

Router#terminal monitor
Router#debug ip nat
Sep 8 19:51:08.396 EDT: NAT: s=192.168.3.1->192.168.19.1, d=192.168.3.2 [0]
Sep 8 19:51:11.560 EDT: NAT*: s=192.168.1.10->192.168.19.55, d=192.168.3.2 [490
9]
Sep 8 19:51:11.568 EDT: NAT*: s=192.168.3.2, d=192.168.19.55->192.168.1.10 [490
9]
Sep 8 19:51:11.572 EDT: NAT: s=192.168.3.2, d=192.168.19.55->192.168.1.10 [4909
]
Sep 8 19:51:12.552 EDT: NAT*: s=192.168.1.10->192.168.19.55, d=192.168.3.2 [491
1]
Sep 8 19:51:12.564 EDT: NAT*: s=192.168.3.2, d=192.168.19.55->192.168.1.10 [491
1]

This particular trace follows a simple series of PING packets. The interior device 192.168.1.10 sends ICMP PING packets to the external destination 192.168.3.2. The router rewrites the internal address as 192.168.19.55 and forwards the packet to the external destination.

You can also see the PING responses coming back from the destination device. The router rewrites the internal address back to its true value and forwards the packet appropriately

Checking NAT Status

Checking NAT Status

Problem

You want to see the current NAT information.

Solution

There are several useful EXEC commands for checking the status of NAT on a router. You can view the NAT translation table by using the following command:

Router#show ip nat translation

You can clear all or part of the NAT translation table by specifying either a * or a particular address. To clear a specific entry, you must specify either the global address for a device that is inside, or a local address for a device that is outside:

Router#clear ip nat translation *
Router#clear ip nat translation inside 172.18.3.2
Router#clear ip nat translation outside 192.168.1.10

You will often want to look at NAT statistics, including information on which interfaces use NAT, how many entries are in the NAT table, how often they have been used, and, most importantly, how often packets have bypassed NAT. The command to see this is show ip nat statistics:

Router#show ip nat statistics

And you can clear these statistics as follows:

Router#clear ip nat statistics

Discussion

The NAT translation table contains information about every translation that the router is currently tracking. In this example, you can see that there have been two connections between the interior device 192.168.1.10 and the exterior device 172.18.3.2. The first of these connections is shown as ICMP:

Router#show ip nat translation
Pro Inside global Inside local Outside local Outside global
icmp 172.16.1.100:21776 192.168.1.10:21776 172.18.3.2:21776 172.18.3.2:21776
tcp 172.16.1.100:1029 192.168.1.10:1029 172.18.3.2:23 172.18.3.2:23
--- 172.16.1.10 192.168.1.15 --- ---
--- 172.16.1.11 192.168.1.16 --- ---
Router#

This command shows only the currently active NAT table entries. You can see, for example, that it translates the inside local address 192.168.1.10 to the inside global address 172.16.1.100. But this router isn't configured to translate outside addresses, so the outside local address is the same as the outside global addresses. As we discussed in Recipe 21.10, the router removes dynamic NAT entries after a defined period of time. For example, by default the router will delete NAT entries for TCP connections after 24 hours.

The output has five columns. The first is the protocol. This column is blank unless you use the overload option in your NAT configuration. The "Inside global" address column is the translated address of an internal device. The "Inside local" column, on the other hand, shows the real internal address for the same device. The "Outside local" column shows the translated addresses of external devices, while "Outside global" shows their real addresses.

This can be a little bit confusing at first sight. The real address on the inside is "local," and the translated address is "global," while the real address on the outside is "global," and it is translated to a "local" address. You can resolve this confusion by remembering that global addresses are always on the outside, and local addresses are on the inside.

The last two rows represent simple static NAT entries. It shows, for example, that the internal device whose real address is 192.168.1.15 is translated to 172.16.1.10 when its packets pass through this router. There are no external addresses listed for this entry. Because it is a static entry, this translation is the same for any external device. However, the row immediately above this one shows all four entries:

tcp 172.16.1.100:1029  192.168.1.10:1029  172.18.3.2:23      172.18.3.2:23

This line includes a lot of useful information. The first column indicates that this row represents a TCP connection, and that the translation is a dynamic entry. On the inside, the source address is 192.168.1.10, and the source TCP port it 1029, while the destination is 172.18.3.2, and the destination port is 23. On the outside, the destination address and port are the same, but the source address is rewritten as 172.16.1.100, and the source port is 1029.

The verbose keyword makes this command show age information about each table entry:

Router#show ip nat translation verbose
Pro Inside global Inside local Outside local Outside global
icmp 172.16.1.100:21776 192.168.1.10:21776 172.18.3.2:21776 172.18.3.2:21776
192.168.3.2:4235
create 00:00:36, use 00:00:36, left 00:00:23, flags: extended
tcp 172.16.1.100:1029 192.168.1.10:1029 172.18.3.2:23 172.18.3.2:23
create 00:00:15, use 00:00:13, left 00:00:46, flags: extended, timing-out
--- 172.16.1.10 192.168.1.15 --- ---
create 1d00h, use 00:23:08, flags: static
--- 172.16.1.11 192.168.1.16 --- ---
create 1d00h, use 00:15:28, flags: static
Router#

This level of detail is most useful when you are trying to diagnose NAT table timeout issues.

The show ip nat statistics command includes useful information about the translation configuration. The following example shows one external and two internal interfaces, with a dynamic NAT pool that runs from 172.16.1.100 to 172.16.1.150:

Router#show ip nat statistics
Total active translations: 3 (2 static, 1 dynamic; 1 extended)
Outside interfaces:
Ethernet0/0
Inside interfaces:
FastEthernet0/0, FastEthernet0/1
Hits: 2628 Misses: 44
Expired translations: 37
Dynamic mappings:
-- Inside Source
access-list 15 pool NATPOOL refcount 1
pool NATPOOL: netmask 255.255.255.0
start 172.16.1.100 end 172.16.1.150
type generic, total addresses 2, allocated 1 (50%), misses 9
Router#

The Hits field shows the total number of times that the router has had to create new translation table entries. The Misses field counts the exceptions. In this case, there is an access-list that excludes certain internal IP addresses

Adjusting NAT Timers

Adjusting NAT Timers

Problem

You want to change the length of time that NAT entries remain active.

Solution

The router will keep NAT entries in the translation table for a configurable length of time. For TCP connections, the default timeout period is 86,400 seconds, or 24 hours. Because UDP is not connection based, the default timeout period is much shorteronly 300 seconds, or 5 minutes. The router will remove translation table entries for DNS queries after only 60 seconds.

You can adjust these parameters using the ip nat translation command, which accepts arguments in seconds:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#ip nat translation tcp-timeout 500
Router(config)#ip nat translation udp-timeout 30
Router(config)#ip nat translation dns-timeout 30
Router(config)#ip nat translation icmp-timeout 30
Router(config)#ip nat translation finrst-timeout 30
Router(config)#ip nat translation syn-timeout 30
Router(config)#end
Router#

To save router memory, you can also define a maximum number of NAT translation table entries:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#ip nat translation max-entries 1000
Router(config)#end
Router#

Discussion

There are many reasons for adjusting these various timeout parameters; most are related to router performance. If sessions are generally short-lived, it is a waste of memory to maintain the NAT entries for a long time. The finrst-timeout and syn-timeout parameters are also useful when the router is connected to the public Internet because they can help to prevent denial of service attacks that are based on sending TCP control packet such as SYN, ACK, and FIN. If the router only keeps the NAT entries associated with these packets for a brief period of time, you can help to limit the impact of such attacks.

We recommend using extreme caution with the max-entries command:

Router(config)#ip nat translation max-entries 1000

When you set a limit like this, the router rejects any additional attempts to use NAT. So, in this example, if you already had 1,000 NAT table entries, the router would simply drop any new connection attempts. This can be useful to prevent excessive NAT processing from overloading the router, but it can also block legitimate access.

It is difficult to select a useful upper limit to the size of the NAT table in general. In most cases, it is best to use the default, which does not enforce any upper limit. You should use this command only if you start to run into serious memory or CPU utilization problems. Because it tells the router to refuse any further requests, however, restricting the table size like this should be a last resort. In most cases, it is more effective to decrease the various timeout values as shown in this recipe.

Start by looking at your NAT translation table, as shown in Recipe 21.12, and see what most of the entries look like. If you are using the overload option, you may find that there are several different entries for each internal host, each for different port numbers or protocols. The relatively long 24-hour timeout period for TCP sessions is probably the best place to start. You can usually reduce this drastically without causing application problems, and it could give a significant improvement to the size of the NAT table.

See Also

Changing TCP Ports for FTP

Changing TCP Ports for FTP

Problem

You have an FTP server that uses a nonstandard TCP port number.

Solution

The FTP protocol includes IP address information in the packet payload. Normally, Cisco's NAT implementation rewrites IP address information in the payloads of FTP packets by looking in every packet sent on TCP port 21, which is the port that FTP uses to pass session control information by default. So when an FTP server uses a nonstandard TCP port number for session control, you have to configure the NAT router to expect FTP packets on this new port number:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#access-list 19 permit 192.168.55.5
Router(config)#ip nat service list 19 ftp tcp port 8021
Router(config)#ip nat service list 19 ftp tcp port 21
Router(config)#end
Router#

Discussion

As we mentioned in the Introduction to this chapter, the common FTP protocol includes IP address information in the packet payload. Cisco routers expect this, and rewrite the information appropriately. But some FTP servers use a nonstandard TCP port number, which means that NAT will break the protocol. So in IOS Version 11.3, Cisco introduced the ability to look for FTP payload information on alternate TCP port numbers.

The example configures the router to expect FTP packets for the server 192.168.55.5 on both the default port number 21 and the nonstandard port number 8021. You can easily configure similar commands for other servers as well, or expand the access-list to include several servers that all use the same nonstandard FTP port number.

In IOS Version 12.2(4)T, Cisco introduced the no-payload keyword, which prevents NAT from modifying any addresses in the packet payload:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#interface FastEthernet0/0
Router(config-if)#ip address 172.16.1.5 255.255.255.252
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#interface FastEthernet0/1
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#ip nat inside source static 192.168.1.10 172.16.1.5 no-payload
Router(config)#end
Router#

Here we have used the no-payload option to configure a static NAT entry. Any translations that use this rule will have the addresses in the IP header translated normally. But any IP addresses in the packet payload will remain untouched.

This command is useful in cases when translating the addresses inside the packet interferes with the functioning of the application

Stateful NAT Failover

Stateful NAT Failover

Problem

You want to use NAT in a high availability configuration, allowing a second router to take over NAT functionality if the first fails.

Solution

Stateful NAT allows you to combine NAT functionality with HSRP using two routers in a high availability configuration:

Router-A#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router-A(config)#access-list 11 permit any
Router-A(config)#ip nat pool NATPOOL 172.17.100.100 172.17.100.150 netmask 255.255.255.0
Router-A(config)#ip nat inside source list 11 pool NATPOOL mapping-id 1
Router-A(config)#interface FastEthernet0/0
Router-A(config-if)#ip address 192.168.1.3 255.255.255.0
Router-A(config-if)#ip nat inside
Router-A(config-if)#standby 1 ip 192.168.1.1
Router-A(config-if)#standby 1 preempt
Router-A(config-if)#standby 1 name SNATGROUP
Router-A(config-if)#exit
Router-A(config)#interface Serial0/0
Router-A(config-if)#ip address 172.17.55.2 255.255.255.252
Router-A(config-if)#ip nat outside
Router-A(config-if)#exit
Router-A(config)#ip nat Stateful id 1
Router-A(config-ipnat-snat)#redundancy SNATGROUP
Router(config-ipnat-snat-red)#mapping-id 1
Router(config-ipnat-snat-red)#exit
Router-A(config)#end
Router-A#

The second router's configuration is nearly identical:

Router-B#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router-B(config)#access-list 11 permit any
Router-B(config)#ip nat pool NATPOOL 172.17.100.100 172.17.100.150 netmask 255.255.255.0
Router-B(config)#ip nat inside source list 11 pool NATPOOL mapping-id 1
Router-B(config)#interface FastEthernet0/0
Router-B(config-if)#ip address 192.168.1.2 255.255.255.0
Router-B(config-if)#ip nat inside
Router-B(config-if)#standby 1 ip 192.168.1.1
Router-B(config-if)#standby 1 priority 90
Router-B(config-if)#standby 1 preempt
Router-B(config-if)#standby 1 name SNATGROUP
Router-B(config-if)#exit
Router-B(config)#interface Serial0/0
Router-B(config-if)#ip address 172.17.55.6 255.255.255.252
Router-B(config-if)#ip nat outside
Router-B(config-if)#exit
Router-B(config)#ip nat Stateful id 1
Router-B(config-ipnat-snat)#redundancy SNATGROUP
Router(config-ipnat-snat-red)#mapping-id 1
Router(config-ipnat-snat-red)#exit
Router-B(config)#end
Router-B#

Discussion

When you use NAT with a router failover protocol such as HSRP, the backup router must be able to take over NAT functionality as well as the IP address of the primary router. The problem is that this necessarily includes the entire dynamic NAT translation table. Simply running NAT and HSRP on a pair of routers is not sufficient because any existing NAT session information will be lost when the backup router takes over.

Stateful Network Address Translation (SNAT) solves this problem. The key command, which must be present on both routers is the ip nat Stateful command, which became available in IOS Version 12.2(13)T:

Router-A(config)#ip nat Stateful id 1
Router-A(config-ipnat-snat)#redundancy SNATGROUP
Router(config-ipnat-snat-red)#mapping-id 1
Router(config-ipnat-snat-red)#exit

There are a couple of things to notice here. First, the keyword Stateful will appear in your configuration capitalized like this. When you enter the command, it is case insensitive, however it can be slightly confusing because one usually expects IOS configuration keywords to be all lowercase. We often take advantage of this fact by deliberately capitalizing user-defined strings like SNATGROUP in this example, making the distinction from keywords obvious.

Entering the ip nat Stateful command puts you into a new configuration mode that allows you to associate a particular SNAT mapping ID with an HSRP group name. You can give the HSRP group a name with the standby name command as follows:

Router-A(config)#interface FastEthernet0/0
Router-A(config-if)#ip address 192.168.1.3 255.255.255.0
Router-A(config-if)#ip nat inside
Router-A(config-if)#standby 1 ip 192.168.1.1
Router-A(config-if)#standby 1 preempt
Router-A(config-if)#standby 1 name SNATGROUP

For more information on HSRP, please refer to Chapter 22.

In this example we have used a simple dynamic NAT configuration by using a pool called NATPOOL:

Router-A(config)#access-list 11 permit any
Router-A(config)#ip nat pool NATPOOL 172.17.100.100 172.17.100.150 netmask 255.255.255.0
Router-A(config)#ip nat inside source list 11 pool NATPOOL mapping-id 1

We could have just as easily used other NAT configuration methods such as static NAT, or PAT address overloading, as described elsewhere in this chapter.

With this configuration, one of the routers will take the virtual IP address, 192.168.1.1, acting as the default gateway for the interior network. The second router will operate in a passive backup mode, waiting to take over this virtual IP address in case the first router fails. The first router will maintain the NAT table for all connections. This means that you have to be very careful to ensure that inbound traffic uses the same path as outbound traffic, or the NAT table may not be able to rewrite the inside global IP address to the correct inside local address.

When the primary router fails, HSRP allows the backup router to transparently take over the virtual IP address. At the same time, SNAT ensures that the NAT translation table is also up to date, allowing the backup router to take over all NAT functions.

You can also use SNAT to create a dual redundancy active/active configuration in which both routers are passing HSRP and NAT traffic. We discuss the HSRP side of this technique in more detail in Chapter 22. The key is to create two HSRP groups, each representing a different virtual IP address. We then assign different priorities to each group so that during normal operation, the first router is active for the first virtual IP address and the second is active for the other address. However, in case of a failure of either router, the other one can take over functionality for both:

Router-A#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router-A(config)#interface FastEthernet0/0
Router-A(config-if)#ip address 192.168.1.3 255.255.255.0
Router-A(config-if)#ip nat inside
Router-A(config-if)#standby 1 ip 192.168.1.1
Router-A(config-if)#standby 1 preempt
Router-A(config-if)#standby 1 name SNAT1
Router-A(config-if)#standby 2 ip 192.168.1.2
Router-A(config-if)#standby 2 priority 90
Router-A(config-if)#standby 2 preempt
Router-A(config-if)#standby 2 name SNAT2
Router-A(config-if)#exit
Router-A(config)#interface Serial0/0
Router-A(config-if)#ip address 172.17.55.2 255.255.255.252
Router-A(config-if)#ip nat outside
Router-A(config-if)#exit
Router-A(config)#ip nat Stateful id 1
Router-A(config-ipnat-snat)#redundancy SNAT1
Router(config-ipnat-snat-red)#mapping-id 1
Router(config-ipnat-snat-red)#redundancy SNAT2
Router(config-ipnat-snat-red)#mapping-id 2
Router(config-ipnat-snat-red)#exit
Router-A(config)#access-list 11 permit any
Router-A(config)#access-list 12 permit any
Router-A(config)#ip nat pool NATPOOL1 172.17.100.100 172.17.100.150 netmask 255.255.255.0
Router-A(config)#ip nat inside source list 11 pool NATPOOL mapping-id 1
Router-A(config)#ip nat pool NATPOOL2 172.17.100.151 172.17.100.200 netmask 255.255.255.0
Router-A(config)#ip nat inside source list 12 pool NATPOOL mapping-id 2
Router-A(config)#end
Router-A#

And the second router's configuration is similar:

Router-B#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router-B(config)#interface FastEthernet0/0
Router-B(config-if)#ip address 192.168.1.4 255.255.255.0
Router-B(config-if)#ip nat inside
Router-B(config-if)#standby 1 ip 192.168.1.1
Router-B(config-if)#standby 1 preempt
Router-B(config-if)#standby 1 name SNAT1
Router-B(config-if)#standby 1 priority 90
Router-B(config-if)#standby 2 ip 192.168.1.2
Router-B(config-if)#standby 2 preempt
Router-B(config-if)#standby 2 name SNAT2
Router-B(config-if)#exit
Router-B(config)#interface Serial0/0
Router-B(config-if)#ip address 172.17.55.6 255.255.255.252
Router-B(config-if)#ip nat outside
Router-B(config-if)#exit
Router-B(config)#ip nat Stateful id 1
Router-B(config-ipnat-snat)#redundancy SNAT1
Router(config-ipnat-snat-red)#mapping-id 1
Router(config-ipnat-snat-red)#redundancy SNAT2
Router(config-ipnat-snat-red)#mapping-id 1
Router(config-ipnat-snat-red)#exit
Router-B(config)#access-list 11 permit any
Router-B(config)#ip nat pool NATPOOL 172.17.100.100 172.17.100.150 netmask 255.255.255.0
Router-B(config)#ip nat inside source list 11 pool NATPOOL mapping-id 1
Router-B(config)#end
Router-B#

Here we have mapped both HSRP groups to the same NAT mapping-id on both routers. Now they can freely allocate addresses from the same pool, and update one another in case either fails. Note that HSRP is the only high-availability protocol that works with SNAT. Other protocols such as VRRP and GLBP are not currently supported.

See Also

Using NAT for Server Load Distribution

Using NAT for Server Load Distribution

Problem

You have several application servers and you want to use NAT so that users can connect to them by a single IP address, distributing the load across all of the servers.

Solution

The rotary keyword allows you to do simple NAT-based load balancing of servers:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#interface FastEthernet0/0
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface FastEthernet0/1
Router(config-if)#ip address 192.168.2.1 255.255.255.0
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#ip nat pool WEBSERVERS 192.168.1.101 192.168.1.105 netmask 255.255.255.0 type rotary
Router(config)#access-list 20 permit host 192.168.1.100
Router(config)#ip nat inside destination list 20 pool WEBSERVERS
Router(config)#end
Router#

Discussion

This example is more applicable to an Intranet than to the public Internet. It shows a simple way of doing load balancing among a group of application servers that all perform the same function. We would like to stress that this load balancing is extremely limited, and if you want a fully featured load-balancing device, you would be much better off with one of Cisco's Content Services Switches, such as the CSS 11500 series. However, we understand that these devices are expensive, so if your requirements are fairly basic, this recipe provides a simpler and more cost effective solution.

We have a set of servers located on the LAN segment attached to the router's FastEthernet0/0 interface. In the example, we define a pool of servers on this segment called WEBSERVERS, which includes the addresses 192.168.1.101 through 192.168.1.105. These are the real physical addresses, the inside local addresses of the servers:

Router(config)#ip nat pool WEBSERVERS 192.168.1.101 192.168.1.105 netmask 255.255.255.0 type rotary

Then we create the actual NAT rule, and use a standard ACL to define the virtual IP address that devices can use to access this group of servers:

Router(config)#access-list 20 permit host 192.168.1.100
Router(config)#ip nat inside destination list 20 pool WEBSERVERS

This NAT rule has a key difference from others that we have looked at so far in this chapter because it is a destination rather than a source rule. All of the previous examples have assumed that the inside device starts the conversation with the outside device, so we have needed to rewrite the source address of the inside device on this essentially outbound conversation. In that scenario, it is appropriate to use an inside source NAT rule. Here, however, the outside device will initiate the conversation with the inside device. So we must use an inside destination NAT rule.

Now we can verify that this configuration behaves as expected by repeatedly connecting to the virtual IP address on the HTTP TCP port (80) several times:

Router#show ip nat translations
Pro Inside global Inside local Outside local Outside global
tcp 192.168.1.100:80 192.168.1.101:80 192.168.2.27:11012 192.168.2.27:11012
tcp 192.168.1.100:80 192.168.1.102:80 192.168.2.27:11013 192.168.2.27:11013
tcp 192.168.1.100:80 192.168.1.103:80 192.168.2.27:11014 192.168.2.27:11014
tcp 192.168.1.100:80 192.168.1.104:80 192.168.2.27:11015 192.168.2.27:11015
tcp 192.168.1.100:80 192.168.1.105:80 192.168.2.27:11016 192.168.2.27:11016
tcp 192.168.1.100:80 192.168.1.101:80 192.168.2.27:11017 192.168.2.27:11017
tcp 192.168.1.100:80 192.168.1.102:80 192.168.2.27:11018 192.168.2.27:11018
Router#

As you can see from the NAT translation table, each successive connection goes to the next address in the pool. It does this on a strict rotation, restarting at the first address in the range once it reaches the end.

Note that although this example uses a common TCP port, there is nothing in the configuration to restrict you to using this method for load balancing web servers. The technique would work equally well for sharing load among nonTCP application servers, such as the UDP-based DNS application.

This recipe shows a simple but effective load-balancer, but it does have several limitations compared to a fully featured load-balancer like the CSS 11500 series. These purpose-built devices are able to monitor all of the devices in the pool and remove any that become unavailable, for example. They also use more sophisticated load balancing algorithms that ensure that no one device in the pool winds up taking an overly large share of the load. Another alternative is the Server Load-Balancing (SLB) IOS feature set, which is currently available only on the 3640, 3660, 7200, and 7301 router platforms.

The method shown in this recipe has neither of these advantages. If any device in the pool becomes temporarily unreachable, or the application stops working, the NAT rule will continue to attempt sending new connections to it each time it comes up in the rotation. The end device will typically have to wait for a TCP connection timeout and reconnect, hopefully getting a different server from the pool.

Then, when the device comes back on line, it will again only receive new connections each time it comes up in the rotation. In most applications, this means that it will take a very long time to rebalance the load

Translating in Both Directions Simultaneously

Translating in Both Directions Simultaneously

Problem

You want to translate both internal and external addresses.

Solution

In some cases, you might need to translate IP addresses on both sides of your router:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#access-list 15 deny 192.168.1.15
Router(config)#access-list 15 permit 192.168.0.0 0.0.255.255
Router(config)#access-list 16 deny 172.16.5.25
Router(config)#access-list 16 permit 172.16.0.0 0.0.255.255
Router(config)#ip nat pool NATPOOL 172.16.1.100 172.16.1.150 netmask 255.255.255.0
Router(config)#ip nat pool INBOUNDNAT 192.168.15.100 192.168.15.200 netmask 255.255.255.0
Router(config)#ip nat inside source list 15 pool NATPOOL overload
Router(config)#ip nat inside source list 16 pool INBOUNDNAT overload
Router(config)#ip nat inside source static 192.168.1.15 172.16.1.10
Router(config)#ip nat outside source static 172.16.5.25 192.168.15.5
Router(config)#ip route 192.168.15.0 255.255.255.0 Ethernet0/0
Router(config)#interface FastEthernet 0/0
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface FastEthernet 0/1
Router(config-if)#ip address 192.168.2.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#interface Ethernet0/0
Router(config-if)#ip address 172.16.1.2 255.255.255.0
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#end
Router#

Discussion

Sometimes you need to translate IP addresses on both the inside and the outside interfaces. This might happen, for example, when you need to connect to another network that uses an overlapping range of unregistered addresses. Cisco routers can do NAT translations of address on both the external and internal interfaces at the same time.

In this case, the router rewrites external addresses that are in the range 172.16.0.0/16 so that they appear to be on the 192.168.15.0/24 subnet in the range specified by the INBOUNDNAT pool. And, at the same time, it rewrites internal addresses that are part of the 192.168.0.0/16 subnet so that they appear on the outside to be part of 172.16.1.0/24 in the range specified by the NATPOOL pool.

Note that the access-lists that define which addresses should use the dynamic address pool both refer to the real addresses (inside local and outside global). So, for internal devices, the access-list should refer to the real internal addresses, while the list for external devices refers to the real external addresses.

The most significant reason for using this feature is to remove a conflict due to overlapping address ranges. The following example shows how to remove an address conflict at the router between two networks that are both using the ubiquitous 10.0.0.0/8 address range. We will map the outside network to 11.0.0.0/8 and the inside to 12.0.0.0/8. Note that these two address ranges are both registered network numbers, so doing this will cause some problems for Internet access. We would only recommend doing this as a temporary measure to resolve an IP address conflict caused by merging two networks with overlapping IP address ranges:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#access-list 17 permit 10.0.0.0 0.255.255.255
Router(config)#access-list 18 permit 10.0.0.0 0.255.255.255
Router(config)#ip nat pool OUTPOOL 11.0.0.1 11.255.255.254 netmask 255.0.0.0 type match-host
Router(config)#ip nat pool INPOOL 12.0.0.1 12.255.255.254 netmask 255.0.0.0 type match-host
Router(config)#ip nat inside source list 17 pool INPOOL
Router(config)#ip nat outside source list 18 pool OUTPOOL
Router(config)#ip route 11.0.0.0 255.0.0.0 Ethernet0/0
Router(config)#ip route 12.0.0.0 255.0.0.0 FastEthernet1/0
Router(config)#interface FastEthernet1/0
Router(config-if)#ip address 10.1.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface Ethernet0/0
Router(config-if)#ip address 10.2.1.2 255.255.255.0
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#end
Router#

Notice that we have used the match-host keyword in the NAT pool definitions:

Router(config)#ip nat pool OUTPOOL 11.0.0.1 11.255.255.254 netmask 255.0.0.0 type match-host

When you use this option, the router will translate the network prefixes and leave the host portions of the address intact. So, in this example, an arbitrary IP address 10.1.2.3 would become 11.1.2.3, changing only the first byte. This has the advantage that the translations are always the same, so you can reliably make connections between any internal and external devices in either direction. You cannot do this with the ordinary dynamic address pools that we have discussed so far in this chapter. Note also that the overload option makes no sense in this configuration.

There are a few important things to watch out for when using NAT in both directions. First, the router must have routing table entries for the fictitious IP addresses. It is quite likely that the translated addresses used for external devices will not be part of a physical IP network that the router knows how to reach. This is why we have configured a static route directing traffic for this range out through the external interface:

Router(config)#ip route 192.168.15.0 255.255.255.0 Ethernet0/0

The second important thing to remember is that with dynamic NAT, the router does not create a translation for each device until it needs to. So if you want to connect through the router to a particular translated address, you have to make sure that the router retains the translation table information. This means that if you want any-to-any connections in either direction, you must either use static mappings or the match-host keyword. Dynamic NAT will not allow access in both directions.

And the third important thing to remember is that all of the other routers must know how to reach the translated addresses. So, if the external network is translated from 10.0.0.0/8 to 11.0.0.0/8, then you need to make sure that the internal routers all know that they can reach this fictitious 11.0.0.0/8 network through the NAT router. The best way to do this is to simply redistribute the static routes for the fictitious networks through your dynamic routing protocol.

Recipe 21.7 shows a somewhat better way to solve this overlapping address problem. Instead of doing simultaneous translation in both directions on the same router, it is better to do it on two routers with a different, nonconflicting address range in the middle. One router will simply translate the prefix for one of these networks from 10.0.0.0/8 to 11.0.0.0/8. The other router will translate the addresses on the other network from 10.0.0.0/8 to 12.0.0.0/8. This is a much more stable solution, and it does not suffer from the problems of dynamic NAT that we mentioned above.

See Also

Rewriting the Network Prefix

Rewriting the Network Prefix

Problem

You want to rewrite all of the addresses in a particular range by simply replacing the prefix with one of equal length.

Solution

Sometimes you need to connect your network to another network that uses an unregistered range, such as 172.16.0.0/16. However, if you already use this range in your network, the easiest thing to do is to simply replace this prefix with another one that doesn't have a conflict, such as 172.17.0.0/16:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#ip nat outside source static network 172.16.0.0 172.17.0.0 /16 no-alias
Router(config)#ip route 172.16.0.0 255.255.0.0 Ethernet1/0
Router(config)#ip route 172.17.0.0 255.255.0.0 Ethernet1/0
Router(config)#interface FastEthernet 0/0
Router(config-if)#ip address 10.1.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface Ethernet1/0
Router(config-if)#ip address 172.16.1.6 255.255.255.252
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#end
Router#

Discussion

Unlike the previous examples, this recipe shows a very simple static form of NAT that translates addresses by simply replacing one prefix with another. So, for example, the remote host, 172.16.55.19, gets its address rewritten simply as 172.17.55.19.

The router can accomplish this with the following command:

Router(config)#ip nat outside source static network 172.16.0.0 172.17.0.0 /16 no-alias

This defines a static mapping of one network prefix to another, as required.

Note that we have included the no-alias keyword in this command. If we didn't include this keyword, the router would try to generate aliases for the translated addresses to allow it to answer ARP requests for them. This keyword is necessary because one of the router's own interfaces belongs to the translated range

Using Route Maps to Refine Static Translation Rules

Using Route Maps to Refine Static Translation Rules

Problem

You want to use route maps to give finer control over your static NAT translation rules.

Solution

One of the best uses of this feature appears when you have two Internet Provider connections and you want to use distinct NAT rules for each:

Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#interface FastEthernet0/0
Router(config-if)#ip address 172.16.1.5 255.255.255.252
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#interface FastEthernet0/1
Router(config-if)#ip address 172.16.2.5 255.255.255.252
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#interface FastEthernet0/2
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#ip nat inside source route-map ISP-1 interface FastEthernet0/0 overload
Router(config)#ip nat inside source route-map ISP-2 interface FastEthernet0/1 overload
Router(config)#route-map ISP-1 permit 10
Router(config-route-map)#match interface FastEthernet0/0
Router(config-route-map)#exit
Router(config)#route-map ISP-2 permit 10
Router(config-route-map)#match interface FastEthernet0/1
Router(config-route-map)#exit
Router(config)#end
Router#

Discussion

This example shows a relatively common situation in which a network has two Internet connections for redundancy. Note that we don't show the redundancy mechanism here, but it could be handled by BGP, for example. There are three Fast Ethernet interfaces on this router, one for each of the two Internet Service Providers, and one for the internal network.

To understand the problem that we are looking at here, consider the standard ip nat inside source command that we used in Recipe 21.1:

Router(config)#access-list 15 permit 192.168.0.0 0.0.255.255
Router(config)#ip nat inside source list 15 interface FastEthernet0/0 overload

This rule translates the source address in all outbound packets to the address on one of the two external connections. As long as all of the traffic uses this particular interface, there is no problem, but then there's not much point in paying for the second connection. So consider what happens to any packets that are transmitted through the second connection when this rule is used. There are two possible consequences. The Internet Service Provider might accept the source address for the wrong network and forward the packet normally, and the return path from the destination might try to use the first Internet connection, which is bad because it might be down. Or, more likely, the second Internet provider will simply drop the packet because it appears to have a spoofed source address.

Instead, by using route maps in our ip nat command, we can specify two different rules, one for each of the two service providers:

Router(config)#ip nat inside source route-map ISP-1 interface FastEthernet0/0 overload
Router(config)#ip nat inside source route-map ISP-2 interface FastEthernet0/1 overload

The first line specifies that any packets matching the route map ISP-1 should have their source addresses changed to match the address on FastEthernet0/0. The second line specifies that packets matching the second route map should translate to the second interface's address.

The corresponding route maps simply match on the interfaces that interfaces that the router wants to forward these packets through:

Router(config)#route-map ISP-1 permit 10
Router(config-route-map)#match interface FastEthernet0/0
Router(config-route-map)#exit
Router(config)#route-map ISP-2 permit 10
Router(config-route-map)#match interface FastEthernet0/1
Router(config-route-map)#exit

See Also

Translating Some Addresses Statically and Others Dynamically

Translating Some Addresses Statically and Others Dynamically

Problem

You want certain hosts to have static address translation properties and all others to use dynamic translation.

Solution

In some cases you might need to use a combination of the two approaches. Some internal devices will always translate to specific external addresses, but others will use a dynamic pool. This is often the case when you have a few internal servers that need to be accessed from outside of the network, but other devices that will only make outbound connections:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#access-list 15 deny 192.168.1.15 0.0.0.0
Router(config)#access-list 15 deny 192.168.1.16 0.0.0.0
Router(config)#access-list 15 permit 192.168.0.0 0.0.255.255
Router(config)#ip nat inside source static 192.168.1.15 172.16.1.10
Router(config)#ip nat inside source static 192.168.1.16 172.16.1.11
Router(config)#ip nat pool NATPOOL 172.16.1.100 172.16.1.150 netmask 255.255.255.0
Router(config)#ip nat inside source list 15 pool NATPOOL overload
Router(config)#interface FastEthernet0/0
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface FastEthernet0/1
Router(config-if)#ip address 192.168.2.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface Ethernet0/0
Router(config-if)#ip address 172.16.1.2 255.255.255.0
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#end
Router#

Discussion

In this recipe, we have the same pool of dynamic addresses as in Recipe 21.2, combined with the same two static translations from Recipe 21.3. It is often useful to combine NAT techniques like this, particularly when you use the connection between these networks for several different applications. Some applications might need to work with well-known IP addresses, while others could work well from a dynamic pool.

The access-list in this example specifically excludes the two addresses that will use static rather than dynamic NAT. This is not strictly necessary because the static NAT commands appear to have precedence over dynamic NAT in the router. However, this is still a good practice because it is absolutely clear to anybody looking at the router configuration what you intended to do.

The other important thing to notice in this example is that we have explicitly removed the static NAT addresses from the dynamic NAT pool. The dynamic pool is from 172.16.1.100 to 172.16.1.150, and the static addresses are 172.16.1.10 and 172.16.1.11. This is critically important because the dynamic NAT allocation does not check each address in the pool to make sure that is not configured for static NAT translation. So you could get serious address conflicts if you do not explicitly separate the static from the dynamic NAT addresses.

See Also

Allocating External Addresses Statically

Allocating External Addresses Statically

Problem

You want to translate specific internal IP addresses to specific external addresses.

Solution

For some applications, you need each internal (inside local) address to always translate to the same external (inside global) address. This is particularly true if you need inbound connections from the outside network to always reach a particular internal device, such as a web or email server:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#ip nat inside source static 192.168.1.15 172.16.1.10
Router(config)#ip nat inside source static 192.168.1.16 172.16.1.11
Router(config)#interface FastEthernet 0/0
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface FastEthernet 0/1
Router(config-if)#ip address 192.168.2.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface Ethernet1/0
Router(config-if)#ip address 172.16.1.2 255.255.255.0
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#end
Router#

Discussion

This recipe includes static translations for two internal devices. The internal address 192.168.1.15 will always appear on the outside as 172.16.1.10, and 192.168.1.16 will always appear as 172.16.1.11. Note that because these translations are static, they will work in either direction. So any packets sent to the NAT address from the external network will reach the internal device. External devices can even initiate TCP sessions.

This example only does NAT translation for these two specific addresses. The router will route all other addresses normally without any address translation.

See Also

Allocating External Addresses Dynamically

Allocating External Addresses Dynamically

Problem

You want to dynamically select addresses from a pool.

Solution

You can configure the router to automatically select global addresses from a pool as they are required:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#access-list 15 permit 192.168.0.0 0.0.255.255
Router(config)#ip nat pool NATPOOL 172.16.1.100 172.16.1.150 netmask 255.255.255.0
Router(config)#ip nat inside source list 15 pool NATPOOL
Router(config)#interface FastEthernet 0/0
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface FastEthernet 0/1
Router(config-if)#ip address 192.168.2.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface Ethernet1/0
Router(config-if)#ip address 172.16.1.2 255.255.255.0
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#end
Router#

Discussion

This example is similar to Recipe 21.1. The important functional difference is that the internal devices will appear on the outside with different global addresses. The first internal device that makes an outbound connection will get the first address in the range, 172.16.1.100, the next one will get the next address, 172.16.1.101, and so forth.

You configure the range with the ip nat pool command:

Router(config)#ip nat pool NATPOOL 172.16.1.100 172.16.1.150 netmask 255.255.255.0
Router(config)#ip nat inside source list 15 pool NATPOOL

In this case, the ip nat inside command does not have the overload keyword. Without this keyword, when the pool of addresses is used up, the router will respond to any additional requests with an ICMP host unreachable message. So once all of the addresses in the poll are in use, any additional devices that try to make any connections through this router will simply fail. But if you include the overload keyword, the router will simply start over at the beginning of the range and allocate multiple interior addresses for each external one:

Router(config)#ip nat inside source list 15 pool NATPOOL overload

Once again, as in Recipe 21.1, any devices that are excluded by the access-list will simply not use this NAT rule. So the excluded devices will appear on the outside with their real (inside local) IP addresses.

Note that in this example, the IP address of the external interface is 172.16.1.2/24, and the pool of translation external addresses for use in translation is 172.16.1.100 tHRough 172.16.1.150. So the pool of NAT addresses is part of the same IP subnet as the external IP address of the NAT router. This is a common practice for Internet connections where the ISP assigns a range of global addresses. But it is not necessary.

Your NAT pool can be anything, as long as the external network knows that this router can route to the NAT addresses. This is particularly useful in cases when you need a larger pool than what is available in that one subnet. For an extreme example, we could easily have made our NAT pool span the entire range 10.0.0.0/8 to give us access to a huge number of external addresses. Of course, this range is not globally unique, so it can't be used on the public Internet:

Router(config)#ip nat pool NATPOOL 10.0.0.1 10.255.255.254 netmask 255.0.0.0

See Also

Configuring Basic NAT Functionality

Configuring Basic NAT Functionality

Problem

You want to set up Network Address Translation on your router.

Solution

In the simplest NAT configuration, all of your internal devices use the same external global address as the router's external interface:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#access-list 15 permit 192.168.0.0 0.0.255.255
Router(config)#ip nat inside source list 15 interface FastEthernet0/0 overload
Router(config)#interface FastEthernet0/2
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface FastEthernet0/1
Router(config-if)#ip address 192.168.2.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#exit
Router(config)#interface Ethernet0/0
Router(config-if)#ip address 172.16.1.5 255.255.255.252
Router(config-if)#ip nat outside
Router(config-if)#exit
Router(config)#end
Router#

Discussion

In this example, the router will rewrite that address of all of the internal devices whose IP addresses are in the range 192.168.0.0/16. When these internal devices connect to devices on the outside of the network, they will all appear to have the same source address as the external interface of the router, 172.16.1.5.

This example actually includes two internal interfaces and one external. You designate the internal interfaces with the ip nat inside command. You can have as many inside interfaces as you like:

Router(config)#interface FastEthernet0/1
Router(config-if)#ip nat inside

You also need to designate at least one outside interface using the command ip nat outside. There can be several outside interfaces, but this can be very difficult to control, so it is usually not recommended:

Router(config-if)#interface Ethernet0/0
Router(config-if)#ip nat outside

You configure the actual translation action with the line:

Router(config)#ip nat inside source list 15 interface FastEthernet0/0 overload

This tells the router to translate the source addresses of any internal devices that match access-list number 15. The router will translate the source addresses of all of these devices to the address that is configured on the interface FastEthernet0/0, which is the outside interface.

The overload keyword is actually assumed here, so if you leave it off, the router will automatically put it in. This option tells the router that many internal devices can use the same global address simultaneously. Since the router itself uses this address, if even a single internal address translates to this address, it is already overloaded. We will explain this option in more detail in Recipe 21.2.

To help explain what the access-list on this command does, we will change it so that it includes every address in the range except one:

Router(config)#access-list 15 deny 192.168.1.101
Router(config)#access-list 15 permit 192.168.0.0 0.0.255.255

Now if you make a connection from the excluded address, 192.168.1.101, the only difference is that the router will not rewrite this internal address. Instead, this address will appear unchanged on the outside.

NAT can be quite confusing because people usually think that there is some firewall function associated with it. There is not. If you exclude one device from your NAT access-list, as we just discussed, anybody on the outside of the network will be able to connect to this internal device by its real address. But there is nothing to prevent an inbound packet from reaching a particular internal device if the person on the outside knows the real internal address and can route to it. Further, NAT by itself doesn't do any firewall functions, such as UDP or TCP port filtering.

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.

Debugging DHCP

Debugging DHCP

Problem

You want to debug a DHCP problem.

Solution

To debug the server events, use the following EXEC command:

Router1#debug ip dhcp server events

The following command will allow you to monitor the actual DHCP-related packets being transmitted and received by the router:

Router1#debug ip dhcp server packet

Discussion

The following debug capture shows a router performing normal housekeeping duties, such as updating its address pools, checking for expired leases, assigning new leases, and revoking expired leases:

Router1#debug ip dhcp server events
Sep 15 00:58:17.218: DHCPD: returned 172.25.1.51 to address pool COOKBOOK
Sep 15 00:58:22.566: DHCPD: assigned IP address 172.25.1.51 to client 0100.0103.85e9.87.
Sep 15 01:01:15.056: DHCPD: writing bindings to ftp://dhcp:bindsave@172.25.1.1/dhcp-leases-rtr1.
Sep 15 01:01:15.132: DHCPD: writing address 172.25.1.51.
Sep 15 01:01:15.148: DHCPD: wrote automatic bindings to ftp://dhcp:bindsave@172.25.1.1/dhcp-leases-rtr1.
Sep 15 01:01:58.816: DHCPD: checking for expired leases.
Sep 15 01:03:58.841: DHCPD: checking for expired leases.
Sep 15 01:05:58.859: DHCPD: checking for expired leases.
Sep 15 01:07:58.874: DHCPD: checking for expired leases.
Sep 15 01:09:58.885: DHCPD: checking for expired leases.
Sep 15 01:09:58.885: DHCPD: the lease for address 172.25.1.51 has expired.
Sep 15 01:09:58.885: DHCPD: returned 172.25.1.51 to address pool COOKBOOK.

The next debug capture shows a typical DHCP client transaction between the client and router. The net result is that the router assigns IP address 172.25.1.51 to MAC address 00.0103.85e9.87:

Router1#debug ip dhcp server packet
Sep 15 01:19:41.211: DHCPD: DHCPDISCOVER received from client 0100.0103.85e9.87 on interface FastEthernet0/0.1.
Sep 15 01:19:43.212: DHCPD: Sending DHCPOFFER to client 0100.0103.85e9.87 (172.25.1.51).
Sep 15 01:19:43.212: DHCPD: creating ARP entry (172.25.1.51, 0001.0385.e987).
Sep 15 01:19:43.212: DHCPD: unicasting BOOTREPLY to client 0001.0385.e987 (172.25.1.51).
Sep 15 01:19:43.216: DHCPD: DHCPREQUEST received from client 0100.0103.85e9.87.
Sep 15 01:19:43.216: DHCPD: Sending DHCPACK to client 0100.0103.85e9.87 (172.25.1.51).
Sep 15 01:19:43.216: DHCPD: creating ARP entry (172.25.1.51, 0001.0385.e987).
Sep 15 01:19:43.216: DHCPD: unicasting BOOTREPLY to client 0001.0385.e987 (172.25.1.51).
Router1#

Showing DHCP Status

Showing DHCP Status

Problem

You want to display the status of the DHCP server functions on the router.

Solution

To display the IP address bindings and their associated leases, use the following command:

Router1#show ip dhcp binding

The following command displays any IP address conflicts that the router has detected in the DHCP address pool:

Router1#show ip dhcp conflict

You can view the status of remote database backups with this command:

Router1#show ip dhcp database

And you can see the global DHCP server statistics like this:

Router1#show ip dhcp server statistics

Discussion

To display the status of the DHCP service, use the show ip dhcp EXEC command. If you add the keyword binding, this command displays the current DHCP bindings, which include the assigned IP addresses, the associated client MAC addresses, and the lease expiration time:

Router1#show ip dhcp binding
IP address Hardware address Lease expiration Type
172.25.1.51 0100.0103.85e9.87 Apr 10 2006 08:55 PM Automatic
172.25.1.52 0100.50da.2a5e.a2 Apr 10 2006 09:00 PM Automatic
172.25.1.53 0100.0103.ea1b.ed Apr 10 2006 08:58 PM Automatic
Router1#

To view the IP addresses that are currently in conflict, use the conflict keyword. This command displays all of the IP addresses that the router has discovered conflicts for, and how the conflict was discovered:

Router1#show ip dhcp conflict
IP address Detection method Detection time
172.25.1.51 Ping Apr 09 2006 09:08 PM
172.25.1.54 Gratuitous ARP Apr 09 2006 10:00 PM
Router1#

With the database keyword, you can view the database configuration and status. This command shows all of the configured remote database servers and the current read and write status reports:

Router1#show ip dhcp database
URL : ftp://dhcp:bindsave@172.25.1.1/dhcp-leases
Read : Never
Written : Apr 09 2006 10:24 PM
Status : Last write succeeded. Agent information is up-to-date.
Delay : 300 seconds
Timeout : 300 seconds
Failures : 1
Successes: 30

Router1#

Finally, the statistics keyword lets you view the overall DHCP statistics:

Router1#show ip dhcp server statistics 
Memory usage 17996
Address pools 4
Database agents 1
Automatic bindings 2
Manual bindings 1
Expired bindings 3
Malformed messages 0

Message Received
BOOTREQUEST 0
DHCPDISCOVER 63
DHCPREQUEST 203
DHCPDECLINE 1
DHCPRELEASE 27
DHCPINFORM 19

Message Sent
BOOTREPLY 0
DHCPOFFER 63
DHCPACK 139
DHCPNAK 2
Router1#

This command displays the high-level DHCP statistics, including the number of bindings, address pools, as well as the number of sent and received messages.

See Also

DHCP-Secured IP Address Assignment

DHCP-Secured IP Address Assignment

Problem

You wish to synchronize the ARP entries to the DHCP bindings to prevent IP address spoofing.

Solution

To enable secured IP address assignment, use the update arp command:

Router1#configure terminal 
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#ip dhcp pool OREILLY
Router1(dhcp-config)#update arp
Router1(dhcp-config)#end
Router1#

Discussion

Beginning with IOS Version 12.2(15)T, Cisco introduced the concept of DHCP secured IP address assignment. This feature synchronizes the ARP entry to the DHCP binding to ensure that IP addresses assign via DHCP can't be spoofed. By default, ARP tables dynamically map MAC addresses to IP addresses to facilitate communication. Unfortunately, it's rather easy for someone to spoof a DHCP assigned IP address and overwrite the router's ARP cache with his own MAC address.

Once the DHCP-secured IP address assignment is enabled, the router adds a secured ARP entry for each DHCP binding. This ensures that the ARP entry cannot be dynamically, or even manually, erased or overwritten. In fact, the only way to clear a secured ARP entry is by releasing the DHCP lease.

The following is an example configuration of DHCP-secured IP address assignment:

Router1#configure terminal 
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#ip dhcp pool OREILLY
Router1(dhcp-config)#network 172.25.1.0 255.255.255.0
Router1(dhcp-config)#default-router 172.25.1.1
Router1(dhcp-config)#dns-server 172.25.1.1 172.25.1.3
Router1(dhcp-config)#domain-name oreilly.com
Router1(dhcp-config)#lease 3
Router1(dhcp-config)#update arp
Router1(dhcp-config)#end
Router1#

Once configured, the router will provide DHCP leases as normal; however, for each new binding, the router will also add a secured ARP entry. All of this is completely transparent to the end users. The next example shows three newly assigned DHCP leases:

Router1#show ip dhcp binding
Bindings from all pools not associated with VRF:
IP address Client-ID/ Lease expiration Type
Hardware address/
User name
172.25.1.51 0100.0d60.b21a.4c Aug 24 2006 04:20 PM Automatic
172.25.1.52 0100.104b.33da.73 Aug 24 2006 04:22 PM Automatic
172.25.1.53 0100.0475.839d.3f Aug 24 2006 04:48 PM Automatic
Router1#

To confirm that the router has indeed created secured ARP entries, use the following command:

Router1#show ip dhcp server statistics
Memory usage 108579
Address pools 1
Database agents 0
Automatic bindings 3
Manual bindings 0
Expired bindings 0
Malformed messages 0
Secure arp entries 3

Message Received
BOOTREQUEST 0
DHCPDISCOVER 135
DHCPREQUEST 18
DHCPDECLINE 0
DHCPRELEASE 13
DHCPINFORM 0

Message Sent
BOOTREPLY 0
DHCPOFFER 24
DHCPACK 13
DHCPNAK 1
Router1#

Notice that the router has three new secured ARP entries, as highlighted in the previous example.

You can add the update arp command to existing DHCP pools; however, the router will only create secured ARP entries once existing leases are renewed. Once leases are renewed, the router will automatically create secured ARP entries for the renewed DHCP bindings.


As we mentioned earlier, secured ARP entries cannot be erased manually. For instance, clearing the router's ARP cache does not erase the secured ARP entries:

Router1#clear arp-cache

Router1#show arp
Protocol Address Age (min) Hardware Addr Type Interface
Internet 10.1.1.1 - 000e.8424.4e71 ARPA FastEthernet0/1
Internet 10.1.1.17 0 000d.bcef.f638 ARPA FastEthernet0/1
Internet 172.25.1.52 31 0010.4b33.da73 ARPA FastEthernet0/0
Internet 172.25.1.53 25 0004.7583.9d3f ARPA FastEthernet0/0
Internet 172.25.1.51 33 000d.60b2.1a4c ARPA FastEthernet0/0
Internet 172.25.1.5 0 0001.9670.b780 ARPA FastEthernet0/0
Internet 172.25.1.1 0 0010.4b09.5700 ARPA FastEthernet0/0
Internet 172.25.1.3 0 000a.5e40.0126 ARPA FastEthernet0/0
Internet 172.25.1.101 - 000e.8424.4e70 ARPA FastEthernet0/0
Router1#

Notice that the age of the secured ARP entries remained the same even after we cleared the ARP cache. The secured ARP entries will remain in the ARP cache until the associated DHCP lease is terminated by either the client or DHCP server.

The router can only secure directly connected clients on LAN interfaces.

DHCP Static Mapping

DHCP Static Mapping

Problem

You want to enable the assignment of static IP addresses from a text file.

Solution

To enable the assignment of static IP addresses from a text file, first you must create a static DHCP mapping file on your TFTP server:

Freebsd% cat /tftpboot/dhcp.static
*time* Aug 17 2006 03:52 PM

*version* 2

!IP address Type Hardware address Lease expiration

10.1.1.16 /24 id 0100.104b.33da.74 Infinite
10.1.1.17 /24 id 0100.0dbc.eff6.38 Infinite
10.1.1.18 /24 id 0100.0a5e.4001.27 Infinite
10.1.1.19 /24 id 0100.0331.327e.41 Infinite
10.1.1.20 /24 id 0100.0d60.b21a.4c Infinite

*end*
Freebsd%

To enable the router to read the static text file from the TFTP server, use the origin file command:

Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#ip dhcp pool OREILLY
Router1(dhcp-config)#origin file tftp://172.25.1.1/dhcp.static
Router1(dhcp-config)#default-router 10.1.1.1
Router1(dhcp-config)#dns-server 172.25.1.1 172.25.1.3
Router1(dhcp-config)#domain-name oreilly.com
Router1(dhcp-config)#lease 3
Router1(dhcp-config)#end
Router1#

Discussion

As demonstrated in Recipe 20.7, we can statically bind IP addresses to hardware addresses; however, doing so requires a dedicated DHCP pool, and more importantly, many lines of configuration. For instance, the following is a sample configuration for a single statically mapped IP address:

Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#ip dhcp pool IAN
Router1(dhcp-config)#host 172.25.1.33 255.255.255.0
Router1(dhcp-config)#client-identifier 0100.0103.85e9.87
Router1(dhcp-config)#default-router 172.25.1.1
Router1(dhcp-config)#domain-name oreilly.com
Router1(dhcp-config)#dns-server 172.25.1.1
Router1(dhcp-config)#end
Router1#

While this method of assigning static IP addresses is useful for sites with a few required static addresses, it doesn't scale well when you need to assign a large number of them. Building a new DHCP pool per static address not only consumes NVRAM space, but also clutters the router configuration file.

Beginning with IOS Version 12.3(11)T, Cisco supports the ability to assign static IP address via text files. To begin, you must first create the static mapping text file on your TFTP server. There is no limit to the number of static entries you can add to the file; however, the file must follow a certain format. The following is an example text file:

Freebsd% cat /tftpboot/dhcp.static
*time* Aug 17 2006 03:52 PM

*version* 2

!IP address Type Hardware address Lease expiration

10.1.1.16 /24 id 0100.104b.33da.74 Infinite
10.1.1.17 /24 id 0100.0dbc.eff6.38 Infinite
10.1.1.18 /24 id 0100.0a5e.4001.27 Infinite
10.1.1.19 /24 id 0100.0331.327e.41 Infinite
10.1.1.20 /24 id 0100.0d60.b21a.4c Infinite

*end*
Freebsd%

The file must contain the following elements:

  • Time the file was created

  • Database version number

  • IP address, including mask (must have a space before the mask)

  • Hardware type

  • Hardware address

  • Lease expiration

  • End of file designator

For more information regarding the elements of this file, see the Discussion section of Recipe 20.7.

Once you've created the static mapping text file, you can configure the router to read the file by using the origin file command:

Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#ip dhcp pool OREILLY
Router1(dhcp-config)#origin file tftp://172.25.1.1/dhcp.static
Router1(dhcp-config)#end
Router1#

Use the show ip dhcp binding command to ensure that the static mapping text file loaded correctly:

Router1#show ip dhcp binding 
Bindings from all pools not associated with VRF:
IP address Client-ID/ Lease expiration Type
Hardware address/
User name
10.1.1.16/24 0100.104b.33da.74 Infinite Static
10.1.1.17/24 0100.0dbc.eff6.38 Infinite Static
10.1.1.18/24 0100.0a5e.4001.27 Infinite Static
10.1.1.19/24 0100.0331.327e.41 Infinite Static
10.1.1.20/24 0100.0d60.b21a.4c Infinite Static
Router1#

You will notice that the static mapping have been loaded from the text file and the router is now ready to assign IP addresses based on the static mapping. If you modify the static mapping text file to add, change, or remove entries, then you need to disabled the DHCP server and start it again by removing the DHCP service. By doing so, the router will TFTP the new static mapping file:

Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#no service dhcp
Router1(config)#service dhcp
Router1(config)#end
Router1#

See Also