The scenario
Internal-PC (192.168.1.10) and Internal-Server (192.168.1.50) share a switch with NAT-GW's LAN side (192.168.1.1). NAT-GW's public address is 203.0.113.1, and a port forward sends connections to 203.0.113.1:80 on to 192.168.1.50:80. From Internet (203.0.113.50) that works. When Internal-PC connects to 203.0.113.1:80, the gateway rewrites the destination to 192.168.1.50 and sends the packet back out onto the LAN, but the source is still 192.168.1.10. Internal-Server sees a LAN neighbour and answers it directly across the switch, from 192.168.1.50. Internal-PC is waiting for an answer from 203.0.113.1, so the reply matches nothing and the connection fails. The gateway's existing SNAT rule does not help: it only applies to traffic leaving through the WAN interface, ge1.
What you will work out
Understand why an inside client using a port forward's public address fails without hairpin NAT, and how masquerading that traffic to the gateway's LAN address brings the reply back through the gateway.
Why this matters
'My server works from outside but not from inside' is a classic self-hosting complaint, and a very common cause is this: the inside client uses the public name or address and the gateway has no hairpin NAT. Some home routers offer it as a 'NAT loopback' setting and some do not support it at all. Knowing why the reply goes astray lets you pick the right fix: hairpin NAT on the gateway, or split-horizon DNS so inside clients use the private address.
Running it
Hairpin NAT: Can't Reach Myself opens on a canvas, already wired and addressed. Trace a packet through it hop by hop, or run the same topology live on real Linux network namespaces. How the two modes differ.
Open Hairpin NAT: Can't Reach Myself
Runs in your browser. No install, no signup, and the simulation starts instantly.
Open the lab →