T Techclick ← Palo Alto hub
Palo Alto · PAN-OS · NAT · Interactive lesson

PAN-OS NAT — translate last, prove the xlate

The ticket says inbound HTTPS to the public VIP never hits the DMZ server. The NAT rule looks right. The Security rule dest zone is untrust because “that is where the VIP lives.” PAN-OS already routed the post-NAT address into dmz. This lesson is that split, the click path, and the session fields that close the ticket.

20 min read · L2 primary · Quiz at end

After this page you can

Quick answer (say this out loud)

NAT matches on the pre-NAT packet and the zone of the pre-NAT dest IP after a route lookup. Security then uses those same pre-NAT addresses but the post-NAT dest zone. The header does not change until egress. Source NAT hides internal hosts (DIPP is many-to-one + ports). Dest NAT publishes a VIP. U-turn is dest NAT for internal clients who resolved the public VIP. Bidirectional is a Static IP source-NAT option only. Prove it with show session id plus Traffic log natsrc / natdst — not by adding a second NAT rule.

1. Why the zone split matters

A dest-NAT rule that “looks correct” can still leave inbound sessions on interzone-default. The NAT object is fine. The Security dest zone is still the zone of the public VIP. Official dest-NAT examples are explicit: NAT dest zone follows the pre-NAT route lookup; Security dest zone follows the post-NAT host.

That is the interview sentence. Everything else on this page is how you pick a type, click Policies → NAT, and prove the xlate.

Hero · who talks to whom
Trust laptop through an NGFW SNAT and DNAT cube to Untrust and a DMZ server
Notice two jobs, one box: SNAT hides the laptop on the way out; DNAT lands the public VIP on the DMZ server. Same firewall. Different rules.

Three production tickets this model closes:

Hard words before the runbook

Source NAT — rewrite the packet’s source IP (and often source port) as it leaves. Types: Static IP, Dynamic IP, Dynamic IP And Port (DIPP), Persistent Dynamic IP And Port.

Destination NAT — rewrite the dest IP (and optionally dest port) so a public VIP lands on a private host. Types: Static IP, Dynamic IP (with session distribution).

DIPP — Dynamic IP And Port. Many internals share one public IP; ports keep sessions unique. Also called NAPT / interface-based NAT when Address Type is Interface Address.

U-turn (destination U-turn NAT) — internal clients resolve the public VIP. Dest zone after the first route lookup is Untrust. You dest-NAT that VIP onto the DMZ host.

Bi-directional — a checkbox on Static IP source NAT only. The firewall installs the reciprocal dest-NAT so the same public IP works inbound.

Proxy ARP — the firewall answers ARP for a NAT-pool address only when that address sits in the same subnet as the ingress/egress interface. Pools are not bound to interfaces.

2. Mental model

Hold three parts. Interviews fail when people mix them.

1. Match (pre-NAT)

NAT rules match original source/dest zone, dest interface, addresses, and service. First match wins. Static rows must sit above DIPP — they do not get automatic precedence.

2. Security (mixed)

Addresses stay pre-NAT. Dest zone becomes the zone of the translated dest host. You still need a Security allow. NAT never permits traffic.

3. Translate (egress)

The IP and port do not change until the packet leaves. Session table and Traffic log then show both originals and natsrc / natdst.

Say this out loud

NAT is written on the original packet. Security allows on original addresses and the post-NAT dest zone. The rewrite happens last, on the way out. If those three disagree, the session dies on the default deny — not because NAT “failed to translate.”

Official flow (NAT Policy Rules): ingress inspect → route lookup for egress interface and zone → NAT rule match on those zones → Security on original addresses and post-NAT zones → on egress, translate source and/or dest and ports. You must still write a Security rule to allow the NAT traffic.

3. Packet-order flowchart (NAT vs Security)

Read this before you click Policies → NAT. The packet does not rewrite, then decide. It decides, then rewrites.

Path · route, then match, then allow, then rewrite
Four stations: route lookup, NAT match, security, egress rewrite
Path of one new session: route first so dest zone exists, NAT match next, Security after that, header rewrite only on egress.
Flow 1 · NAT vs Security (official order)
New session · first packet · header still original 1 · Ingress inspect · source zone 2 · Route lookup egress IF + dest zone 3 · NAT match pre-NAT zones + addrs 4 · Security pre-NAT IP · post-NAT zone 5 · Egress — now translate source and/or dest IP + ports change here, not earlier If Security misses → interzone-default NAT match is not an allow. Write Policies → Security. Dest NAT zone split (the exam trap) NAT dest zone = route lookup of the public VIP (often Untrust → Untrust) Security dest zone = route lookup of the private host (Untrust → DMZ) Security Destination Address = the public VIP (pre-NAT), never the DMZ IP Lab inbound: 192.0.2.250 → 192.0.2.100 becomes 192.0.2.250 → 10.1.1.100 on egress Firewall proxy-ARPs 192.0.2.100 if that VIP is on the Untrust subnet Source: Destination NAT Example — One-to-One Mapping · NAT Policy Rules

Read left → right, then down. Green box is the only moment the header changes. Red box is the ticket that looks like “NAT is broken.”

Flow 2 · dest NAT zones (pre-NAT vs post-NAT)
Internet host 192.0.2.250 Policies → NAT Untrust → Untrust · dest 192.0.2.100 → 10.1.1.100 DMZ server 10.1.1.100 Policies → Security for the same flow From Untrust → To DMZ · Destination Address = 192.0.2.100 (pre-NAT) Wrong: dest zone Untrust, or dest address 10.1.1.100 — rule never matches Traffic log still shows dst = 192.0.2.100 and natdst = 10.1.1.100 Lab names from the official one-to-one dest NAT example (RFC 5737 / docs)

If you remember one picture from this lesson, remember this: NAT Untrust→Untrust, Security Untrust→DMZ, dest object stays the VIP.

4. How to choose the NAT type

One rule per job. Do not turn Bidirectional on to “make inbound work” unless the translation is Static IP source NAT.

You needNATTranslation TypeWhy
Users on Trust browse the internet Source NAT Dynamic IP And Port (DIPP). Address Type = Interface Address on the Untrust IF, or Translated Address = a public pool Many internals, one (or few) public IPs. Ports distinguish sessions. Official outbound pattern.
A 1:1 public IP for a server that also initiates outbound Source NAT + reciprocal dest NAT Static IP on Source Address Translation, Bi-directional = Yes Bidirectional exists only on Static IP. It installs the inbound dest-NAT for you. You still write Security both ways.
Publish one VIP to one (or a range of) private hosts Destination NAT Static IP dest translation. Optional Translated Port for port-forward / port-hide Original and translated dest counts must match. Security dest address stays the VIP.
Cloud VIP / FQDN that returns many IPs Destination NAT Dynamic IP (with session distribution) Required when the pre-NAT dest is FQDN or a DAG. Methods: Round Robin, Source IP Hash, IP Modulo, IP Hash, Least Sessions.
Internal users open the company site by public FQDN Destination U-turn NAT Dest Static IP: public VIP → DMZ IP. Original dest zone = Untrust DNS gave them the public address. First route lookup exits Untrust. Official procedure is dest NAT, not “add VIP to Trust.”
STUN / voice / video behind DIPP Source NAT Persistent Dynamic IP And Port (PAN-OS 11.1.1+ per rule). Older: global persistent DIPP CLI Same original source IP:port keeps the same public IP:port across destinations. Oversubscription on that rule is 1.
Exclude a host from a later DIPP pool No-NAT Match the host, Source Translation = None / No Source Translation Put the no-NAT row above the broader DIPP. First match wins.

Source: Source NAT, Destination NAT, and the official Configure NAT tasks. DIPP default oversubscription (how many sessions may reuse the same public IP:port) is a device setting — 8, 4, 2, or 1 — not a hidden “unlimited PAT.”

Do not do this

Do not set Bi-directional on DIPP. The field is not there — bidirectional is Static IP only. Do not write dest-NAT dest zone as DMZ because “the server is in DMZ.” The dest zone on the NAT rule is the zone of the original dest IP after route lookup, which for a public VIP is almost always Untrust.

5. Runbook · Side A objects, Side B NAT, Side C proof

Lab story (documentation / RFC 5737 addresses only): Trust users 10.1.1.0/24 browse out via Untrust interface 203.0.113.100. Internet clients reach the DMZ web server 10.1.1.11 on public VIP 203.0.113.11. You will not invent a second VIP “because inbound failed.” You will build objects, one DIPP rule, one dest-NAT (or one bidirectional Static), Commit, then prove the xlate.

Primary source for clicks: Translate Internal Client IP Addresses (Source DIPP NAT) and Destination NAT Example — One-to-One Mapping.

Side A — objects first

  1. Confirm zones and the Untrust IP

    Network → Zones already has trust, untrust, dmz on interfaces. Network → Interfaces shows ethernet1/1 with 203.0.113.100/24 in untrust. NAT cannot invent a zone or a next hop. If Untrust has no IP, stop — that is a network build.

  2. Address objects with a NAT- prefix

    Objects → Addresses → Add. Official best practice: prefix NAT pool objects so you never reuse them as Security destinations by accident.

    • NAT-egress-public — Type IP Netmask — 203.0.113.100/32 (DIPP / interface).
    • NAT-web-public — Type IP Netmask — 203.0.113.11/32 (VIP).
    • NAT-web-dmz — Type IP Netmask — 10.1.1.11/32 (real host). Keep this object off the Security Destination column for inbound.
    • net-users-trust10.1.1.0/24.
https://fw.lab.example.com/#objects/addresses Training mock · not live

Objects → Addresses → Add

Address Object

NAT-web-public
IP Netmask
203.0.113.11/32
Public VIP for DMZ web (lab)
nat-pool · lab-only
Cancel OK

Click next: OK, add NAT-web-dmz (10.1.1.11/32) and NAT-egress-public the same way, then Policies → NAT → Add. Source: Objects → Addresses; NAT Policy Rules “NAT-[name]” prefix.

Side B — the NAT rule

  1. Add the outbound DIPP rule

    Policies → NAT → Add. General: Name snat-trust-dipp. NAT Type = ipv4 (default). Put Static / no-NAT rows above this one.

  2. Original Packet

    Source Zone = Add trust. Destination Zone = untrust (the zone after the route lookup of the internet dest). Leave Destination Interface, Source Address, Destination Address, and Service as any unless you are carving a no-NAT exception.

  3. Translated Packet — source DIPP

    Source Address Translation → Translation Type = Dynamic IP And Port. Address Type = Interface Address, Interface = ethernet1/1 (the NAT rule then follows whatever IP that interface later acquires). Or Address Type = Translated Address → Add NAT-egress-public. Destination Address Translation stays None. OK.

  4. Add inbound dest NAT (or use bidirectional Static instead)

    Policies → NAT → Add. Name dnat-web-vip. Original Packet: Source Zone = untrust, Destination Zone = untrust, Destination Address = NAT-web-public. Translated Packet: Destination Address Translation → Translation Type = Static IP, Translated Address = 10.1.1.11 (or the NAT-web-dmz object). Optional Translated Port if you hide 8080 behind 443.

    Alternative for a server that also initiates: one Static IP source NAT from dmz to untrust, Source Address = NAT-web-dmz, Translated Address = NAT-web-public, Bi-directional = Yes. Official task name: Enable Bi-Directional Address Translation for Your Public-Facing Servers (Static Source NAT).

  5. U-turn if Trust users resolve the public FQDN

    A second dest-NAT: Source Zone = trust, Destination Zone = untrust, Destination Address = NAT-web-public, dest translate Static IP to 10.1.1.11. Official task: Enable Clients on the Internal Network to Access your Public Servers (Destination U-Turn NAT). If client and server share a Layer-2 that bypasses the firewall, also source-NAT the client so the reply returns through the firewall — that is the hairpin case, not the official three-zone U-turn.

  6. Security still required

    Policies → Security: outbound trust → untrust allow (your existing web/dns rule). Inbound untrust → dmz, Destination Address = NAT-web-public (pre-NAT), Application/Service for the published app, Action Allow, Log at Session End. U-turn needs trust → dmz with dest = the same VIP. Commit.

https://fw.lab.example.com/#policies/nat Training mock · not live

Policies → NAT → Add

NAT Policy Rule

General Original Packet Translated Packet
dnat-web-vip
ipv4
untrust
untrust · pre-NAT route
NAT-web-public
any
None
Static IP
10.1.1.11
(blank = same port)
Cancel OK · then Commit

Click next: OK, write the Security allow Untrust → DMZ dest NAT-web-public, Commit, then Monitor → Session Browser. Source: Policies → NAT · Original Packet / Translated Packet (PAN-OS Configure NAT).

Side C — prove it in session and the Traffic log

  1. Optional pre-check: Device → Troubleshooting

    Official NAT Policy Rules page: select Device → Troubleshooting and test traffic matches for the NAT rule. This is a config test — it is not a live packet. Use it to confirm the intended row is first match before you generate traffic.

  2. Generate traffic, then Session Browser

    From a Trust host, browse out. From an Untrust tester, hit https://203.0.113.11. Monitor → Session Browser — browse and filter running sessions (official Help: Monitor → Session Browser). Confirm source, dest, application, and that the session is live — not DISCARD.

  3. CLI xlate (same proof, more fields)

    Official DIPP verify steps: show session all, then show session id <id>. For Dynamic IP pool exhaustion: show counter global filter aspect session severity drop | match nat.

  4. Traffic log columns that close the ticket

    Monitor → Logs → Traffic. Filter on the tester IP. Quote these official fields: Source Address / Destination Address (originals), NAT Source IP (natsrc), NAT Destination IP (natdst), NAT Source Port, NAT Destination Port, Source/Destination Zone, Rule (Security). Flag 0x00400000 means a NAT translation was performed. Log at Session End is enough unless you are debugging a long-lived tunnel.

Dummy evidence · show session id (lab inbound VIP)
show session id 42188

Session          42188

        c2s flow:
                source:      192.0.2.250 [untrust]
                dst:         203.0.113.11
                proto:       6
                sport:       51922       dport:      443
        s2c flow:
                source:      10.1.1.11 [dmz]
                dst:         192.0.2.250
                proto:       6
                sport:       443         dport:      51922

        start time                           : Wed Aug 15 10:14:02 2026
        application                          : ssl
        rule                                 : allow-untrust-web
        address/port translation             : destination
        nat-rule                             : dnat-web-vip(vsys1)
Dummy evidence · Traffic log columns (same flow)
Receive Time     src            dst            natsrc         natdst         from     to      rule
2026/08/15 10:14 192.0.2.250    203.0.113.11   192.0.2.250    10.1.1.11      untrust  dmz     allow-untrust-web
Green success

Inbound: dst is still the VIP, natdst is the DMZ host, dest zone is dmz, Security Rule Name is your allow — not interzone-default. Outbound DIPP: src is the Trust host, natsrc is 203.0.113.100 (or the pool), natsport is not the original client port. That pair of rows closes the ticket.

6. Runtime path after commit

After go-live the user does not care about your object names. One HTTPS SYN to the VIP does this.

  1. Untrust host ARPs for 203.0.113.11. If that VIP is on the Untrust subnet, the firewall proxy-ARPs with the Untrust MAC. If the VIP is not on that subnet, there is no proxy ARP — the upstream router needs a route for the VIP pointing at the firewall.
  2. Route lookup of the original dest 203.0.113.11 selects Untrust as dest zone. NAT rule dnat-web-vip matches Untrust → Untrust, dest NAT-web-public.
  3. Second route lookup of the translated dest 10.1.1.11 selects DMZ as the Security dest zone. Security matches Untrust → DMZ, dest = the VIP. Allow + Log at Session End.
  4. On egress ethernet1/3 the dest becomes 10.1.1.11:443. Session installs. Traffic log later writes dst=203.0.113.11 and natdst=10.1.1.11.
  5. Trust users browsing out skip dest NAT, hit snat-trust-dipp, and leave with source 203.0.113.100 plus a translated port. DIPP oversubscription decides how many sessions may share that public IP:port.
Proxy ARP in one sentence

NAT pools are not bound to interfaces. Same-subnet VIP → firewall answers ARP. Off-subnet pool → you must route the return, or the SYN never arrives. Source: NAT Policy Rules, “Proxy ARP for NAT Address Pools.”

7. Traps + proof checklist

Proof · close the ticket with a named field
Operations desk monitor showing a green health check and a highlighted log row
Notice: proof is a named field on a timestamp, not a screenshot of a spinning tab.
FailureLooks likeActualProof
Security dest zone still Untrust “NAT works, server never answers” Security evaluated post-NAT dest zone (DMZ) and missed Traffic log dest zone + Rule = interzone-default
Security dest = private IP Rule never hits Addresses are pre-NAT — dest must be the VIP Log dst is still 203.0.113.11
NAT dest zone set to DMZ Inbound NAT has zero hits NAT dest zone is the pre-NAT route (Untrust) Device → Troubleshooting NAT match; hit count 0
No proxy ARP No SYN on the firewall VIP not in the Untrust subnet; upstream has no route No session, no ARP for the VIP on Untrust
DIPP pool / ports exhausted Some users browse, new ones fail DIPP oversubscription or empty Dynamic IP pool show counter global … | match nat
U-turn missing Internet works; office cannot open the public site Trust clients routed to Untrust toward the VIP Session src zone trust, dest = VIP, no dest NAT
Bidirectional on the wrong type “I cannot enable bi-dir” Field exists only on Static IP source translation Translated Packet → Translation Type
Static NAT below DIPP Server outbound uses the shared PAT First match; static has no automatic priority Policies → NAT order; session natsrc
NAT without Security Hit count on NAT, deny in logs NAT never permits Rule Name is a deny / default
Proof checklist before you add another NAT rule
Interview close

I match NAT on the original packet and the pre-NAT dest zone. I allow Security on those same addresses and the post-NAT dest zone. Translation happens on egress. I prove it with Session Browser and natsrc / natdst, not with a second NAT rule.

Knowledge check

Six judgment items. Map each one back to the zone split, the NAT type table, or the session / Traffic log proof. Check, then Reset if you miss any.

Q1

Inbound HTTPS to VIP 203.0.113.11 dest-NATs to 10.1.1.11 in DMZ. How must the Security rule be written?

Correct: b. Security uses pre-NAT addresses and the post-NAT dest zone. Re-read Mental model and Flow 2.
Q2

You publish 192.0.2.100 on Untrust to 10.1.1.100 in DMZ. What dest zone goes on the NAT rule?

Correct: a. Official one-to-one dest NAT: Untrust → Untrust on the NAT rule. Re-read Packet-order flowchart.
Q3

Two hundred Trust users need the internet through one public IP on ethernet1/1. Which Translated Packet setting?

Correct: c. DIPP (NAPT) is the official many-to-one outbound pattern. Re-read How to choose and Side B.
Q4

Your dest-NAT VIP is 198.51.100.50. Untrust is 203.0.113.100/24. Internet testers never create a session. First check?

Correct: d. Pools are not bound to interfaces. Same-subnet → proxy ARP. Off-subnet → you route. Re-read Runtime path and the traps table.
Q5

When can you set Bi-directional = Yes?

Correct: b. Official bidirectional task is Static Source NAT. Re-read How to choose and Side B step 4.
Q6

You committed dest NAT. Users still fail. What do you quote before adding another NAT rule?

Correct: a. Official verify is session + Traffic log fields. Re-read Side C and the proof checklist.

Sources

Related: Security policy fundamentals · Session factory · Session table and flow · Zones, interfaces, VR · Traffic not passing · Palo Alto interview hub · Palo Alto course