How to Set Up Network Address Translation (NAT) on Cisco ASA Firewalls: Complete Configuration Guide

How to Set Up Network Address Translation (NAT) on Cisco ASA Firewalls

How to Set Up Network Address Translation (NAT) on Cisco ASA Firewalls

NAT on the ASA confused me far more than it should have when I first started, mostly because I learned it on an old 8.2 image and then had to relearn everything when I touched an 8.3+ box using object NAT. If you’re going through that same headache right now, this guide is meant to get you from “why is my server unreachable” to actually understanding how ASA NAT thinks, with real commands and real output along the way.

Why NAT Still Matters on a Modern Firewall

Even with IPv6 adoption growing, most enterprise networks still run heavily on IPv4 private addressing internally, and NAT is what lets those private hosts communicate with the public internet, or lets external users reach internal servers through a public-facing address. On an ASA, NAT isn’t just an address translation feature — it is tightly interwoven with routing and, in many configurations, with how ACLs match traffic. Understanding NAT properly on the ASA is not optional if you want to run one confidently.

Networking Fundamentals: What NAT Actually Does

At its core, NAT rewrites the source and/or destination IP address (and often port, in the case of PAT — Port Address Translation) as a packet crosses the firewall. There are three classic types you’ll deal with:

The Big Shift: ASA 8.2 vs 8.3+ NAT

If you learn NAT from an old textbook or an outdated blog post, you’ll learn the 8.2-style syntax using nat, global, and static commands independently. Since ASA 8.3, Cisco moved to object-based NAT, which is what every modern deployment uses. I’ll focus entirely on 8.3+ syntax here since that’s what you’ll encounter on any currently supported ASA software.

In 8.3+, there are two NAT rule types:

Step 1: Configuring Dynamic PAT for Outbound Internet Access

This is the single most common NAT configuration on any ASA protecting an internal network.

ciscoasa(config)# object network INSIDE-NETWORK
ciscoasa(config-network-object)# subnet 10.1.1.0 255.255.255.0
ciscoasa(config-network-object)# nat (inside,outside) dynamic interface
ciscoasa(config-network-object)# exit

The dynamic interface keyword tells the ASA to PAT all traffic from this subnet to the outside interface’s own IP address. This is the go-to setup for giving an entire internal subnet internet access without consuming a whole pool of public addresses.

Step 2: Configuring Static NAT for an Inbound-Facing Server

Say you have an internal web server at 10.1.1.50 that needs to be reachable from the internet at 203.0.113.50.

ciscoasa(config)# object network WEB-SERVER
ciscoasa(config-network-object)# host 10.1.1.50
ciscoasa(config-network-object)# nat (inside,outside) static 203.0.113.50
ciscoasa(config-network-object)# exit

Remember: NAT alone does not open access. You still need an ACL on the outside interface permitting the desired inbound traffic to the real (10.1.1.50) or mapped (203.0.113.50) address, depending on your ASA version’s ACL-NAT interaction behavior — on 8.3+, ACLs typically reference the real address.

Step 3: Static PAT (Port Forwarding) for a Single Service

Often you don’t want to expose an entire server publicly — just one port, like HTTPS.

ciscoasa(config)# object network WEB-SERVER-HTTPS
ciscoasa(config-network-object)# host 10.1.1.50
ciscoasa(config-network-object)# nat (inside,outside) static 203.0.113.10 service tcp 443 443
ciscoasa(config-network-object)# exit

This maps only TCP port 443 on the public IP 203.0.113.10 through to port 443 on the internal server, which is enormously useful when you have limited public IP addresses and multiple internal servers needing selective external exposure.

Step 4: Manual (Twice) NAT for Policy-Based Scenarios

Manual NAT becomes necessary when the translation should depend on both source and destination — for example, when a host should get a different translated address depending on which remote network it’s talking to (common in multi-VPN or multi-ISP setups).

ciscoasa(config)# object network INSIDE-HOST
ciscoasa(config-network-object)# host 10.1.1.75
ciscoasa(config-network-object)# exit

ciscoasa(config)# object network PARTNER-NET
ciscoasa(config-network-object)# subnet 192.168.50.0 255.255.255.0
ciscoasa(config-network-object)# exit

ciscoasa(config)# object network PARTNER-VISIBLE-IP
ciscoasa(config-network-object)# host 172.16.99.5
ciscoasa(config-network-object)# exit

ciscoasa(config)# nat (inside,outside) source static INSIDE-HOST PARTNER-VISIBLE-IP destination static PARTNER-NET PARTNER-NET

This rule says: when 10.1.1.75 talks to the 192.168.50.0/24 partner network, present it as 172.16.99.5, and don’t translate the destination. Manual NAT rules are evaluated before Auto NAT rules and in the explicit order they appear in the NAT table, so ordering discipline matters a lot here.

Step 5: Verifying NAT Configuration

ciscoasa# show nat
ciscoasa# show nat detail

Expected output for the dynamic PAT rule looks something like:

Auto NAT Policies (Section 2)
1 (inside) to (outside) source dynamic INSIDE-NETWORK interface
    translate_hits = 1204, untranslate_hits = 1189

The translate_hits counter confirms the rule is active and being used — an essential first check whenever a “server unreachable” ticket lands on your desk.

Also check active translations directly:

ciscoasa# show xlate
2 in use, 45 most used
TCP PAT from inside:10.1.1.20/52344 to outside:203.0.113.1/24501 flags ri idle 0:00:12 timeout 0:00:30

And, as with ACL work, packet-tracer is invaluable here too:

ciscoasa# packet-tracer input outside tcp 198.51.100.5 12345 203.0.113.50 443

This shows you exactly which NAT rule matched, whether the ACL allowed it, and whether the packet was ultimately permitted or dropped — all in one command.

Practical Lab: Building a Multi-Service NAT Environment

In a lab with an inside network of 10.1.1.0/24 and a single outside public IP block of 203.0.113.0/29, configure the following:

  1. Dynamic PAT for general internet access from the inside subnet.
  2. Static PAT exposing an internal mail server’s SMTP (port 25) on 203.0.113.2.
  3. Static PAT exposing an internal web server’s HTTPS (port 443) on 203.0.113.3.
ciscoasa(config)# object network INSIDE-NETWORK
ciscoasa(config-network-object)# subnet 10.1.1.0 255.255.255.0
ciscoasa(config-network-object)# nat (inside,outside) dynamic interface
ciscoasa(config-network-object)# exit

ciscoasa(config)# object network MAIL-SERVER
ciscoasa(config-network-object)# host 10.1.1.25
ciscoasa(config-network-object)# nat (inside,outside) static 203.0.113.2 service tcp 25 25
ciscoasa(config-network-object)# exit

ciscoasa(config)# object network WEB-SERVER
ciscoasa(config-network-object)# host 10.1.1.50
ciscoasa(config-network-object)# nat (inside,outside) static 203.0.113.3 service tcp 443 443
ciscoasa(config-network-object)# exit

ciscoasa(config)# access-list OUTSIDE-IN extended permit tcp any object MAIL-SERVER eq 25
ciscoasa(config)# access-list OUTSIDE-IN extended permit tcp any object WEB-SERVER eq 443
ciscoasa(config)# access-list OUTSIDE-IN extended deny ip any any log
ciscoasa(config)# access-group OUTSIDE-IN in interface outside

This is a very typical small-to-mid business setup: one PAT’d outbound pool, and a couple of statically forwarded services.

Real-World Enterprise Scenario

I once supported a merger where two companies, each already using the 10.0.0.0/8 space internally, needed to interconnect over a site-to-site VPN without full IP renumbering. The answer was manual NAT with identity-preserving translation on both sides: each company’s overlapping subnet was translated to a unique, non-overlapping range only for traffic crossing the VPN tunnel to the other company, while internal routing stayed untouched. This is a scenario where understanding twice NAT thoroughly — not just Auto NAT — saved months of painful readdressing work.

Security Best Practices

Optimization and Performance Tuning

Troubleshooting and Common Mistakes

Frequently Asked Questions

Do I need an ACL in addition to a NAT static rule for inbound traffic? Yes. NAT and the interface ACL are separate, cooperating mechanisms — NAT translates the address, the ACL decides if the traffic is permitted at all.

What’s the difference between Auto NAT and Manual NAT? Auto NAT (object NAT) is simple, one object translated the same way regardless of destination. Manual NAT (twice NAT) lets the translation depend on both source and destination, and gives explicit control over rule ordering.

Can I have multiple NAT rules for the same host? Yes, particularly with manual NAT, where different rules apply depending on the destination — this is exactly how policy NAT for multiple VPN peers or ISPs is achieved.

Why does show xlate show a translation but the connection still fails? That usually means NAT succeeded but the ACL, routing, or an inspection policy is dropping the packet afterward — packet-tracer will pinpoint exactly which stage failed.

Summary

Modern ASA NAT configuration revolves around object-based Auto NAT for straightforward one-to-one and dynamic PAT scenarios, and Manual (Twice) NAT when translation needs to depend on both source and destination. Getting comfortable with show nat detail, show xlate, and packet-tracer will save you hours of guesswork whenever connectivity issues arise. Once you understand that NAT and ACLs are two separate, cooperating layers of policy, the rest of ASA configuration becomes far more predictable.

References

Exit mobile version