ASA

Cisco ASA packet-tracer Command: Complete Troubleshooting Guide

Cisco ASA packet-tracer Command: Complete Troubleshooting Guide
In: ASA

If you only learn one Cisco ASA troubleshooting command, make it packet-tracer. It simulates a single hypothetical packet through every ASA decision point - existing-connection lookup, security check, NAT untranslate, ACL, NAT translate, route lookup, egress checks - and tells you exactly where it would be allowed, dropped, or routed somewhere unexpected. No actual traffic is generated, no real session is opened, and you do not need to be on the inside or outside of the firewall to test. It is the closest thing the ASA has to a debugger.

This guide is part of the Cisco ASA Complete Guide on PingLabz. We cover the syntax, every common scenario (inside-to-outside PAT, outside-to-DMZ static NAT, ACL deny, NAT mismatch, VPN decryption), how to read the phase-by-phase output, the most useful flags, and the mistakes that make engineers misread results. All output is captured from a real ASAv 9.23 running in our lab.

Syntax Basics

The minimum form of packet-tracer takes five arguments: ingress interface, protocol, source IP, source port, destination IP, destination port. The ASA simulates one packet matching that 6-tuple, walks it through the data path, and prints the result.

packet-tracer input <ingress-interface> <protocol> <src-ip> <src-port> <dst-ip> <dst-port>

For TCP and UDP you give source and destination port. For ICMP you give type, code, and identifier instead. A typical inside-to-outside HTTPS test looks like this:

ASA-PERIM# packet-tracer input inside tcp 10.10.10.50 12345 8.8.8.8 443

And a typical outside-to-DMZ HTTP test (someone hitting the public IP of a DMZ web server) looks like this:

ASA-PERIM# packet-tracer input outside tcp 203.0.113.50 33000 198.51.100.10 80

Source IP and source port are usually arbitrary. The destination IP must be the real IP of the destination as it would appear on the wire from the ingress interface side - which is where engineers first get confused. We will come back to this.

Reading the Output: Phases and Final Verdict

Every packet-tracer run produces a series of phases, each phase representing one stage of the ASA data path. Each phase reports its type (ROUTE-LOOKUP, ACCESS-LIST, NAT, INSPECT, etc.), its action (allow or drop), and any matching configuration.

Here is what an inside-to-outside PAT lookup looks like on our lab ASA:

ASA-PERIM# packet-tracer input inside tcp 10.10.10.50 12345 8.8.8.8 443

Phase: 1
Type: ACCESS-LIST
Subtype:
Result: ALLOW
Elapsed time: 65404 ns
Config:
Implicit Rule
Additional Information:
MAC Access list

Phase: 2
Type: INPUT-ROUTE-LOOKUP
Subtype: Resolve Egress Interface
Result: ALLOW
Elapsed time: 21670 ns
Config:
Additional Information:
Found next-hop 203.0.113.1 using egress ifc  outside

Phase: 3
Type: NAT
Subtype:
Result: ALLOW
Elapsed time: 29681 ns
Config:
object network INSIDE-NET
 nat (inside,outside) dynamic interface
Additional Information:
Dynamic translate 10.10.10.50/12345 to 203.0.113.2/12345

Phase: 4
Type: NAT
Subtype: per-session
Result: ALLOW

Phase: 5
Type: IP-OPTIONS
Subtype:
Result: ALLOW

Phase: 6-7
Type: QOS
Result: ALLOW

Phase: 10
Type: FLOW-CREATION
Subtype:
Result: ALLOW
New flow created with id 4, packet dispatched to next module

Phase: 11
Type: INPUT-ROUTE-LOOKUP-FROM-OUTPUT-ROUTE-LOOKUP
Subtype: Resolve Preferred Egress interface
Result: ALLOW
Found next-hop 203.0.113.1 using egress ifc  outside

Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: outside
output-status: up
output-line-status: up
Action: drop
Time Taken: 282497 ns
Drop-reason: (no-v4-adjacency) No valid V4 adjacency. Check ARP table (show arp) has entry for nexthop.

Read it bottom-up: Action: drop, Drop-reason: no-v4-adjacency. The ASA simulated the flow successfully through every security and translation check, but the ARP cache does not yet have an entry for the next-hop 203.0.113.1, so it cannot synthesize the egress frame. This is a packet-tracer quirk you will see often on ASA software 9.x: every phase reports ALLOW, but the final action drops with no-v4-adjacency because no real packet has yet primed the ARP table. In production, real traffic would trigger ARP resolution and the same flow would forward. The lesson: read all the phase results, not just the final action. Every ALLOW phase confirms a configuration block is correct.

Read top-down to see how the ASA processed it: implicit ACL allowed (inside is high-security going to lower-security), route lookup found the egress, NAT translated the source from 10.10.10.50 to the outside interface IP (PAT, port 12345), QoS and IP-options checks passed, a flow entry was created, and the egress was confirmed. Every block of configuration that should have applied did apply. When the ARP table primes (real traffic, or after a quick ping 203.0.113.1), the same packet-tracer would return Action: allow.

When something goes wrong at a configuration layer, the matching phase has Result: DROP and the final Action: is drop, with a drop-reason that names the configuration block.

Scenario: ACL Drop

A user is reporting they cannot SSH to a public-facing DMZ host. We test from outside:

ASA-PERIM# packet-tracer input outside tcp 203.0.113.50 44000 198.51.100.10 22

Phase: 1
Type: UN-NAT
Subtype: static
Result: ALLOW
Elapsed time: 20882 ns
Config:
object network DMZ-WEB
 nat (dmz,outside) static 198.51.100.10
Additional Information:
NAT divert to egress interface dmz
Untranslate 198.51.100.10/22 to 192.168.50.10/22

Phase: 2
Type: ACCESS-LIST
Subtype:
Result: DROP
Elapsed time: 6304 ns
Config:
Implicit Rule
Additional Information:

Result:
input-interface: outside
input-status: up
input-line-status: up
output-interface: dmz
output-status: up
output-line-status: up
Action: drop
Time Taken: 27186 ns
Drop-reason: (acl-drop) Flow is denied by configured rule, Drop-location: frame snp_classify_table_lookup:6044 flow (NA)/NA

Two things to notice. First, Phase 1 (UN-NAT) shows the ASA correctly untranslating the public IP 198.51.100.10 to the real IP 192.168.50.10 - the static NAT is working. Second, Phase 2 (ACCESS-LIST) hits the implicit deny because OUTSIDE_IN only permits ports 80, 443, and ICMP to DMZ-WEB; port 22 falls through to the implicit deny at the bottom of the ACL. The fix is to add a permit line for SSH or scope the existing ones differently. The Drop-reason: acl-drop at the bottom is the verdict, captured directly from our ASAv 9.23 lab.

This is the canonical packet-tracer flow that proves an outage is an ACL problem and not a NAT, route, or inspection problem.

Scenario: NAT Mismatch

An engineer added a new VPN site-to-site tunnel and the tunnel comes up, but interesting traffic does not pass. The classic culprit is that interesting traffic is being NATed before being placed in the tunnel.

ASA-PERIM# packet-tracer input inside tcp 10.10.10.50 12345 10.20.0.50 443

Phase: 1
Type: ACCESS-LIST
Subtype:
Result: ALLOW
Config:
Implicit Rule

Phase: 2
Type: ROUTE-LOOKUP
Subtype: Resolve Egress Interface
Result: ALLOW
Config:
Additional Information:
found next-hop 203.0.113.1 using egress ifc outside

Phase: 3
Type: NAT
Subtype:
Result: ALLOW
Config:
object network INSIDE-NET
 nat (inside,outside) dynamic interface
Additional Information:
Dynamic translate 10.10.10.50/12345 to 203.0.113.2/12345

[...VPN encryption phases...]

Result:
Action: allow

This is wrong. The packet is destined for the remote VPN subnet 10.20.0.0/24, which should be carried untranslated through the IPsec tunnel. Instead, Phase 3 PATted it to the outside interface IP. The fix is a NAT exemption rule (also called identity NAT) placed in Section 1 (manual NAT, before auto NAT), so VPN traffic is matched first and not translated. We cover that pattern in detail in Cisco ASA VPN NAT Exemption: The Mistake That Breaks Tunnels.

Useful Flags

packet-tracer supports several flags that change what it tests. The ones worth knowing:

FlagWhat it does
detailedPrints additional debug-level information, including object-group expansion and ACL hit details.
xmlRenders the result as XML. Useful when scripting (paste into a Python parser).
vlan-id <n>Tags the simulated packet with a VLAN ID, useful when the ingress is a trunk subinterface.
icmp instead of tcp/udpFor ICMP, give type/code/identifier: packet-tracer input outside icmp 1.1.1.1 8 0 198.51.100.10
decryptedTests a packet as if it had already been decrypted by a VPN engine. Lets you simulate the inner-payload behavior.
persistThe simulated flow is kept in the connection table after the trace, so subsequent show conn can be used.

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.

Get the Cisco ASA cheat-sheet

Troubleshooting a Real Outage with packet-tracer

The fastest way to use packet-tracer during an incident is to test the exact source-to-destination 6-tuple the user is reporting, in both directions, from both perspectives. A four-step pattern that resolves most outages:

  1. Test the user's flow as reported. Type the same source IP, source port (any high port is fine), destination IP, and destination port the user gave you. Look at the final Action.
  2. If it allows but the flow still fails, the ASA is not the problem. Check the destination host, downstream firewall, or DNS.
  3. If it drops, look at the Drop-reason. If it is acl-drop, the ACL is the cause. If it is nat-no-xlate, NAT is the cause. If it is rpf-violated, asymmetric routing or anti-spoofing is biting you. The phase that matches the drop tells you which configuration block to fix.
  4. If you need to test the reverse direction (server-to-client), simulate it with packet-tracer ingress from the destination interface. ASA does not assume reciprocity; you must explicitly test both directions when troubleshooting return-traffic issues.

Combine this with packet capture to see what is actually arriving, and you have covered the gap between simulation and reality.

Common packet-tracer Drop Reasons

The drop-reason field is a controlled vocabulary. The ones that come up over and over in production:

Drop-reasonLikely cause
acl-dropThe interface ingress ACL denies the flow.
nat-no-xlate / nat-no-xlate-to-pat-poolNo NAT rule matches and the egress requires translation. Often a missing dynamic NAT or a mistakenly removed object NAT.
nat-rpf-failedNAT reverse-path forwarding check failed. Usually means the route the ASA picked does not match what NAT expected.
no-route / no-adjacencyThe ASA has no route or no ARP entry for the next-hop on the egress interface.
sp-security-failedAnti-spoofing (uRPF) rejected the source.
tcp-not-synThe first packet on a flow is not a SYN. Often a return packet from an asymmetric path.
inspect-icmp-error-different-embedded-connAn ICMP error came in for a flow the ASA does not have in its connection table. Frequently a sign of an asymmetric path.

Every one of these has a well-defined fix, and packet-tracer pinpoints which one applies before you start typing in the dark. Full counter explanations live in Cisco ASA asp-drop Counters Explained.

Common Mistakes

  • Testing the wrong destination IP. When testing from outside to a NATed server, use the public IP. When testing inside to inside (or DMZ to inside), use the real IP. The ASA's untranslate phase will handle the rest.
  • Forgetting that ACLs reference real IPs. ACL phase results show the real (untranslated) destination. If you wrote the ACL against the public IP, packet-tracer will show ACL-drop even when the public-to-private NAT works.
  • Trusting a single direction. An allow result for client-to-server does not guarantee server-to-client works. Test both.
  • Ignoring the implicit rule. Phase 1 often says "Implicit Rule" - that is the security-level default. Two interfaces at the same security level produce an implicit drop unless you have configured same-security-traffic permit.
  • Testing without enough info from the user. Without the actual source IP and destination port, packet-tracer is guesswork. Get the exact values from the user before you start.

Packet-tracer is most powerful in combination with these:

  • show conn detail - real connection table, what flows are actually open right now.
  • show xlate - the live NAT translation table.
  • show asp drop - data-plane drop counters since the last clear.
  • show access-list OUTSIDE_IN - per-line hit counters on a specific ACL.
  • capture CAP-NAME interface outside match tcp host 203.0.113.50 host 198.51.100.10 eq 80 - real packet capture filtered by ACL match.

Walk through every one of these in the Cisco ASA Cheat Sheet for the working command list, and the Connection Table and xlate Table Troubleshooting article for deeper coverage.

Key Takeaways

Packet-tracer simulates one synthetic packet through every ASA decision point and prints the verdict, no real traffic required. Read the output bottom-up for the action, top-down for the reasoning. The phase that drops the packet, plus its drop-reason, is the single most useful piece of troubleshooting data the ASA produces. Use it as the first command in any ASA outage investigation, and combine it with show conn, show xlate, and a real packet capture to bridge from simulation to reality.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.