The Situation
You set up port forwarding on your router, pointed it at your server's local IP, and tested from outside β nothing. Connection refused, a timeout, or the connection just hangs. The service runs perfectly on your LAN, but nothing from the outside world gets through.
The maddening part: everything looks correct in the router admin panel. The rule is there. The IP is right. And it still doesn't work. Here's how to actually find what's broken.
Step 1: Confirm the Service Is Actually Listening
Don't touch the router yet. First, make sure your application is listening on the right address and port.
# On Linux/macOS
ss -tlnp | grep 8080
# Or with netstat
netstat -tlnp | grep 8080
# Windows
netstat -ano | findstr :8080
You want output like this:
tcp 0.0.0.0:8080 LISTEN 12345/node
Seeing 127.0.0.1:8080 instead of 0.0.0.0:8080? That means the service only accepts local connections β traffic from the router gets dropped before it even reaches your app. Fix the app config to bind to 0.0.0.0 or your specific LAN interface.
Step 2: Test Locally Before Blaming the Router
From a different device on the same LAN, try connecting to your server's private IP directly:
# From another machine on the LAN
curl http://192.168.1.100:8080
# Or just test TCP connectivity
nc -zv 192.168.1.100 8080
If this fails, you have a local problem β firewall or misconfigured service. Fix it here first. There's no point debugging the router if traffic can't even reach the server from inside.
Step 3: Audit the Router Port Forwarding Rule
Log into your router (usually 192.168.1.1 or 192.168.0.1) and check each field carefully:
- External port: the port outside clients connect to
- Internal IP: your server's static local IP β not a DHCP-assigned one that may change
- Internal port: the port your app actually listens on (can be different from external)
- Protocol: TCP, UDP, or Both β a web server needs TCP; a game server might need UDP
- Rule is enabled: some routers let you save a rule in a disabled state
The most common trap here is a drifting IP. DHCP handed your server 192.168.1.105 last week, then reassigned it to 192.168.1.112 after a reboot β now the forwarding rule points at the wrong machine. Set a static IP on the server, or use a DHCP reservation in the router so it always gets the same address.
Step 4: Check the Firewall on the Server Itself
Port forwarding gets traffic to your machine. A local firewall can still silently drop it after that. Check and open the port:
# UFW (Ubuntu/Debian)
sudo ufw status
sudo ufw allow 8080/tcp
# firewalld (CentOS/RHEL/Fedora)
sudo firewall-cmd --list-ports
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
# iptables (direct)
sudo iptables -L INPUT -n | grep 8080
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
# Windows Defender Firewall
netsh advfirewall firewall add rule name="Allow 8080" protocol=TCP dir=in localport=8080 action=allow
Step 5: Test from a Real External Network
Testing from inside your own LAN doesn't work β most home routers don't support NAT hairpinning, so you'll get a false negative. Use a phone on mobile data, a cheap cloud VM, or an online port checker.
# Get your public IP first
curl ifconfig.me
# or
curl https://api.ipify.org
# Then test from outside
curl http://YOUR_PUBLIC_IP:8080
nc -zv YOUR_PUBLIC_IP 8080
Read the error carefully. A timeout means a firewall is dropping packets upstream β the router firewall, your ISP, or the OS firewall. A Connection refused means traffic is arriving at the machine but something is rejecting it at the application layer.
Step 6: Look for Double NAT
Got a modem/router combo from your ISP, plus your own router plugged in behind it? You're behind double NAT. Forwarding a port on your router only gets traffic to your router's WAN port β the ISP device still blocks it from the internet.
# Trace your path out
traceroute 8.8.8.8
# Two private IP hops (e.g., 192.168.0.1 then 10.0.0.1)?
# That's double NAT.
The cleanest fix is putting the ISP device into bridge mode so it stops doing NAT entirely. Otherwise, you need port forwarding rules on both devices β the ISP modem forwards to your router's WAN IP, and your router forwards to the server. Call your ISP if the modem admin panel is locked down.
Step 7: Check for CGNAT
This one catches people off guard. Many ISPs β especially mobile/4G providers β use Carrier-Grade NAT, where your "public" IP is actually shared across thousands of customers. You literally cannot receive inbound connections. Port forwarding won't work, period.
# Compare these two:
curl ifconfig.me # Your apparent public IP
# vs. your router's WAN IP in the admin panel
# If they're different, you're behind CGNAT.
If your router's WAN IP falls in any of these ranges, that confirms it:
100.64.0.0/10 (CGNAT range, RFC 6598)
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
Options: ask your ISP for a real public IP (some offer it free, others charge around $5β10/month), use a VPN service with port forwarding support (Mullvad, AirVPN), or bypass the problem entirely with a tunnel like Cloudflare Tunnel or ngrok.
Verification
After applying fixes, confirm from an actual external network:
# From mobile data or a cloud VM
curl -v http://YOUR_PUBLIC_IP:8080
# Expected: HTTP response from your app
# Bad: "Connection refused" or a hang
Also check your router's firewall/NAT logs β most routers record whether packets are hitting the forwarding rule, which tells you exactly how far traffic is getting.
Tips
When chasing NAT and subnet issues, I keep the Subnet Calculator at ToolCraft open in a tab. It's useful for quickly confirming whether your server's LAN IP actually falls within the router's local range β easy to miscount the subnet mask when you're already frustrated. Runs in the browser, nothing uploaded.
A few quick sanity checks before diving into router config:
- Confirm the server is on the same subnet as the router's LAN interface (e.g., both on 192.168.1.0/24)
- Check that the server's default gateway points to the router β not some leftover static route
- Run
ip route(Linux) orroute print(Windows) to make sure traffic isn't sneaking out a different interface
Prevention
- Always assign a static IP or DHCP reservation to any server you forward ports to β a changing IP breaks your rules silently
- Write down your port forwarding rules somewhere. Router resets and firmware updates wipe them, and you'll forget what you configured six months later
- For reliable long-term remote access, WireGuard VPN beats opening individual ports β harder to attack, easier to audit, and works even on restrictive networks
- Always verify from outside your own network after any change. NAT loopback issues give misleading results when you test from the same LAN

