IIS7/8: Logging the real client IP in the IIS hit logs

I’ve seen questions around logging the real client IP in the IIS logs come up a handful of times in the past few weeks, so I figured I’d try and tackle that here. If you’re using load balancing with IIS (who isn’t these days?), then you’ve probably seen that by default, the load balancer’s IP address is generally what’s logged as the client IP in the c-ip field in your IIS logs. These days, most load balancers (and proxy servers) should have the ability to preserve the original client IP in an optional header: X-Forwarded-For. All well and good, but how exactly do we get IIS to log that XFF value to the c-ip field?

First, why would you want to? That’s easy enough to answer: if all you’re logging in c-ip is the IP address of your load balancer or proxy, it makes it harder to distinguish between requests from different clients, which can impact troubleshooting, reporting, or even forensic analysis of the logs should any penetration attempts occur. There may be other reasons as well, but that last one alone should make anyone running a web server want to ensure they’re logging the real client IP address. Out of the box, IIS doesn’t have any built-in functionality to read the value of that header and log it as the c-ip value, so to handle it, you have a couple of options:

 

1. You could use Advanced Logging to handle this, but personally, I feel like this is overkill that adds more administrative overhead than you need for this purpose. Introducing Advanced Logging means that you now have two hit logs to deal with, as this module logs to a separate file (located in ‘%SystemDrive%\inetpub\logs\AdvancedLogs’ by default). If you choose to go this route, it’s not that hard to set up, but you’ll  need to add a custom logging field entry to the Advanced Logging config. I’m going to steal re-use a sample that Robert McMurray posted internally a while back for this exact purpose:

<location path="Default Web Site">
  <system.webServer>
    <advancedLogging>
      <server>
        <fields>
          < field id="X-Forwarded-For" sourceName="X-Forwarded-For" sourceType="RequestHeader" logHeaderName="x-forwarded-for" category="Default" description="" defaultValue="" loggingDataType="TypeLPCSTR" />
        </fields>
      </server>
    </advancedLogging>
  </system.webServer>
</location>

There are also some instructions on loadbalancer.org on how to set this up if you want to go this route: http://blog.loadbalancer.org/iis-and-x-forwarded-for-header/

 

2. The cleaner option, in my opinion: Use an HTTP module to handle it during request processing. If you don’t want to write one yourself, there are a couple out there that can do the job for you:

OPTION 1: ARRHelper: http://blogs.iis.net/anilr/archive/2009/03/03/client-ip-not-logged-on-content-server-when-using-arr.aspx

When I originally wrote this blog entry, my understanding was that this module wasn't supported by the product group, as it was written by one of their developers as a side project. After an internal discussion a few months back, I discovered that the product group does in fact support this module now, so for those looking for a supported option that isn't Advanced Logging, this is it (big shout-out to the IIS PG for letting me add that info :) ). I’ve seen it used for this purpose (without ARR in play) in a couple of fairly large, high-traffic environments without any issues or performance degradation. Note: It does have one behavioral issue that I should mention, which is by design. In addition to logging the real client IP address in the c-ip field, it will also change the s-port value to either 80 or 443 depending on whether HTTP or HTTPS was in use for the request. Not an issue if your site is running on the standard HTTP/HTTPS ports, but if any of your sites run on non-standard ports, the s-port value won’t reflect this in the IIS logs when ARRHelper is in use. One example of what I mean: Let’s say you host www.contoso.com, and in the IIS bindings for your site, the HTTP binding is set to a port value of 8080, and you're load balancer handles redirection of client requests to the site on port 80 back to 8080 on the web server. In the IIS logs, with ARR in place, the s-port value would show as 80 in the IIS logs, even though the site is bound to and listening on port 8080.

Again, this is expected behavior. This is done to ensure that any links created by the code on the sever are relative to the port on the ARR/load balancer side (per the developer of ARRHelper). It shouldn’t be a big deal, however, unless you’re relying on the s-port value to differentiate your sites when you mine your hit logs.

OPTION 2: A 3rd party module, written by one of F5’s architects: https://devcentral.f5.com/blogs/us/x-forwarded-for-http-module-for-iis7-source-included#.UdrYQ6TD9mM

Much like ARRHelper, it doesn’t look like F5 provides official support for it (per Joe’s last sentence), but it appears he also provides the source code for it for those who want to see how this work is done in an HTTP module. Disclaimer: I’ve never downloaded/used this one, or had any customers that have, so I can’t comment on it other than to say it’s another option you can look at.

 

There may be other options out there, and if so, feel free to post them in the comments. These are just the ones I’m familiar with :-)

6 Comments

  • Hi,

    Can you please suggest me.
    In our network, we used H/W load balancer and i am not able to get the client IP address.

    Same setup, i did without load balancer. it was working. Please suggest me.

    @ as per your blogs. Shall we need ARR for help x-forwarded-for ?













  • Please suggest me how to use.
    mention blogs name Robert McMurray , I am not able to find.

  • Note that the config sample above is only useful if you are using the Advanced Logging module to log the client IP. The Advanced Logging module logs its data to a separate log file, it will not log the client IP to the regular IIS logs. If you want the client IP logged there (the default IIS logs), you need to look at one of the other choices I discussed above (ARRHelper or a 3rd party module).


  • Hi DeanC,

    Thanks for Reply me,

    Now i understand if we require client IP through XFF (Advanced Logging) than We need this config sample and in case we want client IP address in our default IIS logs then we use ARR.

    Please correct me if i am wrong.

    Please suggest me.
    In our network, we used H/W load balance and we are not able to get the client IP address.

  • First:

    "if we require client IP through XFF (Advanced Logging) than We need this config sample"

    I'm not sure what you mean by this. The XFF header is one supplied by the load balancer to preserve the originating client IP, it's not something tied directly to Advanced Logging. Advanced Logging is just one option for logging the value of that header, and as mentioned it does so to a separate log file

    "in case we want client IP address in our default IIS logs then we use ARR"

    Correct. If you want the value of c-ip in the IIS logs to reflect the original client IP that the load balancer passed to IIS in the XFF header, you'd use ARRHelper (you do not need to install the full ARR package), or the other HTTP module mentioned in the article from F5.

    "In our network, we used H/W load balance and we are not able to get the client IP address."

    As mentioned above, the load balancer still needs to pass the original client IP back to the web server (normally done in the XFF header), or none of this is going to work for you. Since IIS sits behind the load balancer, it can't see the originating IP without some assistance from the load balancer

  • Hi DeanC,

    Thanks for your information, now i able to getting the client IP. :)


Comments have been disabled for this content.