NAT and PAT, Part 2

In Part 1 of this series, we discussed static NAT. While static NAT works, since it uses manually constructed “one-to-one” translations, it’s not scalable. For example, translating all of the legal host addresses on the 10.1.2.0/24 subnet would require 254 lines. And if we were dealing with the entire 10.0.0.0/8 network, covering all possible addresses would require over sixteen million lines! The solution is “dynamic NAT”.

In dynamic NAT, instead of specifying the translations one-by-one, you give the NAT device some rules that specify which addresses are translated to what. In the case of a Cisco router, the addresses to be translated are specified by an access control list (ACL), and the addresses to which they are translated are specified by a “pool”.

For example, to translate any address on the 10.1.2.0/24 subnet (those permitted by ACL 1) to an address on the 200.1.2.0/24 network (as specified by the pool named “Test”), you could do this:

  • Router(config)#ip nat inside source list 1 pool Test

The translation tells the router that if a packet with source address matching a permit in ACL 1 hits the inside interface, and it is bound for the outside interface, translate the source address to an available address in the pool named “Test”. Obviously, you also need to create ACL 1 and the pool “Test”. Let’s create the ACL first:

  • Router(config)#access-list 1 permit 10.1.2.0 0.0.0.255

As is the usual case with a standard IP ACL, this list specifies the source address. Remember that ACLs use a wildcard (inverse) mask. Now, let’s create the pool named “Test” (pool names are case-sensitive):

  • Router(config)#ip nat pool Test 200.1.2.0 200.1.2.127 netmask 255.255.255.0

The “netmask” specified for the pool is the subnet mask of the network or subnet containing the translated addresses, and this is not a wildcard (inverse) mask. If you prefer, you can specify the pool’s mask using “slash” (“bitcount”, “CIDR”) notation by using the “prefix-length” option:

  • Router(config)#ip nat pool Test 200.1.2.0 200.1.2.127 prefix-length 24

Notice that while the ACL covers 254 addresses, the pool only specifies 127 addresses (due to the “255.255.255.0” or “/24” mask, the pool knows that the address 200.1.2.0 is not legal). Why specify only 127 addresses? First, it’s not likely that all 254 host addresses are actually in use. Second, even if they are in use, it’s not likely that all 254 hosts are simultaneously trying to access the Internet (the company may run several work shifts, for example). The size of the pool only needs to cover the number of hosts that simultaneously require translation, and this conserves public IP addresses (a good thing). Also, if the public addresses are being rented from a provider (typically the case), conserving public IP addresses can save money.

Finally, if it hasn’t already been done, the “inside” and “outside” interfaces must be assigned, just as with static NAT. Let’s assume that FastEthernet0/1 is on the inside, and Serial1/2 is on the outside:

  • Router(config)#interface fa0/1
  • Router(config-if)#ip nat inside
  • Router(config-if)#int s1/2
  • Router(config-if)#ip nat outside

If we view the translation table (show ip nat translations) at this point, we would see no entries, because no traffic matching the ACL has attempted to traverse the router from “inside” to “outside”. To trigger a translation, we generate traffic from an “inside” host that’s destined for an “outside” host.

For TCP, entries are placed in the table when a session is built (when the NAT device sees the “SYN” marking the start of a three-way handshake) and removed when the session is terminated. For UDP and ICMP, the translation table entries are created with the first packet in a particular data stream, and the entries are removed when an inactivity timer expires.

Next time, we’ll examine PAT, a variation of dynamic NAT.

Author: Al Friebe

In this article

Join the Conversation