Monday, March 24, 2014

ASA pre-8.3 vs post-8.3 NAT explained

In ASA software version 8.3(1), Cisco completely restructured ASA NAT syntax.  Quite a bit has already been written about these changes. However, since this is often a cause of confusion, I will try to provide an explanation of three of the most commonly used forms of NAT on an ASA: dynamic PAT, static NAT, and "nonat."  Below you'll find pre-8.3 and post-8.3 configuration examples with translations into into plain English.  Please feel free to comment if you have any questions.

What is NAT?

I'll start with the basics.  NAT stands for network address translation.  It translates the real IP address of a device to the mapped IP and vice versa.

Real IP: the actual IP address of the device generating the traffic (on the inside interface in the examples below)
Mapped IP: the IP address the ASA translates the real IP address to (on the outside interface in the examples below).

NAT is most often used to translate private RFC 1918 IP addresses to publicly routable IP addresses (there are other less common uses as well).

For example:
A ping is sent from TestVM ( to R1 (  In this example, R1 is on the internet, so the ASA cannot route the private address of to R1.  It must NAT the packet.

We can see this happen in the Wireshark captures below:

  • When the ASA receives the packet on its inside interface, the source is and the destination is  The packet header is re-written, and the packet is sent out the outside interface with a source address of  The destination address is not changed.  
  • When the return traffic is received on the outside interface with a destination IP of, the packet header is once again re-written.  The packet is sent out the inside interface with a destination IP of  The source address is not changed.

On to the configuration examples...

Dynamic PAT - many-to-one

PAT stands for port address translation.  It is many to one NAT translation.  This is what some vendors simply refer to as NAT.  It is more accurately called PAT because in order to translate many IPs to one IP, randomly selected ephermal ports must be used on the mapped IP address.  When return traffic is received, the ASA must check the xlate table (NAT translation table) in order to determine where to send the return traffic.

Here is the xlate table from the example ping above:
asa01# sh xlate
1 in use, 1 most used
Flags: D - DNS, i - dynamic, r - portmap, s - static, I - identity, T - twice
ICMP PAT from inside: to outside: flags ri idle 0:00:09 timeout 0:00:30


asa01(config)# nat (inside) 1
asa01(config)# global (outside) 1 interface
INFO: outside interface address added to PAT pool

This configuration says: Translate any traffic received on the inside interface from (NAT ID 1) to the corresponding global PAT pool.  In this case, nat (inside) 1 corresponds to global (outside) 1, so anything from is translated to the outside interface IP.  Return traffic will be translated back to the real IP address by checking the xlate table for the appropriate translation.

You could also use an IP address or range of IP addresses in place of the word "interface" in the global statement.  If you were to use a range of IP addresses in the global statement, you would have a many-to-many dynamic NAT instead of many-to-one dynamic PAT.


asa01(config)# object network inside-network
asa01(config-network-object)# subnet
asa01(config-network-object)# nat (inside,outside) dynamic interface

This configuration says: Define a network object for subnet  Any traffic received on the inside interface that matches this network object, translate to the outside interface IP address.  Return traffic will be translated back to the real IP address by checking the xlate table for the appropriate translation.

Show run output:
asa01# sh run object
object network inside-network
asa01# sh run nat
object network inside-network
 nat (inside,outside) dynamic interface

Notice when we configure object NAT in 8.3+, we configure both the subnet and the NAT under the same network object.  However, they appear separately in the show run output.  As with pre-8.3 config, we can also specify a specific IP or range of IPs for the translation.

Static NAT - one to one

Static NAT translates a single real IP to a single mapped IP.  This is commonly used to NAT a device on the inside or DMZ of an ASA to a static IP on the subnet of the outside interface.


asa01 (config)# static (inside,outside) netmask


object network inside-host
 nat (inside,outside) static

Both of the above say the following: Traffic that is received on the inside interface from, translate to on the outside interface, and vice versa.

In 8.2(5) and earlier, the syntax is static (inside,outside) [outside ip] [inside ip] netmask [netmask].  I find this syntax to be counter intuitive, because it reads (inside,outside) and then outside inside.  I am not aware of any logical reason for this.

I find 8.3+ syntax to be easier to read, however it does dramatically increase the number of lines per NAT statement.  As with the PAT example above, if you look at the show run output you will see the object listed twice - once to define the host and once to define the static NAT.  Therefore, what took a single line in 8.2(5) now takes four lines in 8.3(1) and above.

Both 8.3+ configuration examples so far have used network object NAT.  Object NAT is easy to use, but somewhat limited and only takes into account the source address.  If we need more control over our NAT statements, we can use twice NAT, which I will cover in greater detail in a future post.

No-nat (NAT exemption & identity NAT)

There are certain circumstances when traffic is being translated on an ASA, but we do not want this traffic to be translated when destined to specific subnets.  The most common example is VPN traffic.  We want the source address of the VPN traffic to have the real IP, not the mapped IP, for obvious reasons.


access-list nonat extended permit ip
nat (inside) 0 access-list nonat

In ASA 8.2(5) and earlier, this is called NAT exemption.  This says: define an extended access list (in this case nonat) and specify the appropriate source and destination traffic.  Any traffic received on the inside interface that matches this access list, use NAT ID 0.  NAT ID 0 exempts the traffic from being translated.


asa01(config)# object network inside-network
asa01(config-network-object)# subnet
asa01(config)# object network remote-network
asa01(config-network-object)# subnet
asa01(config)# nat (inside,outside) source static inside-network inside-network destination static remote-network remote-network

In ASA 8.3(1) and above, NAT exemption no longer exists.  This can now only be accomplished by using identity NAT.  Identity NAT is a form of twice NAT, which allows us to specify both source and destination in our NAT statements.  In the above configuration example, we define two network objects: inside-network and remote-network.  We then configure an identity NAT statement that tells the ASA not to NAT the traffic.

The structure of the identity NAT statement is as follows:
nat (real_interface,mapped_interface) source static real_object mapped_object destination static mapped_object real_object

So the example above says: Any traffic received on the inside interface from inside-network destined to remote-network translate to the source to inside-network and the destination to remote-network (ie. don't NAT it).

This is clearly less intuitive than the 8.2(5) syntax, but it's not that bad once you get used to it.

That's it?

Nope.  These are just a few examples of common NAT configurations. I will follow up with a more comprehensive post to dive deeper into the different types of post-8.3 NAT (object NAT & twice NAT) as well as the explain some of the intricacies of both pre and post-8.3 NAT: order of operations, no-proxy-arp, route-lookup, etc.

I planned to update this post with a deep dive into different ASA NAT types. However, I stumbled across an extremely thorough NAT write-up. I suggest anyone looking for more information on ASA 8.3+ NAT check out the this post:

Here are additional resources that I found helpful: