X-Forwarded-For: Getting the Real Client IP Behind a Proxy

Updated: 2026-05-31

When traffic passes through a reverse proxy, load balancer or CDN, your application sees the proxy's IP in the TCP connection, not the visitor's. The X-Forwarded-For (XFF) header carries the original client IP — but only if you read it safely.

How the header grows

Each proxy appends the address it received the request from:

X-Forwarded-For: <client>, <proxy1>, <proxy2>

The left-most entry is the claimed original client; entries to the right are the proxies it traversed.

Why you must not blindly trust it

A client can send a fake X-Forwarded-For header themselves. If your app reads the left-most value without checking, an attacker can spoof any IP — bypassing IP allowlists, poisoning logs, or evading rate limits. This is a real and common vulnerability.

Read it correctly

Trust XFF only from your own infrastructure:

  1. Know how many proxies are in front of you (CDN + load balancer = 2).
  2. Start from the right-most entry and strip exactly that many trusted hops.
  3. The first address you reach that is not one of your trusted proxies is the real client.

This site applies that rule: it derives the client IP from XFF only for trusted proxy hops, otherwise it falls back to the connection address. See how an address looks to the world on the home page, and what it can reveal in what your IP can reveal.

Note: The newer Forwarded: header (RFC 7239) standardizes this with explicit for= / proto= fields. Use whichever your proxy sets, but apply the same trust discipline.

Sources