ASA NAT feels mysterious right up until the moment you understand the table. Once you can picture the sections, read them top to bottom, and see that the first matching rule wins, every "why did that packet get translated by the wrong rule" question answers itself. This is the single mental model that makes Cisco ASA NAT stop being a guessing game, and the good news is that the firewall shows you the whole table in one command.
This article is part of the Cisco ASA cluster. It is the companion to the NAT order of operations article: that one covers the phase order (what the ASA does to a packet, un-NAT then ACL then route), while this one covers the table order (which of your configured NAT rules the ASA picks in the first place). You need both to reason about a real firewall. Here we work from live show nat output on an ASAv, with an identity NAT and a server publish sitting in different sections, and prove which rule a real flow hits.
The Three Sections (Plus a Hidden One)
Every NAT rule you configure on an ASA lands in one of three numbered sections, and the ASA evaluates them strictly in order. There is also a section zero you do not write yourself but will see in the output, so it is worth knowing all four:
nlp_* entries)nat (x,y) source ... destination ...nat inside object networknat (x,y) ... after-autoThe rule to memorise is short: Section 1, then Section 2, then Section 3, top to bottom, first match wins. The moment a packet matches a rule, the ASA stops looking. Nothing below that rule gets a vote. Section 0 sits above all of it and is the firewall's own housekeeping, so you rarely think about it, but recognising the nlp_* entries stops them from confusing you when you read the table.
The Whole Table in One Command
Here is the payoff. A single show nat prints every section at once, in evaluation order, with per-rule hit counters. This output, from the lab ASAv, is the centrepiece of the whole topic because it shows the sections coexisting:
FW1# show nat
Manual NAT Policies Implicit (Section 0)
1 (nlp_int_tap) to (inside) source static nlp_server__snmp_... service udp snmp snmp
translate_hits = 0, untranslate_hits = 0
2 (nlp_int_tap) to (outside) source static nlp_server__ssh_0.0.0.0_intf2 interface ... service tcp 4122 ssh
translate_hits = 32, untranslate_hits = 32
... (system management NAT, sections you did not write) ...
Manual NAT Policies (Section 1)
1 (inside) to (dmz) source static INSIDE-NET INSIDE-NET destination static DMZ-NET DMZ-NET
translate_hits = 0, untranslate_hits = 0
Auto NAT Policies (Section 2)
1 (dmz) to (outside) source static DMZ-WEB DMZ-WEB-PUB
translate_hits = 0, untranslate_hits = 7Read it from the top. Section 0 holds the system's own management NAT (the SSH-to-the-box rule has 32 hits, which is just administrators logging in). You did not write those and you should not touch them. Then Section 1 holds our identity NAT, the inside-to-DMZ exemption that translates nothing. Then Section 2 holds our server publish, the object NAT that maps the DMZ web server to a public IP. Three different kinds of rule, three different sections, one command, in the exact order the ASA will consult them.
Why the Section a Rule Lands In Is the Priority
Here is the teaching point that this table proves, and it is the crux of ASA NAT design. Our identity NAT is a manual rule, so it sits in Section 1. Our server publish is an auto rule, so it sits in Section 2. If a single packet could plausibly match both, the Section 1 rule wins, because Section 1 is evaluated first and the first match ends the search.
That is not an accident you have to design around; it is a feature you design with. You never assign explicit priority numbers to ASA NAT rules the way you might sequence a route-map. Instead, you choose the rule type based on where you want it to land:
- Specific exemptions go in as manual (twice) NAT so they land in Section 1 and get first look. A NAT-exemption rule for VPN traffic has to win over your general PAT, and putting it in Section 1 guarantees that.
- General translations go in as auto (object) NAT so they land in Section 2 and only catch what the exemptions did not. Your broad outbound PAT and your server publishes belong here.
- True catch-alls go in as manual after-auto so they land in Section 3 and run only if nothing above matched.
Choose the type, and the section ordering does the prioritisation for you. This is why the advice "write exemptions as twice NAT and general rules as object NAT" is not a style preference; it is how you control which rule wins.
Order Within a Section
Sections set the coarse priority, but there is a finer level too. Within Section 1 and Section 3, manual NAT rules are evaluated in the order you enter them, top to bottom, and you can control that order explicitly (inserting a rule at a specific line). So the full precedence is: Section 1 rules in configured order, then Section 2, then Section 3 rules in configured order.
Section 2 (auto NAT) is different. You do not control its order by hand; the ASA orders object NAT rules automatically, roughly most-specific first (static before dynamic, smaller prefixes before larger). That automatic ordering is usually what you want, and it is another reason to keep general translations in Section 2 and reserve manual sections for the cases where you genuinely need to dictate sequence.
Where Section 3 (after-auto) Actually Earns Its Keep
Section 3 is the one most engineers never touch, and that is usually correct, but it exists for a real reason. Manual NAT normally lands in Section 1, above your object NAT. Sometimes you want a manual rule (say, a broad policy translation that depends on both source and destination) but you want it to run after your specific object NAT rules, not before them. Adding after-auto to the manual statement moves it from Section 1 to Section 3, so it becomes a fallback rather than a first responder.
The classic case is a general catch-all written as twice NAT. If you put it in Section 1, it would shadow your object NAT publishes and PAT rules, grabbing traffic before the more specific rules got a chance. Push it into Section 3 with after-auto and it only fires for whatever the object NAT rules in Section 2 left unmatched. The lesson is that "manual NAT" and "Section 1" are not the same thing: a manual rule is Section 1 by default, but after-auto lets you demote it to Section 3 when you want auto NAT to win.
If you ever find a manual NAT rule that seems to be losing to an object NAT rule you expected it to beat, check for after-auto on the statement. That one keyword changes which section the rule lives in and therefore which rule wins, and it is easy to miss when scanning a running config.
Proving Which Rule a Real Flow Hit
Knowing the theory is one thing; proving which rule a live packet actually matched is what you do at 2 a.m. when something is translated wrong. There are two tools, and they agree with each other.
The first is the set of hit counters in show nat. Every rule carries translate_hits (outbound, source translation) and untranslate_hits (inbound, destination un-translation). In the table above, the Section 2 publish shows untranslate_hits = 7: seven inbound connections have un-NATed through it. If you expect a flow to hit a particular rule and its counters are not moving, the flow is matching something else, and the counters on the other rules will tell you which. Watching the counters move, or fail to move, while you generate traffic is the most direct evidence there is.
The second tool is packet-tracer, which simulates a specific packet and names the exact rule it matched in the UN-NAT phase (it prints the matching Config: block). Between the two, you never have to guess: the counters tell you what real traffic did in aggregate, and packet-tracer tells you what one specific flow will do and why. The deeper walk through the ASA's per-packet processing, where NAT sits relative to the route lookup and the interface ACL, is in the ASA packet flow article.
A Worked Example: Two Rules, One Packet
Tie it together with the two rules from our table. Suppose an inside host at 10.20.10.100 opens a connection to the DMZ web server at 172.20.30.80. Which rule handles it?
The ASA starts at Section 0 (management NAT, no match for this traffic), then Section 1. There it finds the identity NAT: source static INSIDE-NET INSIDE-NET destination static DMZ-NET DMZ-NET. Our packet is inside-to-DMZ, both networks match, and the rule fires. First match wins, so the search stops right there. The Section 2 publish rule never even gets considered for this flow, because it lives below a rule that already matched. The inside host reaches the DMZ server with its real address intact, exactly as the exemption intends.
Now flip it: an outside client hits 203.0.113.80. Section 0 has no match, Section 1's identity rule is scoped to inside-to-DMZ so it does not match outside-to-DMZ traffic, and the search falls through to Section 2, where the object NAT publish un-NATs the destination to 172.20.30.80. Same firewall, same table, two flows, two different rules, and the section order decided each one. That is the entire model.
Reading the Table Like a Pro
A few habits turn show nat from a wall of text into a diagnostic instrument. First, always read it top to bottom and mentally note the section headers as you go; the ASA prints them for you (Manual NAT Policies (Section 1), Auto NAT Policies (Section 2)), so you never have to guess which section a rule is in. Second, treat the Section 0 nlp_* entries as background noise for your own troubleshooting; they are the firewall managing access to itself, and a hit count climbing there is just administrative traffic, not your data plane.
Third, use the counters as a story. A publish rule with untranslate_hits steadily climbing is being reached by inbound clients. An exemption rule with flat counters while its traffic clearly flows is being shadowed by a rule above it, which points you straight at a section-ordering problem. Fourth, when in doubt, do not argue with the config in your head; run packet-tracer for the exact flow and let the firewall tell you which rule wins. The table order is deterministic, so packet-tracer's answer is authoritative.
Put those four habits together and NAT troubleshooting collapses into a short checklist: identify the flow, find the first rule in section order that could match it, confirm with the counters or packet-tracer, and fix the placement if the wrong rule is winning. There is no hidden magic in ASA NAT once you can read the table the way the firewall evaluates it.
Key Takeaways
- ASA NAT has three sections you write, plus a hidden Section 0. Section 1 is manual (twice) NAT, Section 2 is auto (object) NAT, Section 3 is manual after-auto, and Section 0 is the system's own management NAT.
- Evaluation is top to bottom, first match wins. The moment a packet matches a rule the ASA stops looking, so a Section 1 rule beats a Section 2 rule for the same packet.
- The section a rule lands in is its priority. Write specific exemptions as manual NAT (Section 1) and general translations as object NAT (Section 2); the section ordering does the prioritising for you.
- show nat prints the whole table at once. Every section in evaluation order, with per-rule
translate_hitsanduntranslate_hits. - Prove which rule a flow hit two ways. Watch the hit counters move under real traffic, and use
packet-tracerto see the exact matching rule for one simulated flow.
The table order and the phase order are two halves of the same skill. Pair this with the NAT order of operations and the rest of the Cisco ASA cluster to reason confidently about any flow through the firewall.