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.

6 guides · cluster reviewed 8 September 2026

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#

MechanismLayerAppends or overwritesUse when
X-Forwarded-ForHTTP headerappends, comma separatedHTTP proxying, de facto everywhere
Forwarded (RFC 7239)HTTP headerappends, structuredyou want the standardised form and control both ends
PROXY protocolTCP prefixone block, before any payloadL4 proxying, TLS passthrough, non-HTTP protocols

Do these in order#

  1. 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.
  2. Strip inbound forwarding headers at your outermost hop so a client cannot seed the chain.
  3. Verify the result with real requests, including one that pretends to be an attacker. Client IP spoofing through proxies has the test procedure.
  4. 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#