Which client IP header does your proxy send?

Every reverse proxy, load balancer and CDN hides the visitor's address behind its own, and each one hands the original back to you in a slightly different header. This is the reference table: what each vendor sets, whether you have to turn it on, and which header is actually safe to log.

Short answer. Nearly every proxy sets X-Forwarded-For, and it is the one to log: it is the cross-vendor standard and it preserves the whole proxy chain, so the address can be validated against a trust list. Vendor-specific headers like CF-Connecting-IP, True-Client-IP and X-Azure-ClientIP are simpler to parse because they hold a single address, but they carry no chain to validate and they tie your logging to one vendor.

What each field and header actually is

Two different things get called "the client IP" and they are easy to confuse. c-ip is a field in the IIS log. Everything else on this list is an HTTP request header set by something upstream. The whole job is getting the right header value into that one field.

Name What it is Holds
c-ip IIS W3C log field, not a header. The "client IP" column in your logs, and the value every SIEM, geo-IP lookup and compliance parser reads. By default IIS fills it with the TCP peer address, which behind a proxy is the proxy. One address
X-Forwarded-For The de facto cross-vendor standard, set by almost every proxy. Each hop appends the address it saw, so the header preserves the full chain and can be validated against a trust list. Comma-separated chain
Forwarded The formally standardised version (RFC 7239), carrying for=, proto= and host= in one header. Rarely used in practice; most proxies still send X-Forwarded-For. Structured chain
CF-Connecting-IP Cloudflare's own header, always the single address Cloudflare accepted the connection from. Simpler to parse than the chain, but Cloudflare-specific. One address
True-Client-IP Originally Akamai's header, also emitted by Cloudflare on Enterprise plans. Same meaning as CF-Connecting-IP. If both arrive, they should agree. One address
X-Azure-ClientIP Set by Azure Front Door: the client address Front Door determined, already stripped of the port. One address
X-Azure-SocketIP Also Azure Front Door: the raw TCP socket address of the connection. Differs from X-Azure-ClientIP when another proxy sits in front. One address
X-ARR-LOG-ID Added by IIS Application Request Routing. A per-request correlation GUID for tracing a request across ARR and the backend. It is not a client IP, despite the name suggesting a log value. GUID
X-Real-IP A convention, not a standard. Commonly set by hand in Nginx configs to carry a single address alongside X-Forwarded-For. One address

The reference table

Proxy / CDN On by default Headers it sets Notes
Cloudflare Automatic X-Forwarded-For
CF-Connecting-IP
True-Client-IP
CF-Connecting-IP holds the visitor address on its own. True-Client-IP is an Enterprise-plan feature. Full guide →
AWS Application Load Balancer
AWS Classic Load Balancer
Automatic X-Forwarded-For Added for you at layer 7. Nothing to enable. Full guide →
AWS Network Load Balancer Not applicable None Operates at layer 4. With target-type instance the original source IP reaches your server intact, so no header is needed, and none is added.
Azure Application Gateway Automatic X-Forwarded-For Appends IP:port, not a bare address. Anything parsing the header has to strip the port. Full guide →
Azure Front Door Automatic X-Forwarded-For
X-Azure-ClientIP
X-Azure-SocketIP
X-Azure-ClientIP is the visitor address; X-Azure-SocketIP is the address of the socket that connected to the edge. Full guide →
F5 BIG-IP (LTM) Off by default X-Forwarded-For Enable Insert X-Forwarded-For on the HTTP profile attached to the virtual server. Without it, SNAT leaves you with F5 addresses only. Full guide →
IIS Application Request Routing (ARR) Automatic X-Forwarded-For
X-ARR-LOG-ID
X-ARR-SSL
Preserve client IP in the following header defaults to X-Forwarded-For in the ARR server proxy settings — worth confirming rather than assuming. X-ARR-LOG-ID is a correlation ID, not an address. Full guide →
Nginx Off by default X-Forwarded-For Nothing is forwarded until you add it yourself: proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; Full guide →
HAProxy Off by default X-Forwarded-For Requires option forwardfor in the backend or defaults section. Full guide →
Apache mod_proxy Automatic X-Forwarded-For
X-Forwarded-Host
X-Forwarded-Server
mod_proxy_http adds all three when acting as a reverse proxy.
Akamai Check setting True-Client-IP
X-Forwarded-For
True-Client-IP is Akamai's original single-value header; the header name itself is configurable in property settings.
Fastly Automatic Fastly-Client-IP
X-Forwarded-For
Fastly-Client-IP holds the visitor address on its own.

How the X-Forwarded-For chain works

X-Forwarded-For is not a single address — it's a comma-separated list, and each proxy in the path appends the address it received the connection from. A request through a CDN and then an internal load balancer arrives looking like this:

X-Forwarded-For: 203.0.113.45, 198.51.100.7, 10.0.0.12

Reading left to right: 203.0.113.45 is the visitor, 198.51.100.7 is the CDN edge that spoke to your load balancer, and 10.0.0.12 is the load balancer that spoke to your web server. The leftmost entry is the one you want.

Why you can't just take the leftmost value

The leftmost entry is also the only one an attacker controls. Anyone who can reach your origin directly can send X-Forwarded-For: 1.2.3.4 and every proxy in front of you will simply append to it, leaving their forged value sitting in first position.

The safe method is to walk the list from the right, discarding addresses you recognise as your own infrastructure, and take the first address that isn't on your trust list. That's the last hop you can actually vouch for. This is what a Proxy Trust List does in X-Forwarded-For for IIS, and it's why the chain matters: a single-value header like CF-Connecting-IP gives you nothing to validate.

Trust the header only as far as you trust the path. Header validation is worth little if attackers can bypass the proxy entirely. Restrict your origin firewall to accept traffic only from your proxy's published ranges, so the header can't arrive from anywhere else.

Three gotchas worth knowing

Frequently asked questions

Should I log X-Forwarded-For or CF-Connecting-IP?

X-Forwarded-For. Both carry the visitor's address, but X-Forwarded-For preserves the full proxy chain, so the value can be validated against a trust list rather than taken on faith. It's also the cross-vendor standard, so the same logging setup keeps working if you change CDN. CF-Connecting-IP is single-value and Cloudflare-only.

Why does X-Forwarded-For contain several IP addresses?

Because every proxy the request passed through appended the address it saw. The list reads oldest-first: the leftmost entry is the original visitor and each subsequent entry is a hop closer to your server. Multiple addresses mean multiple proxies, not an error.

Can X-Forwarded-For be spoofed?

Yes, trivially, if your origin server can be reached directly. A client can set any value it likes and the proxies in front will append rather than replace it. The defence is two-part: validate the chain from the right against a trust list of your own proxies, and firewall the origin so requests can only arrive through them.

What is X-ARR-LOG-ID?

A correlation ID that IIS Application Request Routing adds so a request can be traced across the proxy and the backend. It is not a client IP address; ARR carries the address in X-Forwarded-For, when preserving the client IP is enabled.

Does IIS read these headers on its own?

No. Microsoft never built X-Forwarded-For support into IIS, so the c-ip field always records the address of whatever opened the TCP connection (your proxy). Restoring the real address needs a filter that reads the header and writes it into the log.

Log the real client IP in IIS

X-Forwarded-For for IIS reads the header your proxy sets and writes the real visitor address into the standard IIS c-ip field, with a Proxy Trust List to validate the chain. Works behind any of the proxies above. IIS 10 on Windows Server 2016–2025.

View the product   or request a download →