Every packet that enters a Cisco ASA goes through a deterministic series of checks before it is forwarded, dropped, or handed to the VPN engine. Understanding that order is the difference between fixing an outage in two minutes and chasing the wrong layer for an hour. This article walks the full ASA packet flow on software 9.x, with a worked example from our lab, and pins each step to the configuration block you would inspect when something fails.
It is part of the Cisco ASA Complete Guide on PingLabz. After this read, the next stop is usually Cisco ASA packet-tracer, which simulates this exact flow against any source-destination pair you give it.
The Nine Steps of ASA Packet Flow
For a TCP or UDP packet entering an ASA interface, the data plane evaluates these phases in order:
| Step | Phase name | What happens | Configuration that controls it |
|---|---|---|---|
| 1 | Existing connection lookup | If the 5-tuple matches an existing connection in the state table, skip directly to step 7. | Connection table (show conn), TCP/UDP/ICMP timeouts. |
| 2 | IP options / fragment / TCP-state checks | Drops malformed packets, fragmented packets without an existing flow if assembly is required, TCP packets that violate state-machine expectations. | fragment, set connection, default state check. |
| 3 | NAT untranslate (UN-NAT) | If the destination is a translated address, reverse the NAT to find the real destination. The ACL check uses the real destination. | Auto NAT static rules, Manual NAT static rules. |
| 4 | ACL check | Evaluate the inbound ACL against the real source and real destination. | access-list + access-group ... in interface. |
| 5 | NAT translate | Apply the forward NAT rule (auto or manual). Source is translated, destination may also be translated. | Same as UN-NAT, but evaluated forward. |
| 6 | Route lookup | Pick the egress interface based on the global routing table. | Static routes, OSPF, BGP, EIGRP. |
| 7 | Adjacency / ARP | Resolve the next-hop MAC address. If no adjacency, drop with no-adjacency. | arp, ND for IPv6. |
| 8 | Egress interface checks | Output ACL (rare), QoS policies, inspection engines (FTP, HTTP, SIP, etc.). | MPF (modular policy framework), inspection maps. |
| 9 | Forward | Packet is sent out the egress interface. Connection-table entry is updated or created. | None - this is the success path. |
Several things to notice about this sequence:
- Existing connections short-circuit the whole flow. Once a session is permitted and added to the state table, subsequent packets in either direction skip the security and ACL checks entirely. This is what "stateful firewall" means in practice. Return packets do not need a return ACL.
- NAT untranslate happens before the ACL check. This is the single biggest difference from IOS routers. Your ACL rules permit destinations by their real (untranslated) IP, even on the outside interface where the destination hits as a public NAT address.
- NAT translate happens between ACL and route lookup. The packet is translated to its egress form before the route is selected. This matters for asymmetric path scenarios and for VPN policies.
- Route lookup is global, not per-VRF. Standard ASA software does not have VRFs. Multiple security contexts give per-context routing tables, but a single context has one global table.
Worked Example: Inside to Outside (PAT)
An inside host at 10.10.10.50 opens a TCP connection to 8.8.8.8 on port 443. The ASA flow:
- Existing-connection lookup. The first packet (TCP SYN) does not match any existing connection. Continue.
- Sanity checks. SYN flag set, no IP options to drop on, IP TTL above 1. Continue.
- UN-NAT. Destination is 8.8.8.8, no static NAT or twice NAT translates 8.8.8.8 to anything else. Real destination remains 8.8.8.8.
- ACL check. Inside is security-level 100, outside is 0. The implicit rule (high-to-low) allows. No explicit ACL needed on the inside interface for this traffic.
- NAT translate. Source 10.10.10.50 matches Auto NAT under
object network INSIDE-NETwith rulenat (inside,outside) dynamic interface. Source is translated to the outside interface IP (203.0.113.2) with PAT. - Route lookup. 8.8.8.8 matches the default route via 203.0.113.1, egress interface outside.
- Adjacency. ARP resolves 203.0.113.1.
- Egress checks. No outbound ACL on outside, no inspection that matters here.
- Forward. Packet is sent. A new connection-table entry is created keyed on (10.10.10.50:src-port, 8.8.8.8:443) plus the translated (203.0.113.2:src-port, 8.8.8.8:443) tuple. The reply will match this entry and skip steps 2-6.
This is what packet-tracer would show as a 6-phase ALLOW sequence. Read Cisco ASA packet-tracer Command: Complete Troubleshooting Guide for the syntax that simulates exactly this flow on demand.
Worked Example: Outside to DMZ (Static NAT)
A user on the internet hits 198.51.100.10 (the public IP of a DMZ web server) on TCP/443. The ASA flow:
- Existing-connection lookup. First packet, no match.
- Sanity checks. Pass.
- UN-NAT. Destination 198.51.100.10 matches the static NAT under
object network DMZ-WEB. Real destination is 192.168.50.10. The packet's destination IP is conceptually replaced from now until step 5 forward. - ACL check. Outside ACL
OUTSIDE_INevaluates against destination 192.168.50.10 (real IP) on TCP/443. Permit line matches:permit tcp any object DMZ-WEB eq 443. Continue. - NAT translate. Forward NAT rule for the same DMZ-WEB object. Translation is symmetric (same rule provides both untranslate and translate).
- Route lookup. 192.168.50.10 is on directly-connected subnet 192.168.50.0/24, egress interface dmz.
- Adjacency. ARP resolves 192.168.50.10.
- Egress checks. No DMZ outbound ACL, default inspection.
- Forward. A connection-table entry is created. The reply path will match it and skip ACL.
The critical insight: the ACL on outside permits to the real IP 192.168.50.10, not the public IP 198.51.100.10. This is the single most-misunderstood ASA detail.
Get the Cisco ASA Field Reference - 9 pages, free
Everything you'd want to remember about Cisco ASA on nine printable pages. Per-packet pipeline diagram, NAT 8.3+ section ordering, six-branch troubleshooting decision tree, real lab show-output annotated, paste-ready three-zone config. Free for PingLabz members - just sign up with your email.
When Things Fail: Where in the Flow It Drops
The phase that drops a packet tells you which configuration block to inspect. The mapping:
| Failed phase | What to check |
|---|---|
| UN-NAT | Static NAT rule. Did you forget to publish the public IP? Is the object referencing the right interface pair? |
| ACL check | Inbound ACL on the ingress interface. Is the rule using the real destination IP? Is the protocol/port right? Is the ACL applied with access-group ... in interface? |
| NAT translate | Forward NAT. Most often this is a missing dynamic NAT (the source has nowhere to translate to) or an Auto vs Manual NAT ordering issue. |
| Route lookup | Routing table. Is there a route to the destination? Is it via the expected egress interface? |
| Adjacency | ARP / next-hop reachability. Run show arp and ping the next-hop. |
| Egress checks | Any outbound ACL on the egress interface, plus inspection. Most ASA outages are upstream of this. |
Combined with packet-tracer, this lookup table covers most ASA outage triage. The full data-plane drop counter list is in Cisco ASA asp-drop Counters Explained.
The Connection Table: Why Step 1 Matters
The state table is what makes the ASA stateful. After step 9 of any successful flow, the ASA inserts an entry. Future packets matching that 5-tuple skip steps 2-6 entirely. This has three operational consequences:
- Return traffic does not need an explicit allow ACL. The reply packet matches the existing connection and is forwarded.
- An ACL change does not break existing flows. If you remove a permit line that allowed an active connection, that connection keeps working until it is torn down or times out.
- Asymmetric routing breaks the model. If the reply packet enters through a different interface than the request egressed, the ASA does not see it as part of the existing flow and applies the full check-set, including ACL. This is the most common cause of "but my ACL allows it!" weirdness in dual-firewall, dual-ISP, or active-active failover designs.
show conn shows what is in the table right now. show conn count gives you a quick total. We cover the connection table in detail in Cisco ASA Connection Table and xlate Table Troubleshooting.
Related Articles
- Cisco ASA packet-tracer Command: Complete Troubleshooting Guide - simulates this exact flow on demand.
- Cisco ASA NAT Explained: Auto NAT vs Manual NAT - the model behind steps 3 and 5.
- Cisco ASA ACL Configuration: Inbound Rules and Object Groups - step 4 in detail.
- Cisco ASA Connection Table and xlate Table Troubleshooting - step 1 and step 5 verification.
- ASA vs Router ACLs: What Network Engineers Get Wrong - why ASA ACLs use real IPs.
- Cisco ASA Modular Policy Framework - what step 8 (egress inspection) actually does.
Key Takeaways
The ASA evaluates packets in nine deterministic phases: existing-connection lookup, sanity checks, NAT untranslate, ACL, NAT translate, route lookup, adjacency, egress checks, and forward. Existing connections short-circuit the security checks, which is what makes the firewall stateful. NAT untranslate happens before the ACL, which is why ASA ACLs reference the real destination IP. Knowing which phase drops a packet tells you exactly which configuration block to inspect, and packet-tracer walks every phase on demand against any flow you specify.