skip to content

Staff on the same subnet as a port-forwarded web server browse to the IPv4 NAT's public address and see a hang behind one NAT and the router's own login page behind another; why?

level: seniorimportance: should knowfreq 20%

answer

  1. two different points of failure
  2. forward rule matched where
  3. who actually received the SYN
  4. ping proves nothing here

basics

~20 s

The login page means the NAT never applies the port forward to inside traffic, so its own management service answers its own address. The hang means it rewrites only the destination, so the server replies directly and the client resets the unexpected reply.

solid answer

~50 s

The **login page** comes from a NAT that does not hairpin at all: its forward rule matches only packets arriving on the outside interface, so the inside SYN is just a packet to the router's own address and its own HTTPS management service answers. The server never sees a SYN. The **hang** comes from a NAT that applies the forward but rewrites only the destination: the server sees an inside source on its own subnet and replies directly, the client's TCP has no connection with `10.20.0.10:443` and resets it, and the client keeps retrying `203.0.113.10` until it times out. A capture on the server separates them: no SYNs means the NAT kept the traffic, SYNs from inside addresses mean the reply is bypassing it. Ping to the public address proves nothing: the router answers it itself.

go deeper

for a junior

Recall that inside traffic to the public address reaches the NAT itself, and that a NAT may either keep it or forward it without fixing the reply path.

for a middle

Explain both traces: the forward rule that only matches outside traffic, and the direct server reply that the client resets.

for a senior

Show the diagnostic split: capture at the server for SYNs and their source, capture at the client for the stray SYN-ACK and RST, and why ping proves nothing.

for a principal

Turn the diagnosis into a standard: which fix the organisation adopts for published services, and how teams avoid depending on device-specific hairpin support.

## The setup An office NAT has the public address `203.0.113.10` and forwards `203.0.113.10:443` to an inside web server at `10.20.0.10`. Staff on the server's own subnet, `10.20.0.0/24`, browse to the public name, which resolves to `203.0.113.10`. Outside users reach the site fine. Two NAT devices give two different failures for the same inside request: - behind one, the browser **hangs** and finally times out; - behind the other, the browser shows **the router's own login page**. Both are hairpinning failures, but at different points in the NAT's processing. ## Symptom 1: the router's own login page The NAT does not hairpin at all. In many implementations, a port-forward rule is matched only against packets arriving on the **outside** interface. The staff member's SYN arrives on the **inside** interface, so it never matches the forward. What is left is a packet addressed to one of the router's own addresses. A router delivers such packets to its own local services, so if the router runs its management web service on port `443`, that service answers. The browser shows the router's login page under the portal's name, usually with a certificate warning, because the router's certificate does not carry the portal's name. If the router has no local service on that port, the same root cause shows up differently: the router's TCP refuses the connection with a reset, or its local filtering drops the SYN and the browser hangs. In all of these, the **server never sees the connection attempt**. ## Symptom 2: the hang The NAT applies the forward to inside traffic but rewrites only the **destination**. The trace: 1. Client `10.20.0.55:50123` sends a SYN to `203.0.113.10:443`. 2. The NAT rewrites the destination to `10.20.0.10:443` and leaves the source as `10.20.0.55:50123`. 3. The server sees a SYN from a host on its own subnet and sends its SYN-ACK **directly** to `10.20.0.55`, bypassing the NAT. 4. The client is waiting for `203.0.113.10:443`. A segment from `10.20.0.10:443` matches no connection it has, so under RFC 9293 it answers with a reset (a host firewall may simply drop it). 5. The client retransmits its SYN to the public address until it gives up. The user sees a hang. A compliant NAT avoids this by also rewriting the **source** to the client's external mapped endpoint, as RFC 4787 REQ-9a (UDP) and RFC 5382 REQ-8a (TCP) require, so the reply has to return through it. ## Telling them apart from the protocol evidence | Evidence | No hairpinning | Destination-only rewrite | |---|---|---| | SYNs from the inside client reach the server | no | yes, with the client's inside source | | Client receives a SYN-ACK from `10.20.0.10` | no | yes, and answers it with RST | | Staff on another inside subnet routed by the same NAT | also fail | succeed, because the reply crosses the NAT | | Outside users | succeed | succeed | - A **packet capture on the server** is the fastest split: no SYNs at all means the NAT kept the traffic; SYNs from inside addresses mean it forwarded with only the destination rewritten. - A **capture on the client** that shows a SYN-ACK from the server's inside address followed by the client's RST is the signature of the reply bypassing the NAT. - **Ping is not evidence.** An ICMP Echo Request from inside to `203.0.113.10` is addressed to the router's own address, so if the router answers ping at all, it answers it itself, in both cases. A successful ping says nothing about the port forward. ## Fixing each - **Enable full hairpinning** where the device supports it: the forward applies to inside traffic and the source is rewritten too. This fixes both symptoms. - **Split-horizon DNS**: the inside resolver answers the name with `10.20.0.10`, so inside clients never use the public address. This fixes both symptoms for clients that use the name and the inside resolver. - **Put the server on its own subnet.** This fixes only the hang, because replies to inside clients must then cross the NAT and the destination rewrite is reversed. It does nothing for a NAT that never applies the forward to inside traffic. Restricting the router's management service to another port changes symptom 1 into a refusal or a hang; it does not create hairpinning.

  • In the hanging case, why do staff on a different inside subnet reach the server through the public address without trouble?
    Their requests get the same destination rewrite, but the server's reply to an off-subnet client must go through its default gateway, the NAT device. The NAT sees the reply, reverses the destination rewrite and restores the public source, so the client sees exactly the endpoint it called. Only clients on the server's own subnet get the direct, unexpected reply.
  • Which of the usual fixes repairs the hang but not the login-page case?
    Moving the server onto its own subnet. It makes every inside client's reply cross the NAT, so a destination-only rewrite completes correctly. A NAT that never applies the forward to inside traffic still delivers the packet to itself, so the login page remains. Full hairpinning or split-horizon DNS fix both cases.

saying these in an interview costs you the question

  • A successful ping to the public address proves the hairpin path works.
  • The login page means the port forward is misconfigured for outside users.
  • The hang must be the server's firewall, since the NAT forwarded the SYN.
  • Moving the server to another subnet fixes every hairpinning failure.
  • Both symptoms come from the same NAT behaviour on different browsers.