ASA

Cisco ASA Dynamic PAT Configuration for Internet Access

Cisco ASA Dynamic PAT Configuration for Internet Access
In: ASA

Almost every Cisco ASA in the world runs the same outbound NAT rule: take everything coming from the inside subnets and translate it to the outside interface IP, port-mapped. That is dynamic Port Address Translation, and it is the rule that keeps the entire user side of the network connected to the internet.

This article is the field reference for that rule on Cisco ASA software 9.x. We cover what dynamic PAT is doing, the exact configuration on a real ASAv, the show commands that prove it is working, and the failure modes you will eventually see in production. For the broader cluster context, see the Cisco ASA pillar; for what NAT looks like across the whole platform, see Cisco ASA NAT Explained.

What Dynamic PAT Actually Does

Dynamic PAT (Port Address Translation, sometimes called NAT overload) takes many private source addresses and rewrites them to a single public address, using the Layer 4 source port to keep flows distinct. Two different inside hosts can both look like the outside interface IP because their port numbers are different.

The ASA tracks each translation in the xlate table and the matching connection in the conn table. The xlate is what stitches the return packet back to the right inside host: the ASA looks at (destination IP, destination port) on the return, finds the matching xlate, rewrites the destination back to the original inside (IP, port), and forwards.

If you take one thing away from this article, make it that: PAT is a stateful operation, and the xlate is the state. No xlate, no return path.

The Lab Topology

Every output below comes from a live ASAv running Cisco ASA 9.23(1) in the PingLabz reference lab. The relevant pieces:

  • inside interface (G0/0): 10.10.0.254/24, security-level 100. Inside subnets 10.10.0.0/24 and 10.10.10.0/24 sit behind it.
  • outside interface (G0/1): 203.0.113.2/30, security-level 0. Default route points to 203.0.113.1 (the ISP).
  • dmz interface (G0/2): 192.168.50.1/24, security-level 50. Not relevant to PAT, mentioned for completeness.

Configuration: Object NAT, the One-Liner

The cleanest way to write dynamic PAT on a modern ASA is object NAT (also called Auto NAT, lives in Section 2 of the NAT table). Define a network object for the source subnet, attach the NAT rule to it, done.

object network INSIDE-NET
 subnet 10.10.10.0 255.255.255.0
 nat (inside,outside) dynamic interface

object network INSIDE-TRANSIT
 subnet 10.10.0.0 255.255.255.0
 nat (inside,outside) dynamic interface

Two things to notice. First, the NAT rule is nested inside the object. The keyword is dynamic interface, which means "translate to whatever IP is currently configured on the named outside interface". You do not have to know or hardcode the public IP. If your ISP changes it, the NAT rule does not need to change.

Second, the rule names two interfaces: (inside,outside). The first is the real (pre-NAT) interface, the second is the mapped (post-NAT) interface. Get the order wrong and the rule will not match traffic in the direction you expect.

Verifying the Configuration Loaded

Pull the running config NAT block to confirm both pieces of the rule (the object and the nested NAT) are in place.

ASA-PERIM# show running-config nat
nat (inside,outside) source static INSIDE-NET-FULL INSIDE-NET-FULL destination static REMOTE-VPN-NET REMOTE-VPN-NET no-proxy-arp route-lookup
nat (inside,outside) source dynamic INSIDE-NET INSIDE-PARTNER-PAT destination static PARTNER-NET PARTNER-NET
!
object network INSIDE-NET
 nat (inside,outside) dynamic interface
object network INSIDE-TRANSIT
 nat (inside,outside) dynamic interface
object network DMZ-WEB
 nat (dmz,outside) static 198.51.100.10

The two object NAT lines at the bottom (INSIDE-NET and INSIDE-TRANSIT) are the dynamic PAT rules. The other entries are unrelated (manual NAT for VPN exemption, manual twice NAT for a partner network, static NAT for the DMZ web server) and will become familiar across the rest of the NAT articles in this cluster.

Watching PAT in Action

With inside hosts generating outbound traffic, the xlate table fills up. Here is the live xlate from the same ASA after a series of pings sourced from 10.10.10.1 to 8.8.8.8:

ASA-PERIM# show xlate
5 in use, 5 most used
Flags: D - DNS, e - extended, I - identity, i - dynamic, r - portmap,
       s - static, T - twice, N - net-to-net
NAT from dmz:192.168.50.10 to outside:198.51.100.10
    flags s idle 0:28:35 timeout 0:00:00
ICMP PAT from inside:10.10.10.1/2 to outside:203.0.113.2/2 flags ri idle 0:00:08 timeout 0:00:00
ICMP PAT from inside:10.10.10.1/0 to outside:203.0.113.2/26309 flags ri idle 0:00:19 timeout 0:00:00
ICMP PAT from inside:10.10.10.1/3 to outside:203.0.113.2/3 flags ri idle 0:00:08 timeout 0:00:00
ICMP PAT from inside:10.10.10.1/1 to outside:203.0.113.2/1 flags ri idle 0:00:08 timeout 0:00:00

Read the flags: r means portmap (PAT) and i means dynamic. Each ICMP echo got its own xlate keyed to the ICMP identifier (the slash-number after the IP). Three of the four kept the same identifier on the outside; the fourth rolled to 26309 because the ASA detected a collision with a different inside source already using that ID.

The wider hit counter lives in show nat detail. The PAT rule on INSIDE-NET (10.10.10.0/24) shows 46 translations since the ASA last rebooted:

ASA-PERIM# show nat detail

Auto NAT Policies (Section 2)
1 (dmz) to (outside) source static DMZ-WEB 198.51.100.10
    translate_hits = 0, untranslate_hits = 7
    Source - Origin: 192.168.50.10/32, Translated: 198.51.100.10/32
2 (inside) to (outside) source dynamic INSIDE-TRANSIT interface
    translate_hits = 0, untranslate_hits = 0
    Source - Origin: 10.10.0.0/24, Translated: 203.0.113.2/30
3 (inside) to (outside) source dynamic INSIDE-NET interface
    translate_hits = 46, untranslate_hits = 0
    Source - Origin: 10.10.10.0/24, Translated: 203.0.113.2/30

translate_hits increments when an inside-to-outside packet matches the rule and gets a new xlate. untranslate_hits increments when a return packet matches the xlate and gets the destination rewritten back. For pure outbound dynamic PAT, untranslate is always zero (return traffic uses the xlate, not the rule).

Proving the Path with packet-tracer

The fastest way to confirm a brand new PAT rule is doing what you think before any user reports an outage is to walk a hypothetical packet through the ASA with packet-tracer:

ASA-PERIM# packet-tracer input inside tcp 10.10.10.50 49000 8.8.8.8 80

Phase: 1
Type: INPUT-ROUTE-LOOKUP
Subtype: Resolve Egress Interface
Result: ALLOW
Found next-hop 203.0.113.1 using egress ifc  outside

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

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

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

Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: outside
output-status: up
output-line-status: up
Action: allow

Phase 2 is the entire story: the ASA matched the packet against object INSIDE-NET, applied the dynamic NAT rule, and translated 10.10.10.50:49000 to 203.0.113.2:49000. The same source port came through unchanged because no other flow needed it; on a busy ASA the source port often changes. Phase 9 confirms the conn was created and the packet would be forwarded to next-hop 203.0.113.1 on the outside interface. That is a working PAT path.

For a deeper walk through every packet-tracer phase, see Cisco ASA packet-tracer Command: Complete Troubleshooting Guide.

The Port Pool, and What Happens When It Fills

A single outside IP gives you, in theory, 64,512 high-numbered ports per protocol (1024-65535). In practice the ASA reserves some ranges and divides ports across protocols, so the usable pool is smaller. For most edge deployments it is more than enough.

If it is not enough (a SaaS company with thousands of concurrent sessions per IP, for example), the symptom shows up in syslog as %ASA-3-202010: PAT pool exhausted and the conn table starts dropping new flows. Two ways to fix it:

  1. Add a second mapped IP. Build an object network OUTSIDE-PAT-POOL as a small range or list of public IPs, then point the dynamic NAT at that object instead of interface. The ASA round-robins across them.
  2. Per-session PAT (default on 9.x). Modern ASA software releases ports back to the pool the moment a TCP flow ends, instead of holding them for the full PAT timeout. This is on by default and is one of the reasons you do not see PAT exhaustion as often as on older releases.

Idle Timeouts You Should Know

Dynamic PAT xlates do not live forever. The relevant timers (defaults shown):

TimerDefaultWhat it controls
timeout xlate3:00:00How long an idle xlate survives without traffic.
timeout pat-xlate0:00:30Specific to PAT xlates. The 30-second hold lets in-flight TCP teardowns complete before the port returns to the pool.
timeout conn1:00:00Idle TCP conn timeout. The xlate cannot disappear before the conn does.
timeout udp0:02:00UDP conn idle timeout. Lower than TCP because UDP is connectionless and the ASA cannot watch a teardown.

The interaction matters: if a TCP flow goes idle for two hours, the conn ages out, then the xlate ages out, then the port returns to the pool. Until all of that happens, the inside host has burned a port on the outside IP. On a high-throughput edge this is one knob worth understanding.

Failure Modes You Will Actually See

The most common dynamic PAT failures, ranked by how often they cause an outage:

  • Wrong interface order. nat (outside,inside) instead of (inside,outside). The rule does not match outbound traffic and inside hosts cannot reach the internet. Easy to spot in show running-config object; easy to miss when copy-pasting from a different ASA.
  • Subnet mask mismatch. The object subnet does not cover all the inside hosts. Some hosts work, others do not. Compare the subnet line under each object NAT with the actual inside subnets on the routing side.
  • Routing not in place. The packet matches the NAT rule but never gets a route to 0.0.0.0/0. Check show route for a default route on outside.
  • ACL denying the return. Outbound packet leaves fine, return packet comes back and gets dropped at the outside interface ACL. The ACL must permit established sessions or the matching return flow.
  • PAT pool exhaustion. Already covered. Symptom: syslog 202010, slow new connections. Fix: bigger PAT pool or enable per-session PAT.

The fastest diagnostic for "did the PAT rule match my traffic?" is always packet-tracer with the source IP and port the user reports.

Where to Go Next

Key Takeaways

  • Dynamic PAT is the standard outbound NAT rule on the ASA: many inside hosts to one outside IP, distinguished by source port.
  • Object NAT (nat (inside,outside) dynamic interface nested inside an object network) is the modern, one-line way to write it. It lands in Section 2 of the NAT table.
  • The xlate table is the state. Watch it with show xlate, watch the rule itself with show nat detail.
  • packet-tracer is the fastest way to confirm a PAT rule matches the source you expect, before you touch live traffic.
  • The most common failure is interface order. Second most common is mask mismatch. Both are config bugs and both show up immediately in packet-tracer.
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.