Logging the real client IP in IIS behind an AWS load balancer

Behind an AWS Application Load Balancer (ALB) or Classic ELB, IIS logs the load balancer's private IP instead of your real visitors. Here's why, and how to record the true client IP in the standard IIS log using the X-Forwarded-For header.

Short answer. An AWS ALB or Classic ELB terminates the client connection and opens a new one to your EC2 target, so IIS logs the load balancer node's private VPC address in c-ip. AWS already adds the visitor's address to the X-Forwarded-For header for you. Nothing to enable. Install an ISAPI filter on IIS that reads it and writes the real address into the standard c-ip field, trusting only your load balancer's subnet ranges.

The problem

An AWS Application Load Balancer (or Classic Load Balancer) terminates the client connection and opens a new one to your EC2 targets. The connection your IIS instance receives therefore comes from the load balancer node's private IP within your VPC subnets, so the IIS c-ip log field records the load balancer's addresses, not the visitor's, and geolocation, reporting and security tooling lose the real client.

Why it happens

This is normal layer-7 load balancing: the LB is the network peer your instance sees. AWS preserves the original client address for you in an HTTP header:

So the client IP reaches IIS in a header. But IIS doesn't read X-Forwarded-For natively. The header arrives and is ignored. That's the gap Winfrasoft X-Forwarded-For for IIS fills.

The fix: X-Forwarded-For for IIS

Winfrasoft X-Forwarded-For for IIS is an ISAPI web filter that reads the X-Forwarded-For header the load balancer adds and writes the real client address into the standard IIS c-ip log field (with no application changes). A Proxy Trust List of your load balancer's addresses ensures only the LB hop is trusted, so the genuine client is logged and the header can't be spoofed.

Step by step

  1. Use an HTTP/HTTPS listener on your ALB (or Classic ELB). X-Forwarded-For is added automatically — there's nothing to switch on.
  2. Install X-Forwarded-For for IIS on each EC2 target (IIS 10 on Windows Server 2016–2025).
  3. Add the load balancer's private addresses to the Proxy Trust List. ALB nodes draw addresses from the subnets the load balancer is attached to, so trust those subnet ranges. (See the Installation & Configuration Guide for the exact trust-list format.)
  4. Run IISRESET, then browse the site and confirm the IIS c-ip field shows real client addresses.

Lock down the targets. So a client can't reach your instances directly and forge an X-Forwarded-For header, set the EC2 security group to accept web traffic only from the load balancer's security group. Trusting only the LB's addresses is what keeps the logged client IP reliable.

Frequently asked questions

Does an AWS ALB add X-Forwarded-For automatically?

Yes. Application Load Balancers add the X-Forwarded-For header containing the client IP on HTTP and HTTPS listeners by default. Classic Load Balancers do the same for HTTP/HTTPS listeners.

What about a Network Load Balancer (NLB)?

An NLB operates at layer 4 and can preserve the original client IP at the network level (client IP preservation), so the source address often reaches IIS directly. Where it doesn't (or where Proxy Protocol v2 is used), carrying the client in X-Forwarded-For via an ALB is the simpler route for IIS logging.

Which addresses should I add to the Proxy Trust List?

The private IP ranges of the subnets your ALB is attached to (the addresses your instances see as the source). X-Forwarded-For for IIS then treats those as trusted and logs the first untrusted address, the real client.

Get X-Forwarded-For for IIS

Restore real visitor IPs in your IIS logs behind an AWS load balancer. Available now for IIS 10 on Windows Server 2016–2025, with a free 14-day trial.

View the product   or request a download →