How to Determine the Client IP Behind a CDN or Reverse Proxy
If your website sits behind a content delivery network (CDN) or reverse proxy, your server may record that service's IP address instead of your visitor's. A CDN serves content through a network of servers; a reverse proxy receives requests on your website's behalf. The intermediary can pass along the address it observed in an HTTP header—extra information attached to the request. Your server should accept that information only from proxies you have explicitly configured it to trust.
The address your server selects from that trusted information is the derived client IP. Before using it, check which proxy supplied it, how that proxy set the value, and whether a visitor could bypass the proxy and send a forged header directly. The address and other details passed along by a proxy are called forwarding metadata. A familiar header name alone does not make them trustworthy.
Trust the connection path before trusting a forwarding header.
The result is best described as the derived client IP or edge-observed client IP. It is usually the source address observed by the first approved proxy receiving Internet traffic, called the trusted edge. That address may belong to a household network address translation (NAT) gateway, Carrier-Grade NAT (CGNAT) gateway, VPN endpoint, Tor exit, corporate forward proxy, or another intermediary. It does not prove the identity of a person or device.
What address can a website determine?
The application knows which system connected directly to it. That system is its immediate peer, also called its socket peer. A load balancer—a service that distributes requests among servers—may be that peer. The application can determine an earlier address only when the systems in between pass it along through a path the application is configured to trust.
In HTTP terminology, a forward proxy is selected by the client. A gateway, commonly called a reverse proxy, acts on behalf of the website's own server, called the origin. A public or client-controlled forward proxy is normally outside the website operator's trust boundary. Any address it adds to a forwarding header remains an unverified claim unless the operator has a separate authenticated relationship with that proxy.
A website will therefore ordinarily see the egress address of a VPN, Tor exit, or forward proxy, not an address behind it. This guide does not explain how to reveal an address concealed by one of those services. It explains how an origin safely receives the address observed by its own delivery infrastructure.
Which terms describe the request path?
- Immediate peer
- The system that opened the connection accepted by the current server. For an application behind a load balancer, this is usually the load balancer.
- Trusted edge
- The first operator-approved CDN or reverse proxy that accepts the Internet-facing connection. This is normally where the most useful externally observed address is established.
- Trusted proxy
- A proxy whose network identity, ingress path, and forwarding behavior are explicitly configured. Trust can come from restricted CIDRs, private networking, a provider tunnel, mutual TLS, or another authenticated origin mechanism.
- Derived client IP
- The address selected after validating the immediate peer and, when applicable, walking a forwarding chain. It records what trusted infrastructure established, not what an arbitrary request header claimed.
What is a safe client IP workflow?
- Map every route to the application. Include the normal CDN route, direct or internal routes, health checks, development access, failover paths, and secondary load balancers.
- Start with the immediate peer. If it is not trusted, ignore all client-IP forwarding headers and use the socket address.
- Restrict access to the origin. Prevent clients from bypassing the CDN or load balancer and submitting forged headers directly. Use firewall rules, private networking, a provider tunnel, or authenticated origin connections.
- Choose one agreed forwarding signal. Do not accept whichever of Forwarded, X-Forwarded-For, X-Real-IP, or a provider-specific header happens to be present.
- Define whether the signal is one value or a chain. A trusted proxy must remove incoming copies before setting an authoritative single-value header. For a chain, trusted proxies may append the peer they observed, but earlier entries remain claims until the application evaluates them relative to its trusted proxies.
- Use trusted-proxy support in the server or framework. Configure explicit proxy addresses or CIDRs instead of selecting the first header value in application code. A fixed hop count is safe only when every request follows the same route and no direct or shorter path can reach the application.
- Define failure behavior. If expected metadata is absent, malformed, duplicated unexpectedly, or inconsistent with the route, use the immediate peer or mark the derived address unavailable. Never silently fall back to another unsanitized header.
- Log the derivation evidence. Preserve the derived address, immediate peer, selected mechanism, and trust result.
Why does an IP lookup identify the CDN or hosting provider?
The application's immediate peer may be one of your load balancers or an address belonging to the CDN. Looking up that address will correctly describe the peer's network, not the derived client.
An IP address tag such as Content Delivery Network or Hosting describes a network role. It does not prove that the address acted as a proxy for this request. A hosting address can be the direct client, such as an automation worker, API consumer, or server-side crawler.
Establish the request path from your known topology, expected upstream ranges, and authenticated forwarding configuration, not from an IP classification alone.
Which forwarding signal should I use?
Use the signal documented by the edge you trust and supported by the component that validates it. These mechanisms are not interchangeable:
| Signal | Typical use | Main trust requirement |
|---|---|---|
| Provider-specific header | CDN-to-origin traffic | Accept only through the provider's restricted origin path and confirm that client-supplied values are overwritten. |
| X-Forwarded-For | Multi-hop HTTP deployments | Validate from right to left, beginning with the immediate peer. |
| Forwarded | Deployments using the standardized HTTP field | Use a conforming parser and the same trusted-chain model. |
| X-Real-IP | One trusted proxy selects the address to pass on | Remove incoming copies and overwrite the value. |
| PROXY protocol | Layer-4 load balancing and non-HTTP services | Enable only on a dedicated listener reachable from trusted upstreams. |
Forwarded
RFC 7239 defines the standardized Forwarded request field:
Forwarded: for=203.0.113.24;proto=https;by=198.51.100.10
Forwarded: for="[2001:db8::1]:4711";proto=https
Commas separate proxy elements, while semicolons separate parameters within one element. The specification also permits unknown and obfuscated identifiers, so a valid for= value is not necessarily an IP address. Do not parse the field with simple comma, semicolon, or colon splitting. Standardization does not authenticate the field; the client or any intermediary can modify it.
X-Forwarded-* and X-Real-IP
X-Forwarded-For: 203.0.113.24, 198.51.100.7
X-Forwarded-Proto: https
X-Real-IP: 203.0.113.24
X-Forwarded-For normally carries a client-and-proxy address chain. X-Forwarded-Proto preserves the external request scheme; it does not identify the client. X-Real-IP usually carries one address selected by a proxy, but its meaning depends on that proxy's configuration. See X-Forwarded-For Header: Format, Forwarded Comparison and Security for detailed syntax, repeated-field handling, spoofing examples, and implementation references.
PROXY protocol
A protocol is a set of rules for exchanging information. The PROXY protocol sends details about the original connection before the application starts exchanging its own messages. Those initial details form a preamble and include source and destination addresses and, where applicable, ports. A port is a number that helps distinguish applications or exchanges of data at an IP address. Version 1 uses a human-readable line. Version 2 uses a binary format and supports additional address families and optional Type-Length-Value metadata.
Configure a listener either to require PROXY protocol or not to use it. Do not guess whether a preamble is present, and allow only known proxies to reach a PROXY-enabled listener. PROXY metadata belongs to a connection. It cannot represent different clients whose HTTP requests are multiplexed over one shared upstream connection; use per-request forwarding fields in that situation.
How does trusted-chain processing work?
For an X-Forwarded-For chain, begin with the application's socket peer. If that peer is not trusted, ignore the header. If it is trusted, inspect entries from right to left. Continue while each address is a configured trusted proxy, then stop at the first untrusted address. That address is the derived client IP. Ignore values farther to the left for security-sensitive decisions.
The application trusts the load balancer and then the CDN. The next address, 203.0.113.40, is outside the trusted set, so it becomes the derived client IP. The farther-left value may have been inserted by the forward proxy. The website cannot verify it and should not use it for access control, rate limiting, or attribution.
A known enterprise forward proxy can be trusted when its identity and forwarding behavior are separately authenticated. A public anonymous proxy should not be.
What should I check for common CDN providers?
Cloudflare
For ordinary edge-to-origin traffic, CF-Connecting-IP contains the address that connected to Cloudflare. Accept it only through the intended Cloudflare origin path. A direct request can contain a forged header with the same name. Stacked-CDN and Worker subrequest paths require separate evaluation.
Akamai
Akamai can send a configurable client-IP header, commonly True-Client-IP. To use it as an authoritative edge-selected value, enable the header and disable the option that allows clients to set it. Accept it only through the intended Akamai delivery path.
Fastly
Fastly documents that an incoming Fastly-Client-IP value is not protected from modification at the edge. Before using it for access control, rate limiting, or attribution, overwrite it from the connection-derived client address on the appropriate first edge visit using Varnish Configuration Language (VCL).
Across all providers, the header name never authenticates the sender. In a direct request, a field called True-Client-IP, CF-Connecting-IP, or Fastly-Client-IP is merely attacker-controlled text. The related forwarding headers reference links to provider and server documentation.
What should I log?
Record at least:
- The derived client IP.
- The immediate peer IP.
- The forwarding mechanism used.
- The trusted-proxy policy or trust result.
- Whether the request was direct, successfully derived, missing metadata, or malformed.
- A request or trace identifier that can be correlated with edge and origin logs.
Keep a bounded and safely encoded copy of the original forwarding field only when it serves a defined operational purpose. Treat it as attacker-controlled input, restrict access, and minimize retention. Do not let a framework that rewrites its normal remote-address field erase the original peer from every log.
Derived client IP
Which source did the trusted edge attribute the request to?
Immediate peer IP
Which system actually connected to the application?
Even a correctly derived address may belong to a VPN, Tor exit, CGNAT gateway, or forward proxy. Its location and IP classifications describe that network endpoint, not necessarily the person making the request. See logging best practices for broader collection and storage guidance.
How should I test the configuration?
Test the complete deployed path, not only the parsing function:
- A direct request containing forged forwarding headers must not change the derived client IP.
- A request through the trusted edge with an extra forged leftmost value must still select the nearest untrusted address.
- A missing or malformed expected field must not cause fallback to another client-supplied header.
- IPv4, IPv6, and IPv6-with-port forms must follow the selected signal's syntax.
- Duplicate and repeated fields must be handled deterministically.
- Direct, shorter, health-check, development, and failover routes must not undermine a fixed-hop policy.
- A public client must not be able to reach a PROXY-enabled listener.
- Changes to CDN ranges, edge settings, load-balancer behavior, or framework configuration should rerun the same tests.
The safest implementation is not the one that recognizes the most forwarding headers. It accepts one documented signal through a verified delivery path and preserves enough evidence to explain every derived address.