Testing Inbound Reachability: Port Checks, Hairpin NAT, and What ‘Open’ Really Means

Smartphone on mobile data running an external port reachability test against a home server

The only reliable way to test if a port is open on your home network is from outside it — a phone on mobile data or an external port-checking service hitting your public IP while the service is actually listening. A test from inside your own LAN proves nothing, because NAT reflection can make a port look open when it is closed to the world, or closed when it is fine. “Open” only means something when the request came from off-network and a real service answered.

This is the step people skip, and it is why “I opened the port and it still doesn’t work” is such a common dead end. I never trust an in-LAN check; I confirm from a vantage point that genuinely sits on the public internet. This guide covers how to test properly, what open versus closed versus filtered actually mean, the hairpin NAT trap that fools everyone, and the checklist to walk when a port refuses to open. It is the verification step for everything in the main reachability guide.

Test From Outside, With the Service Running

A valid reachability test has two requirements: the request must originate outside your network, and the target service must be listening at that moment. Use a phone on cellular data (Wi-Fi off), an external port-checker website, or a remote machine running a port scan against your public IP and port. If the service is not actually running, even a perfect network setup will report the port closed.

The cleanest external test I use is a phone on mobile data with Wi-Fi disabled — it is genuinely off your network and on a different carrier path, so it sees your connection exactly as the outside world does. Point it at your public IP and the target port, or use a web-based “can you see me” port checker that connects back to your address from its own servers. For something scriptable, a remote box running a port scan or a simple netcat connection works too. Whatever the tool, make sure the service is up first: a web server, game server, or SSH daemon has to be listening and bound to the LAN-facing address, or the test fails for a reason that has nothing to do with your firewall. Test the service locally first to confirm it answers, then test from outside to confirm the path.

Smartphone on mobile data running an external port check against a home server's public IP

What ‘Open’, ‘Closed’, and ‘Filtered’ Actually Mean

Port scanners report three states with distinct meanings — the same open, closed, and filtered classifications the Nmap port-scanning documentation defines. Open means a service accepted the connection — success. Closed means the packet reached your host but nothing was listening on that port, so it was actively refused. Filtered means no response came back at all, which usually indicates a firewall silently dropping the traffic, or that you never reached your host because of CGNAT.

Telling these apart points you straight at the cause:

  • Open — the full path worked and a service answered. You are reachable. If the app still misbehaves, the problem is now in the application, not the network.
  • Closed — your packet reached the host but got an active refusal because nothing is listening on that port there. This usually means the service is down, bound to the wrong interface (often 127.0.0.1), or your forward points to the wrong internal IP. The good news: a “closed” result proves traffic is reaching your network, so NAT and CGNAT are not the blocker.
  • Filtered — no answer at all. Either a firewall rule is silently dropping the traffic (missing or misordered WAN pass rule), or the connection never reached your router because you are behind CGNAT. Confirm your connection state with how to tell if you’re behind CGNAT before assuming it is a firewall.

The Hairpin NAT Trap

Hairpin NAT, also called NAT loopback, is why testing your public IP from inside your LAN is unreliable. When a device on your network connects to your own public IP, the router has to “hairpin” that traffic back inside. Some routers do this and some do not, so an in-LAN test can succeed even when the port is closed to the outside, or fail even when external access works perfectly.

This single misunderstanding wastes more troubleshooting time than almost anything else. Picture connecting to your public IP from your laptop on the same LAN: if your router supports hairpinning, the request loops back and hits your service, so you see “it works” — but that says nothing about whether an outside client can reach you. Conversely, if your router does not support NAT loopback, your in-LAN test fails with a connection error even though someone on the actual internet connects fine. Either way the in-LAN result is noise. That is the whole reason the test has to come from outside: only an off-network request exercises the real inbound path. If you specifically need to reach your services by their public name from inside the house, that is a separate hairpin-NAT or split-DNS configuration on your router, not a reachability problem to chase.

Illustration of NAT loopback hairpin traffic looping back inside a home router

The Tools Worth Knowing

A few simple tools cover every test you need. On the host, check what is actually listening; from outside, use a port checker or a remote scan; and confirm the service answers locally before blaming the network. Knowing which tool reports which layer keeps you from chasing the wrong problem.

The ones I reach for, roughly in the order I use them. To confirm a service is listening and on which address, run ss -tlnp (or the older netstat -tlnp) on the host — if it shows the port bound to 127.0.0.1 instead of the LAN IP or 0.0.0.0, that is your culprit before you touch anything else. To test the path from outside, a web-based port checker that connects back to your public IP is the fastest, and a phone on mobile data gives you a real external client. For a scriptable check from a remote machine, nmap -Pn -p PORT your.public.ip reports open, closed, or filtered directly, and nc -vz your.public.ip PORT is a quick yes/no connection test. To prove the service itself works regardless of the network, hit it locally on the host first — if it fails there, the network was never the issue. Layer these from the inside out and each result tells you exactly which link in the chain to fix next, which dovetails with the checklist below.

The Checklist When a Port Won’t Open

Work the chain from the service outward. Confirm the service is listening on the LAN interface, not localhost; confirm the port forward points to the correct, current internal IP; confirm a firewall pass rule exists on the WAN above any block rules; confirm you are not behind CGNAT; then test from outside. Each step rules out one layer, and the order matters — fixing the firewall is pointless if the service is bound to 127.0.0.1.

Here is the exact order I walk, because each step eliminates a layer the next one depends on:

  • Is the service listening on the right address? Many apps default to 127.0.0.1, which is unreachable from anywhere but the host itself. It must listen on the LAN IP or all interfaces. This is the single most common cause of a “closed” result.
  • Is the forward pointing at the correct internal IP? A DHCP lease change quietly breaks a static forward. Use a DHCP reservation for anything you forward to.
  • Is there a matching firewall pass rule on the WAN? On OPNsense and pfSense a port forward needs an accompanying pass rule, placed above any block rules — order is significant, as the OPNsense NAT manual spells out. See OPNsense firewall rules.
  • Are you actually reachable at all? A “filtered” result with everything else correct points at CGNAT. Verify with the CGNAT check, and if confirmed, switch to a tunnel from beating CGNAT without a public IP.
  • Did you forget bridge mode? If your router’s WAN holds a private address, an upstream router is still doing NAT — fix it per bridge mode vs passthrough before anything else can work.

If you have walked all five and the port still will not open, the broader home network troubleshooting guide covers the adjacent failures — DNS, routing, and service-level issues — that can masquerade as a closed port.

Frequently Asked Questions

How do I test if a port is open on my home network?

Test from outside your network with the service running. Use a phone on mobile data with Wi-Fi off, an external port-checker website, or a remote machine scanning your public IP and port. A test from inside your LAN is unreliable because NAT reflection can make the result misleading.

Why does a port checker say closed when I set up the forward?

Most often the service is not listening on the LAN interface, commonly because it is bound to 127.0.0.1, or the forward points to the wrong internal IP. A closed result means traffic reached your host but nothing answered, so check the service binding and the forward target before the firewall.

What is the difference between closed and filtered?

Closed means the packet reached your host and was actively refused because nothing was listening, which rules out NAT and CGNAT as the blocker. Filtered means no response came back at all, indicating a firewall silently dropping the traffic or that you are behind CGNAT and never reached your router.

Why does my port work from inside but not outside?

That is the hairpin NAT trap. Connecting to your public IP from inside your LAN exercises NAT loopback, not the real inbound path, so it can succeed even when the port is closed to the outside world. Always confirm reachability from a device on mobile data or another external network.

Related Articles

Leave a Comment

Your email address will not be published. Required fields are marked *