How to Configure Port Forwarding on Cisco Routers: Static NAT and Access Rules Setup

How to Configure Port Forwarding on Cisco Routers

How to Configure Port Forwarding on Cisco Routers

At some point, almost every network needs to expose an internal service to the outside world — a web server, a mail server, a remote access gateway, a game server, whatever it might be. The challenge is that most internet-facing routers use PAT to share a single public IP across the whole internal network, and PAT alone has no idea an external connection should be routed to a specific internal host. That’s exactly the gap port forwarding fills. I’ll walk you through how it actually works and how to configure it properly and securely on a Cisco router.

What Is Port Forwarding, Really?

Port forwarding — on Cisco platforms, implemented through Static NAT (specifically, static port-level NAT) — creates a permanent, predictable mapping between a specific port on your public IP address and a specific internal host and port. Unlike dynamic NAT or PAT, which are created automatically and temporarily in response to outbound traffic, a static NAT entry exists permanently in the configuration, allowing inbound connections initiated from the internet to reach a specific internal server.

Think of it like a corporate mailroom. Most mail (regular outbound traffic via PAT) gets sorted dynamically based on who’s expecting a reply. But port forwarding is like a permanent, labeled mail slot: “anything addressed to Suite 443 always goes directly to the server in room 192.168.1.100, no matter what.” That mapping doesn’t change and doesn’t depend on anyone inside having sent something out first.

Common Use Cases

Prerequisites

Topology for This Guide

Internal web server: 192.168.1.100, listening on port 80
Public IP: 203.0.113.1 (assigned to Gi0/0, the outside interface)

Step 1: Confirm NAT Inside/Outside Interfaces Are Already Set

Router(config)# interface GigabitEthernet0/1
Router(config-if)# ip nat inside
Router(config-if)# exit

Router(config)# interface GigabitEthernet0/0
Router(config-if)# ip nat outside
Router(config-if)# exit

If you already have PAT configured for general outbound traffic, these are almost certainly already in place — you don’t need to repeat them, just confirm with show ip nat statistics.

Step 2: Create the Static Port Forward

Router(config)# ip nat inside source static tcp 192.168.1.100 80 203.0.113.1 80

Reading this command left to right: translate traffic destined for the inside local address 192.168.1.100 port 80, and make it reachable at the inside global address 203.0.113.1 port 80. Because this is a static entry, external hosts can now initiate a connection to 203.0.113.1:80, and the router will always forward it to the internal web server.

Forwarding to a Different External Port (Port Translation)

You don’t have to use the same port number on both sides. This is genuinely useful if you’re publishing multiple internal services on different hosts but only have one public IP, or if you want to obscure the standard port for a management service:

Router(config)# ip nat inside source static tcp 192.168.1.50 3389 203.0.113.1 33890

Here, external users connect to 203.0.113.1 on port 33890, and the router quietly forwards that to the internal RDP server on its standard port 3389.

Step 3: Allow the Traffic Through Your ACL/Firewall

This is the step people forget constantly — NAT translation and traffic filtering are two completely separate mechanisms in IOS. Creating a static NAT entry does not automatically permit the traffic; you also need an ACL applied to the outside interface (or a proper firewall policy on a device with a stateful firewall like a Cisco ASA/Firepower or ZBFW) that explicitly permits the inbound traffic.

Basic example using an interface ACL:

Router(config)# ip access-list extended OUTSIDE-IN
Router(config-ext-nacl)# permit tcp any host 203.0.113.1 eq 80
Router(config-ext-nacl)# deny ip any any log
Router(config-ext-nacl)# exit

Router(config)# interface GigabitEthernet0/0
Router(config-if)# ip access-group OUTSIDE-IN in

Important detail: this ACL should reference the public (inside global) address, since it’s applied on the outside interface where packets still show the pre-translation destination as seen from outside — which is the public IP.

Multiple Services, Multiple Static Entries

You can stack as many static NAT entries as you need, each on its own port:

ip nat inside source static tcp 192.168.1.100 80 203.0.113.1 80
ip nat inside source static tcp 192.168.1.100 443 203.0.113.1 443
ip nat inside source static tcp 192.168.1.50 3389 203.0.113.1 33890
ip nat inside source static tcp 192.168.1.60 25 203.0.113.1 25

And a matching ACL permitting each specific port:

ip access-list extended OUTSIDE-IN
 permit tcp any host 203.0.113.1 eq 80
 permit tcp any host 203.0.113.1 eq 443
 permit tcp any host 203.0.113.1 eq 33890
 permit tcp any host 203.0.113.1 eq 25
 deny ip any any log

Verifying Port Forwarding

Router# show ip nat translations
Pro Inside global        Inside local          Outside local     Outside global
tcp 203.0.113.1:80       192.168.1.100:80      ---               ---

Note the static entry appears even without active traffic (unlike dynamic PAT entries, which only appear when a session is active) — this is one way to distinguish a static entry from dynamic ones in the table.

Router# show ip nat statistics
Total active translations: 4 (4 static, 0 dynamic; 0 extended)

That “4 static” confirms your static mappings are correctly registered.

Test from an external host or a public online port-checking tool:

telnet 203.0.113.1 80

Or from inside your network to simulate external access more accurately, test from a device genuinely outside your NAT boundary (testing from inside your own LAN toward your own public IP is a classic case where “NAT hairpinning” support becomes relevant — some platforms need extra configuration to allow this internal loopback pattern).

NAT Hairpinning (Accessing Your Own Public IP from Inside)

If internal users try to reach your own public IP/port-forwarded service from inside the same network, this sometimes fails unless the router explicitly supports NAT hairpinning (also called NAT loopback). On IOS, this generally requires that the NAT statements are structured so returning traffic is correctly re-translated on the way back in. This is one of the more advanced edge cases in NAT design — if you hit it, verify with debug ip nat and confirm both the inbound static translation and outbound source translation are both correctly triggered for that traffic flow.

Real-World Enterprise Scenario

A common deployment: a branch office needs a small on-prem application server reachable by a specific partner company over the internet, on a specific TCP port, while all other internal systems remain completely hidden behind PAT. The network team creates a single static NAT entry for that one host/port, layers a tightly scoped ACL that only permits traffic from the partner’s known public IP range (not any), and leaves everything else on standard dynamic PAT. This is a textbook example of exposing exactly what’s needed and nothing more.

Another very common scenario: exposing a VPN concentrator’s UDP ports (like IPsec’s UDP 500/4500) via static NAT so remote workers or site-to-site tunnels can reach it, while the rest of the internal network stays behind standard PAT.

Security Considerations

This is the part I want to really stress, because port forwarding is one of the most common ways networks get compromised through simple misconfiguration:

Common Configuration Mistakes

Troubleshooting Checklist

  1. show ip nat translations — confirm the static entry is present and correctly formed (static entries show even without active traffic).
  2. show ip nat statistics — confirm the static count matches what you expect.
  3. show access-lists OUTSIDE-IN (or equivalent) — check hit counters on the specific permit line to confirm inbound traffic is actually reaching the router and matching the rule.
  4. debug ip nat (short, controlled bursts only) — trace the translation in real time as a test connection comes in.
  5. Confirm the internal host’s own firewall (Windows Firewall, iptables, etc.) isn’t blocking the inbound connection after NAT successfully translates it.
  6. Test from a genuinely external network/device, not just from inside your LAN, to rule out hairpinning-related false negatives.

Performance Tuning Tips

FAQs

Do I need a separate static NAT entry for every port I want to forward? Yes, each ip nat inside source static entry handles one specific protocol/port/host mapping. You stack multiple entries for multiple services.

Can I forward the same external port to different internal hosts? Not directly with the same public IP and port — a given (public IP, port, protocol) combination can only map to one internal destination. If you need to expose multiple internal hosts on the same standard port, you either need multiple public IPs or need to use different external ports per host.

Is port forwarding secure by default? No. Port forwarding only handles address/port translation and traffic redirection — it provides no authentication, encryption, or access control on its own. You must pair it with tightly scoped ACLs and strong security on the exposed service itself.

Does port forwarding work the same way with UDP as TCP? Yes, the same static NAT concept applies — just specify udp instead of tcp in the command, and match your ACL protocol accordingly.

What’s the difference between port forwarding and Dynamic NAT/PAT? Port forwarding (static NAT) is a permanent, manually configured mapping that allows inbound-initiated connections to reach a specific internal host. Dynamic NAT and PAT are automatically created in response to outbound traffic and don’t support reliable inbound access to a specific host.

Summary

Port forwarding through static NAT is how you deliberately punch a precise, permanent hole through your NAT boundary to expose a specific internal service — while everything else stays hidden behind standard dynamic PAT. The essentials to remember: the static NAT command alone doesn’t grant access, you also need a matching ACL permit on the outside interface; keep that ACL as narrowly scoped as your use case allows; and treat every port forward as a standing security decision that deserves periodic review, not a “set it and forget it” configuration.

References

Exit mobile version