The c-ip field in IIS logs

If you've opened an IIS log and found the same address on every single line, you've met c-ip. This is what the field is, what fills it, why a proxy makes it useless, and how it differs from the X-Forwarded-For column people add next to it.

Short answer. c-ip is the client IP address field in the IIS W3C log. IIS fills it with the address of whatever opened the TCP connection, so behind a proxy, load balancer or CDN it records that device rather than the visitor. IIS never reads X-Forwarded-For to correct it.

What does c-ip stand for?

Client IP. The W3C Extended Log File Format that IIS uses names its fields by prefix: c- for client, s- for server, cs- for client-to-server, and sc- for server-to-client. So c-ip is the client's address, s-ip is the server's, cs-method is the method the client sent, and sc-status is the status code the server returned.

Reading the prefix makes the rest of the log self-explanatory. Here are the fields you'll actually meet:

Field What it holds
c-ip Client IP. The address of the TCP peer. Behind a proxy this is the proxy.
s-ip Server IP. Which of the server's own addresses accepted the request.
cs-method The HTTP method: GET, POST and so on.
cs-uri-stem The requested path, without the query string.
cs-uri-query The query string, or - if there wasn't one.
cs-username The authenticated user, or - for anonymous requests.
cs(User-Agent) A request header. Parenthesised names are headers rather than connection facts.
sc-status The HTTP status code returned.
time-taken How long the request took, in milliseconds.

That distinction between a plain name and a parenthesised one matters more than it looks, and it is the root of the confusion this page exists to clear up. c-ip is a fact about the connection. cs(X-Forwarded-For) would be a header the client sent. They are filled from different places and they are not interchangeable.

Where are the IIS logs?

By default, one folder per site under:

C:\inetpub\logs\LogFiles\W3SVC1\

The number after W3SVC is the site ID from IIS Manager, so a server hosting several sites has several folders. Each file opens with a #Fields: line naming the columns in order, which is what tells you (and your log parser) which position c-ip occupies:

#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query
s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status
sc-substatus sc-win32-status time-taken

If c-ip isn't in that line, the field has been switched off in the site's logging configuration. In IIS Manager that is Logging, then Select Fields.

Why does c-ip show my load balancer's address?

Because a reverse proxy terminates the client's connection and opens its own to IIS. IIS records the peer of the connection it accepted, which is the proxy. The visitor's address never reaches the TCP layer, so c-ip has no way to know it.

The proxy usually does pass the original address along, in the X-Forwarded-For request header. The gap is that IIS does not read it. Microsoft never built X-Forwarded-For handling into IIS logging, so the header arrives, sits in the request, and is discarded unless something reads it and acts on it. Our reference of which header each proxy sends covers what your particular device puts where.

The symptom is unmistakable once you know it: every line in the log carries one of a small set of addresses, matching the number of proxies or SNAT addresses in front of the estate.

How do I check what my c-ip actually contains?

Open the newest log file and look at the column. If you want to be quicker about it, this counts the distinct values so you can see the problem rather than infer it:

$log = Get-ChildItem C:\inetpub\logs\LogFiles\W3SVC1 |
       Sort-Object LastWriteTime | Select-Object -Last 1

$fields = (Select-String '^#Fields:' $log.FullName |
           Select-Object -Last 1).Line -replace '^#Fields: ' -split ' '
$i = [Array]::IndexOf($fields, 'c-ip')

Get-Content $log.FullName |
    Where-Object { $_ -notmatch '^#' } |
    ForEach-Object { ($_ -split ' ')[$i] } |
    Group-Object | Sort-Object Count -Descending |
    Select-Object -First 10 Count, Name

A healthy internet-facing site returns a long tail of distinct addresses. A handful of values covering every request means c-ip is recording your infrastructure.

What is the difference between c-ip and cs(X-Forwarded-For)?

IIS 8.5 and later let you add a custom log field sourced from a request header, which appears as cs(X-Forwarded-For). This is free, native, and worth knowing about, but it does something different from what most people want: it adds a column and leaves c-ip alone.

c-ip cs(X-Forwarded-For)
Filled from The TCP connection A request header
Behind a proxy, shows The proxy Whatever the header says
Position in the log Standard field, expected by parsers Appended at the end, after the standard fields
Validated? Cannot be forged: it is the connection No trust list. A forged header is logged as sent
Read by SIEM connectors and geo-IP tooling Yes, by default Only after reconfiguring each one, where that is even possible

So the custom field answers "what did the proxy claim?" while leaving the field everything else reads still pointing at the proxy. If you own the log analysis end to end and can repoint it, that may be enough. If a SIEM, a compliance requirement or a packaged reporting tool is involved, it usually isn't, because those key off c-ip and many cannot be told otherwise. That trade-off is covered in more depth in why SIEM and compliance tooling needs the c-ip field.

Adding the custom field, if that is what you need

  1. In IIS Manager, select the site and open Logging.
  2. Confirm the format is W3C, then choose Select Fields.
  3. Choose Add Field, name it X-Forwarded-For, set the source type to Request Header and the source to X-Forwarded-For.
  4. Apply, then recycle the application pool. New requests get the extra column.

Remember that the value is unvalidated. Anything that can reach IIS directly can set the header to whatever it likes, and the log will record it faithfully.

Getting the real client address into c-ip

The only way to make c-ip itself correct is for something to read the forwarded header and write the address into the field as IIS records it. That is what an ISAPI filter does, and it is why the approach has been in use since the IIS 6 era.

The important part is the trust check. Because a header can be forged, a filter worth using validates the forwarding chain against a list of proxies you trust, and ignores the header when it arrives from anywhere else. Without that, correcting c-ip would trade a wrong-but-honest log for a confidently-wrong one, which is worse for an audit trail than no change at all.

Frequently asked questions

What is c-ip in IIS logs?

c-ip is the client IP address field in the IIS W3C log. IIS fills it with the address of whatever opened the TCP connection to the server. On a directly-exposed server that is the visitor; behind a proxy, load balancer or CDN it is that device instead.

Why is c-ip the same address on every request?

Because a reverse proxy is terminating the client connection and opening its own to IIS, so every request genuinely arrives from the proxy. The number of distinct addresses you see usually matches the number of proxies or SNAT addresses in front of the servers.

Does IIS use X-Forwarded-For for c-ip automatically?

No. Microsoft never built X-Forwarded-For support into IIS logging. The header arrives with the request and is discarded unless a filter or module reads it. c-ip always records the TCP peer address unless something explicitly rewrites it.

What is the difference between c-ip and cs(X-Forwarded-For)?

c-ip is a standard field filled from the connection and cannot be forged. cs(X-Forwarded-For) is an optional custom field filled from a request header, appended after the standard fields, and logged exactly as sent with no trust validation. Adding the custom field does not change c-ip.

Where is the c-ip field in the IIS log file?

Its position varies by configuration, which is why each log file starts with a #Fields: line naming the columns in order. Read that line rather than assuming a fixed column number, because a server with custom fields enabled will not match the default layout.

Can I turn the c-ip field off?

Yes, in IIS Manager under Logging, then Select Fields, though there is rarely a reason to. If c-ip is missing from a log's #Fields: line, that is what has happened. Most log tooling treats its absence as a broken log rather than an empty one.

Make c-ip show the real visitor

X-Forwarded-For for IIS reads the header your proxy sets and writes the real client address into the standard c-ip field, validated against a Proxy Trust List so a forged header is ignored. Nothing downstream needs reconfiguring. IIS 10 on Windows Server 2016–2025.

View the product   or request a download →