Skip to content
← All articles

X-Forwarded-For Header: Understanding Client IP Behind Proxies

When a request passes through proxies, load balancers, or CDNs, the original client IP address is lost — the server sees the proxy's IP instead. The X-Forwarded-For (XFF) header solves this by carrying the client's real IP address through the proxy chain.

How X-Forwarded-For Works

Each proxy appends the previous hop's IP to the XFF header:

Client (203.0.113.50) → Proxy1 (10.0.0.1) → Proxy2 (10.0.0.2) → Server

X-Forwarded-For: 203.0.113.50, 10.0.0.1

The leftmost IP is the original client. Each subsequent IP is a proxy that forwarded the request.

Related Headers

Why It Matters

Server Configuration

Nginx

# Trust only your known proxies
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Apache

# mod_remoteip
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 10.0.0.0/8
RemoteIPTrustedProxy 172.16.0.0/12

PHP

function getClientIP(): string {
    $trusted_proxies = ['10.0.0.0/8', '172.16.0.0/12'];

    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
        // Traverse from right, skip trusted proxies
        foreach (array_reverse($ips) as $ip) {
            if (!isTrustedProxy($ip, $trusted_proxies)) {
                return $ip;
            }
        }
    }
    return $_SERVER['REMOTE_ADDR'];
}

Security: The Trust Chain Problem

XFF is trivially spoofable. Any client can send:

X-Forwarded-For: 1.2.3.4

If your server blindly trusts the leftmost IP, an attacker can impersonate any IP address. The solution: only trust XFF entries added by known, trusted proxies.

Correct Parsing Algorithm

  1. Start from the rightmost IP in X-Forwarded-For
  2. Check if it's a trusted proxy IP
  3. If trusted, move left to the next IP
  4. The first non-trusted IP is the real client IP
  5. Never trust the leftmost IP blindly — it could be spoofed

Common Pitfalls

Cloudflare-Specific

Cloudflare provides CF-Connecting-IP header with the verified client IP. This is more reliable than XFF because Cloudflare controls it. Configure your server to trust Cloudflare's IP ranges and use this header.

Conclusion

X-Forwarded-For is essential for any application behind proxies, but it must be handled with care. Configure your trust chain correctly, parse from right to left, and never blindly trust the leftmost IP. For security-critical decisions, prefer provider-specific headers like CF-Connecting-IP when available.

Check your website right now

Check now →
More articles: HTTP
HTTP
HTTP Methods Explained: GET, POST, PUT, DELETE and Beyond
16.03.2026 · 18 views
HTTP
HTTP/2 vs HTTP/3: Differences and Performance Comparison
13.03.2026 · 15 views
HTTP
HTTP Caching Guide: Cache-Control, ETag, Expires
14.03.2026 · 12 views
HTTP
Server-Sent Events vs WebSockets: Choosing Real-Time Communication
16.03.2026 · 24 views