Topic cluster
Client IP and forwarding headers
X-Forwarded-For, RFC 7239 Forwarded, X-Real-IP and the PROXY protocol, and how to trust any of them without opening a spoofing hole in your own stack.
The moment you put a proxy in front of an application, the address the application sees stops being the client's address. Everything downstream that depended on it, rate limiting, geolocation, IP allowlists, abuse handling, audit logs, quietly starts operating on the wrong value or on a value an attacker controls.
This cluster is about getting that one value right. The short version: the client IP is not a header, it is the result of walking a chain of hops and deciding which of them you trust. Get the trust boundary wrong in either direction and you either lose the real address or accept a forged one.
The three mechanisms#
| Mechanism | Layer | Appends or overwrites | Use when |
|---|---|---|---|
| X-Forwarded-For | HTTP header | appends, comma separated | HTTP proxying, de facto everywhere |
| Forwarded (RFC 7239) | HTTP header | appends, structured | you want the standardised form and control both ends |
| PROXY protocol | TCP prefix | one block, before any payload | L4 proxying, TLS passthrough, non-HTTP protocols |
Do these in order#
- Decide which hops you trust, and write them down as CIDRs or as a hop count. Configuring trusted proxies has the exact syntax for every common proxy and framework.
- Strip inbound forwarding headers at your outermost hop so a client cannot seed the chain.
- Verify the result with real requests, including one that pretends to be an attacker. Client IP spoofing through proxies has the test procedure.
- Log both the socket peer and the derived client IP. When they disagree unexpectedly, you want the evidence.
Work out what your current configuration produces with the client IP resolver.
Every guide in this cluster#
- Client IP spoofing through proxiesHow X-Forwarded-For spoofing bypasses rate limits, IP allowlists and admin panels, the misconfigurations behind it, and a curl test for your stack.
- The Forwarded header (RFC 7239)The RFC 7239 Forwarded grammar in full: for, by, host and proto, node identifiers, mandatory quoting, parser pitfalls, and which proxies emit it.
- The PROXY protocol (v1 and v2)PROXY protocol v1 and v2 at byte level: the exact grammar, the TLV registry, an annotated hex dump, a send/receive support matrix, and the listener rule.
- Configuring trusted proxiesCorrect trusted-proxy config for nginx, HAProxy, Apache, Envoy, Traefik, Caddy, Express, Django, Rails and Spring Boot, plus a curl test that proves it.
- The X-Forwarded-For headerHow X-Forwarded-For is ordered, why the leftmost entry is attacker-controlled, and the right-to-left trusted-proxy walk that resolves the real client IP.
- X-Real-IP, X-Forwarded-Proto, Host and PortHow X-Real-IP, X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Port behave, the redirect loop they cause, and nginx $host vs $http_host vs $proxy_host.