Mental model
The public internet is running out of IPv4 addresses. NAT is the band-aid that’s kept IPv4 alive for 25+ years past its expected end.
The trick: organizations use private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) internally — ranges the public internet refuses to route. When a private host wants to reach the internet, the NAT router on the edge rewrites the source IP from private to a public address it owns. The reply comes back to the public IP; the router looks at its translation table and rewrites the destination back to the private IP before forwarding internally.
The price: NAT breaks the end-to-end principle of the internet. A host behind NAT cannot be directly addressed from outside without an explicit forwarding rule. Many protocols (SIP, FTP active mode, IPsec, peer-to-peer) require special NAT-traversal helpers to work through it. IPv6 was designed to fix this by giving every device a unique routable address — but until v6 is universal, NAT stays.
RFC 1918 — the private ranges
| Range | Size | Common use |
|---|---|---|
10.0.0.0/8 | 16,777,216 addresses | Large enterprise, ISP CGN customer-facing |
172.16.0.0/12 | 1,048,576 addresses | Mid-size enterprise, AWS VPC default range |
192.168.0.0/16 | 65,536 addresses | Home + SMB |
Plus the more recent CGNAT range (RFC 6598):
| Range | Size | Use |
|---|---|---|
100.64.0.0/10 | 4,194,304 addresses | ISP carrier-grade NAT, not routable on the public internet |
The public internet routes none of these. If you tried to send a packet from 10.0.0.5 to 8.8.8.8 directly without NAT, your ISP would drop it.
The three flavors of NAT
| Flavor | Mapping | Used for |
|---|---|---|
| Static NAT | Fixed 1:1 (one inside IP always maps to one outside IP) | Inside servers reachable from internet |
| Dynamic NAT | Pool of public IPs, handed out 1:1 as needed, returned to pool when idle | Less common in 2026 — rare to have a pool of unused public IPs |
| PAT (Port Address Translation / NAT Overload) | Many inside IPs share one public IP, distinguished by source port | The standard. Home routers, branch offices, most enterprise edges. |
PAT is what you’ll deploy 99% of the time. CCNA exam tests all three.
The four terms — inside / outside, local / global
The single biggest CCNA NAT confusion. Memorize this:
- Inside = our network’s hosts.
- Outside = hosts on someone else’s network.
- Local = the address as seen from the inside.
- Global = the address as seen from the outside (the routable internet).
Apply both axes:
| Term | What it means | Example |
|---|---|---|
| Inside Local | Our host’s private IP, before translation | 10.0.0.5 |
| Inside Global | Our host’s public IP, after translation | 203.0.113.7 |
| Outside Global | The remote host’s real IP on its own network | 8.8.8.8 |
| Outside Local | The remote host’s IP as seen from our inside (usually same as Outside Global, but can differ with Twice-NAT) | 8.8.8.8 |
The CCNA exam loves to ask “if 10.0.0.5 becomes 203.0.113.7 talking to 8.8.8.8, what is the Inside Global address?” Answer: 203.0.113.7. Just remember inside = our hosts, local = before translation, global = after translation.
Why “Outside Local” exists
In simple NAT, Outside Local = Outside Global. They diverge only with NAT64 or double NAT scenarios where the outside host is presented to inside clients with a different IP than its real one. Rare in CCNA scope but recognize it exists.
PAT — what your home router does
PAT (Port Address Translation, or NAT Overload) lets many inside hosts share one outside IP. Distinction is the source port of each conversation.
Inside: Outside:
10.0.0.5 : 50000 → 8.8.8.8 : 443
10.0.0.6 : 51000 → 8.8.8.8 : 443 (different conversations)
10.0.0.7 : 52000 → 8.8.8.8 : 443
↓ (NAT router rewrites source IP + possibly source port)
Translation table:
10.0.0.5 : 50000 ↔ 203.0.113.7 : 50000 ↔ 8.8.8.8 : 443
10.0.0.6 : 51000 ↔ 203.0.113.7 : 51000 ↔ 8.8.8.8 : 443
10.0.0.7 : 52000 ↔ 203.0.113.7 : 52000 ↔ 8.8.8.8 : 443
Packets leaving the router:
203.0.113.7 : 50000 → 8.8.8.8 : 443
203.0.113.7 : 51000 → 8.8.8.8 : 443
203.0.113.7 : 52000 → 8.8.8.8 : 443
All three conversations come from the same public IP — the router tells them apart by source port. Each entry stays in the translation table until the conversation ends or times out (default ~24h for TCP, ~5min for UDP, ~60s for ICMP — these matter for troubleshooting).
Port collision handling
If two inside hosts use the same source port (10.0.0.5:50000 and 10.0.0.6:50000), the router rewrites one of them to a different source port to keep them unique. The translation table tracks this.
How many connections does PAT support?
Theoretical limit: ~65,000 conversations per (public IP, protocol) pair (the size of the source-port range). Practical limit on a Cisco router is lower — platform-dependent — usually thousands to tens of thousands. The CGNAT scale issue is real and is why ISPs use multiple public IPs per CGNAT node.
Configuration — the four canonical patterns
Pattern 1: PAT (overload) — the typical home/SMB config
! Mark inside and outside interfaces
R1(config)# interface GigabitEthernet0/0
R1(config-if)# description LAN — inside
R1(config-if)# ip nat inside
R1(config)# interface GigabitEthernet0/1
R1(config-if)# description WAN — outside
R1(config-if)# ip nat outside
! Define what's eligible for translation (which inside sources)
R1(config)# ip access-list standard NAT-INSIDE
R1(config-std-nacl)# permit 10.0.0.0 0.0.0.255
! Enable PAT, overloading on the outside interface
R1(config)# ip nat inside source list NAT-INSIDE interface GigabitEthernet0/1 overload
The overload keyword makes it PAT. Without it, you get plain dynamic NAT (1:1) which exhausts when you run out of pool IPs.
Pattern 2: Dynamic NAT (pool-based, 1:1)
R1(config)# ip nat pool MY-POOL 203.0.113.10 203.0.113.20 prefix-length 24
R1(config)# ip access-list standard NAT-INSIDE
R1(config-std-nacl)# permit 10.0.0.0 0.0.0.255
R1(config)# ip nat inside source list NAT-INSIDE pool MY-POOL
Each inside host gets one outside IP from the pool. Released when the host stops sending. Useful when you genuinely have many public IPs and want 1:1 mapping. Rare in 2026.
Pattern 3: Static NAT (for an inside server)
! Inside server 10.0.0.50 is reachable as 203.0.113.50 from the internet
R1(config)# ip nat inside source static 10.0.0.50 203.0.113.50
The 1:1 mapping is permanent — exists in the table even when no traffic flows. The outside IP must be routable to this router (you must own it, and the upstream must route it to you).
Pattern 4: Port forwarding (static NAT for specific ports only)
! Inside server 10.0.0.50:80 is reachable on the router's public IP at port 8080
R1(config)# ip nat inside source static tcp 10.0.0.50 80 interface Gi0/1 8080
Useful when you only have one public IP but want to expose multiple inside servers on different ports.
Pattern 5: Twice-NAT (translating both source AND destination)
Rare, complex. Used when two networks have overlapping private IPs and need to talk. The router rewrites both source and destination on each packet. Out of CCNA scope — recognize the term.
Hairpin NAT — the inside-loop case
A common gotcha. Inside host 10.0.0.6 wants to reach inside server 10.0.0.50 using its public address 203.0.113.50 (because DNS returned the public IP). Without hairpin NAT, the packet leaves the router, hits the WAN side, gets discarded because there’s no return route.
Hairpin NAT allows the router to rewrite the destination back to the inside IP and forward locally, without leaving the WAN interface.
R1(config)# ip nat inside source static 10.0.0.50 203.0.113.50 extendable
Plus the inside host needs to reach the outside interface — usually requires ip nat enable or careful interface setup.
Real-world fix: use split DNS so internal clients get the internal IP from DNS, and external clients get the public IP. Then hairpin NAT is never needed.
CGNAT — why your home IPv4 is in 100.64.x.x
Many ISPs ran out of public IPv4 addresses. Their solution: Carrier-Grade NAT (CGNAT). Your home router gets a 100.64.x.x address from the ISP (CGNAT private range from RFC 6598), and the ISP’s edge router does another layer of NAT to translate that to a real public IP shared with many customers.
Result: you’re behind two layers of NAT. Direct inbound connections to your home network are impossible without ISP cooperation. Real symptoms:
- Online gaming with strict NAT type
- Self-hosted services unreachable from outside without a tunnel (Cloudflare Tunnel, Tailscale, etc.)
- Some peer-to-peer apps can’t form connections
CGNAT is increasingly common in the US (T-Mobile home internet, some Comcast deployments, all 4G/5G mobile). IPv6 is the long-term fix — most CGNAT’d networks also offer native IPv6, which bypasses the double-NAT entirely.
NAT and IPsec — the famous gotcha
IPsec ESP doesn’t have port numbers — it identifies tunnels by SPI (Security Parameter Index). PAT can’t rewrite SPIs the way it rewrites ports. Result: IPsec tunnels break when they cross a PAT device.
NAT-T (NAT Traversal) solves this: IPsec encapsulates ESP inside UDP port 4500, so PAT can translate the UDP port like any normal packet. Both endpoints must support NAT-T. Modern IPsec implementations enable it by default.
For CCNA: recognize that NAT-T exists and uses UDP 4500.
NAT64 — bridging IPv6-only clients to IPv4-only services
When you have IPv6-only clients (e.g., a modern mobile carrier’s network) that need to reach IPv4-only servers (most of the public internet still), you need NAT64.
A NAT64 gateway translates IPv6 packets to IPv4 statefully:
IPv6 client (2001:db8::5) ↔ NAT64 gw ↔ IPv4 server (8.8.8.8)
↓
The IPv4 server is presented to the client as 64:ff9b::8.8.8.8
(IPv6 representation of 8.8.8.8 under the NAT64 prefix)
Pairs with DNS64 which synthesizes IPv6 AAAA records for IPv4-only hostnames. See IPv6 Transition Mechanisms for the full story.
Translation table — the heart of NAT
The NAT translation table is the stateful element that makes everything work. Each entry contains:
- Inside Local + Inside Global + Outside Global + protocol + ports + timeouts.
R1# show ip nat translations
Pro Inside global Inside local Outside local Outside global
tcp 203.0.113.7:50001 10.0.0.5:50001 8.8.8.8:443 8.8.8.8:443
tcp 203.0.113.7:50002 10.0.0.6:50002 52.95.110.20:443 52.95.110.20:443
udp 203.0.113.7:53 10.0.0.7:53 1.1.1.1:53 1.1.1.1:53
Each row is one active translation. When it times out, it’s removed.
Default timeouts (worth knowing)
| Protocol | Default timeout |
|---|---|
| TCP | 24 hours (or until FIN/RST) |
| UDP | 5 minutes |
| ICMP | 60 seconds |
| DNS | 60 seconds |
| HTTP/finrst | 1 minute after teardown |
You can tune them:
R1(config)# ip nat translation tcp-timeout 3600 ! 1 hour instead of 24
R1(config)# ip nat translation udp-timeout 60 ! 1 minute instead of 5
Lower timeouts free table space faster but break apps that have idle connections.
Translation table overflow
Each translation eats memory. Aggressive scanning, DDoS, or compromised hosts can blow up the table:
R1# show ip nat statistics
Total active translations: 12,847 (3 static, 12,844 dynamic; 12,801 extended)
Outside interfaces: GigabitEthernet0/1
Inside interfaces: GigabitEthernet0/0
Hits: 28,394,213 Misses: 142
CEF Translated packets: 28,394,213, CEF Punted packets: 142
Expired translations: 8,234,562
Dynamic mappings:
-- Inside Source
[Id: 1] access-list NAT-INSIDE interface GigabitEthernet0/1 refCount 12844
If Total active translations is climbing toward the platform’s NAT limit, you’re heading for an outage. Cap with:
R1(config)# ip nat translation max-entries all-host 100 ! per inside host
R1(config)# ip nat translation max-entries 10000 ! global cap
Verification — the four commands
R1# show ip nat translations
R1# show ip nat statistics
R1# show ip nat translations verbose
R1# clear ip nat translation * ! flush table — disruptive
For live diagnosis:
R1# debug ip nat detailed
R1# debug ip nat translations
Debug is high-volume. Use with a tight ACL filter or never in production. Match-specific:
R1# debug ip nat detailed list NAT-DEBUG
R1(config)# ip access-list standard NAT-DEBUG
R1(config-std-nacl)# permit host 10.0.0.5
Now only debug output for translations involving 10.0.0.5.
The 6-step NAT debug
When NAT “isn’t working”:
- Are inside/outside interfaces tagged?
show ip nat statistics— does it list the correct inside + outside interfaces? - Does traffic match the ACL?
show access-list NAT-INSIDE | include match. Hit count rising? If zero, the ACL is wrong (source IPs don’t match) or the traffic isn’t transiting the router. - Are translations appearing in the table?
show ip nat translations. If empty, the ACL doesn’t match OR the inside interface isn’t tagged. - Is the public IP routable back? If you’re using a static NAT to
203.0.113.50but the upstream doesn’t route that IP to you, replies vanish. Check with the ISP / upstream. - Did the
overloadkeyword get included? Without it, dynamic NAT exhausts your pool fast. - Are timeouts too short? TCP working but UDP DNS fails intermittently? Default UDP 5min may be eating short-lived translations under load. Tune.
Worked scenarios
Scenario 1. A home user has 4 devices on 192.168.1.0/24 and one cable-modem-provided public IP. What NAT type?
Answer: PAT (NAT Overload). Many private hosts share one public IP, distinguished by source port. This is the default mode on every consumer router.
Scenario 2. An enterprise has a /28 of public IPs (16 addresses) and ~12 internal servers that need to be reachable from outside. What’s the right NAT pattern?
Answer: Static NAT — one inside IP per public IP. 12 static NAT entries map each server. Inside hosts (clients) can still use PAT against a separate IP if needed.
Scenario 3. You’ve configured PAT but inside hosts can’t reach the internet. show ip nat translations shows nothing. What do you check first?
Answer:
ip nat insideon the LAN interface andip nat outsideon the WAN interface? Both required.- Does the ACL match the inside source range?
show access-list NAT-INSIDE. - Is
overloadin the command? Without it, the pool exhausts.
Scenario 4. A user behind PAT can’t establish an IPsec VPN to a corporate gateway. The IPsec tunnel completes phase 1 but fails phase 2.
Answer: NAT-T (NAT Traversal) isn’t enabled — IPsec ESP can’t be PAT’d directly. Enable NAT-T on both endpoints (Cisco: enabled by default in modern IOS via UDP 4500). Ensure UDP 4500 isn’t blocked anywhere on the path.
Scenario 5. You configure ip nat inside source static 10.0.0.50 203.0.113.50. Hosts on the outside can reach 203.0.113.50 fine. But inside hosts that try to reach 203.0.113.50 (the public IP of an inside server) fail.
Answer: Classic hairpin NAT problem. When an inside host targets the public IP, the packet leaves on the inside interface, hits the NAT process, but the source IP is also inside-local — no path back. Fix: either deploy hairpin NAT (extendable keyword + careful interface setup) OR use split DNS so internal clients receive the internal IP.
Scenario 6. PAT is configured. show ip nat translations shows 50,000 entries. The router CPU is at 90%. What’s happening?
Answer: Either:
- Translation table is close to the platform’s limit and the router is spending CPU on table operations.
- A compromised inside host is scanning (huge number of short-lived translations being created/expired).
Investigate: show ip nat statistics | include misses — high misses = a lot of failed creates. Look at top talkers via show ip nat translations | include 10.0.0 and identify which inside IP is responsible.
Scenario 7. Inside Local 10.0.0.5, Inside Global 203.0.113.7, Outside Global 52.10.20.30. What does Outside Local typically equal in this scenario?
Answer: Outside Local = Outside Global = 52.10.20.30. They differ only in unusual scenarios (NAT64, twice-NAT, where the outside host is presented to inside clients under a different IP).
Scenario 8. You want to expose your inside web server 10.0.0.80:80 to the internet, but you only have one public IP. The router’s WAN interface IP is 203.0.113.7. How?
Answer: Port forwarding:
R1(config)# ip nat inside source static tcp 10.0.0.80 80 interface Gi0/1 80
External users hit 203.0.113.7:80; the router rewrites destination to 10.0.0.80:80 and forwards. If your inside server’s port differs from the public-facing port, swap the numbers:
R1(config)# ip nat inside source static tcp 10.0.0.80 8080 interface Gi0/1 80
Common mistakes
-
Forgetting interface tags. No
ip nat inside/ip nat outside→ ACL matches but nothing translates. Both must be set. -
Wrong direction on the ACL. The ACL identifies inside-local sources — the private IPs you want translated. If you put outside-public IPs in the ACL, nothing matches.
-
Forgetting
overload. Without it, dynamic NAT runs out after the pool size. Alwaysoverloadfor typical home/SMB. -
Static NAT to an IP the router doesn’t own. No traffic ever arrives because the upstream doesn’t route it. Usually use the router’s own outside-interface IP.
-
Inside Local vs Inside Global mix-up. Mnemonic: inside = our hosts, local = before translation, global = after. Draw it out.
-
Translation table fills up. Each port from each source = an entry. DDoS or scanner traffic can blow it up. Limit with
max-entries. -
Default UDP timeout too short. 5 minutes is too short for some apps (gaming, VoIP signaling). Symptom: connection works briefly then drops.
-
Skipping NAT-T for IPsec through PAT. IPsec ESP can’t be PAT’d directly; needs UDP 4500 encapsulation.
-
Hairpin issues with public-IP-from-inside. Symptom: outside works fine but
10.0.0.Xcan’t reach the public IP of inside servers. Fix with split DNS or hairpin config. -
Assuming NAT is security. NAT is address translation, not access control. A motivated attacker can still reach inside hosts via vulnerabilities or forwarded ports. Always pair with a real firewall.
Lab to try tonight
-
Topology — Two networks. Inside:
10.0.0.0/24. Outside:198.51.100.0/24(the “internet”). A router between them with one public IP,198.51.100.1. -
Two inside PCs —
10.0.0.10and10.0.0.11. One outside server at198.51.100.50. -
PAT — configure overload so both inside PCs can reach the outside server. Verify with
show ip nat translations— two entries, same Inside Global, different source ports. -
Test simultaneous connections — both PCs simultaneously HTTP to the outside server. Confirm the table has both translations and a packet capture on the outside link shows different source ports for the two flows.
-
Static NAT — add a static NAT so inside server
10.0.0.50is reachable as198.51.100.2from outside. Test inbound reachability. -
Port forwarding — expose
10.0.0.80:80as198.51.100.1:8080. Verify external requests to port 8080 reach the inside server. -
Translation timeout drill — set UDP timeout to 30 seconds. Send a UDP packet. Watch
show ip nat translationsto confirm the entry vanishes after the timeout. -
NAT debug with ACL filter —
ip access-list standard NAT-DEBUG+permit host 10.0.0.10. Thendebug ip nat detailed list NAT-DEBUG. Send traffic from10.0.0.10. See per-packet translation events without flooding with other hosts’ traffic. -
Outside capture — packet-capture on the outside interface. Confirm packets really do show the public IP as source, not the private one. Capture inside; confirm reverse.
-
Bonus: hairpin scenario — try having an inside host reach the public-static-NAT’d IP of another inside server. Observe failure without hairpin. Add
extendablekeyword and verify.
Cheat strip
| Concept | Plain English |
|---|---|
| NAT | Rewrite IP addresses at a router. Inside (private) ↔ outside (public). |
| RFC 1918 | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 — private ranges |
| CGNAT (RFC 6598) | 100.64.0.0/10 — ISP-side carrier-grade NAT space |
| PAT / overload | Many private hosts share one public IP, distinguished by source port |
| Static NAT | Fixed 1:1 mapping. Used for inside servers reachable from outside |
| Dynamic NAT | Pool-based 1:1 — rare in 2026 |
| Port forwarding | Static NAT for a specific port only |
| Inside Local | Our host’s private IP, pre-translation |
| Inside Global | Our host’s public IP, post-translation |
| Outside Global | Remote host’s real IP |
| Outside Local | Remote host’s IP as we see it (usually = Outside Global) |
ip nat inside / ip nat outside | Interface tags — required for NAT to engage |
overload | Makes it PAT instead of 1:1 NAT |
| Translation table | Stateful per-conversation. Times out per protocol. |
| NAT-T | NAT Traversal — UDP 4500 encapsulation for IPsec to survive PAT |
| Hairpin NAT | Lets inside hosts reach public IPs of other inside hosts |
| NAT64 | IPv6 ↔ IPv4 translation — pairs with DNS64 |
| NAT isn’t security | It’s address translation. Always pair with a real firewall |
show ip nat translations | Daily-driver debug command |
| Default timeouts | TCP 24h · UDP 5min · ICMP 60s |
| Why it exists | IPv4 exhaustion. IPv6 makes NAT unnecessary at the end-to-end level |