What is the NAT order of operations on a Cisco IOS router, and why does it matter?
Show the answer
Say this first
It depends on the direction. Inside to outside, IOS routes first and then translates. Outside to inside, it translates first and then routes. In both directions the inbound ACL runs before NAT, and crypto maps and outbound ACLs run after it. So an ACL inbound on the outside interface must match the global address, the router needs a route to the inside local address for incoming traffic, and VPN traffic must be exempted from NAT or it stops matching the crypto ACL.
Go deeper
The sequence, trimmed to what matters
| Step | Inside to outside | Outside to inside |
|---|---|---|
| 1 | IPsec decryption, if any | IPsec decryption, if any |
| 2 | Input ACL | Input ACL |
| 3 | Policy routing | NAT, global to local |
| 4 | Routing | Policy routing |
| 5 | NAT, local to global | Routing |
| 6 | Crypto map check | Crypto map check |
| 7 | Output ACL | Output ACL |
What follows from it
- Inbound ACL on the outside interface sees pre-NAT addresses. To let the internet reach SRV1
(192.168.20.10, published as 203.0.113.5), permit
host 203.0.113.5, not the private address. - Outbound ACL on the outside interface sees post-NAT addresses, so the sources are inside global.
- Inbound ACL on an inside interface sees inside local addresses.
- Outside to inside, routing uses the translated destination. R1 needs a route to 192.168.20.10.
- Crypto runs after NAT. Traffic to a VPN peer's private network gets PATed first, then no longer matches the private-to-private crypto ACL. Exempt it in the NAT rule:
ip access-list extended NAT-USERS
deny ip 192.168.10.0 0.0.0.255 10.200.0.0 0.0.255.255
permit ip 192.168.10.0 0.0.0.255 any
!
ip nat inside source list NAT-USERS interface GigabitEthernet0/0/0 overload- Translation happens only when a packet crosses between an
ip nat insideand anip nat outsideinterface. Inside to inside is never translated.
Other platforms do it differently
- Cisco ASA (8.3 and later) matches ACLs against the real, untranslated address: the opposite habit.
- Linux netfilter does DNAT in PREROUTING, before the routing decision, and SNAT in POSTROUTING, after it. Filter rules in FORWARD see the private destination of a port forward.
They will ask next
Connections to a published server fail and the permit line in the outside ACL has zero matches. Why?
The line permits the server's private address. The inbound ACL runs before translation, when the destination is still the public address, so the line never matches and the implicit deny drops the traffic. Rewrite it with the global address.
Does policy-based routing see the translated address?
Inside to outside, no: PBR runs before NAT and sees the inside local source. Outside to inside, yes: NAT has already rewritten the destination to the inside local address.
Traps
- Saying NAT happens before routing in both directions.
- Writing the outside interface ACL with private addresses.