VGTech is a blog where the developers and devops of Norways most visited website share code and tricks of the trade… Read more



Are you brilliant? We're hiring. Read more

Logging the correct IP address using Apache 2.2.x

DevOps

Here at VG we have loadbalancers and proxies in front of most of our webservers.
This is key to being able to handle the big amounts of traffic we get.

One problem that arise when traffic is being terminated this way is that the backend webserver, namely Apache will get either the IP of the loadbalancer or the proxy as originating address.

This is of course not desirable since we cannot see the actual client IP in the logs, and thus we cannot make other rules based on client IP in Apache.

What do we want?

  • Use the rightmost unknown IP of the X-Forwarded-For header, since this will contain the actual client IP.
  • Be able to define a subnet which are not rewritten.
  • Return the actual client ip in web applications.
  • Log the correct IP both in the error log and access log.
  • The solution should work with deny/allow, mod_rewrite, etc.

The solution

The solution is to make the loadbalancer and proxies set an extra header in the request to the backend server containing the actual client IP.
This header could be called whatever you’d like, but the most conventionally used name is X-Forwarded-For.

But how do we tell Apache to rewrite client IP and use the IP specified in the header ?

In Apache 2.4 there is included a module called mod_remoteip which does exactly this, but what if you use Apache 2.2 ?
Well, there exists a backport of mod_remoteip which is compatible with Apache 2.2.

However, this module does not suit our needs since it seems to break with mod_rewrite.
Then we have mod_rpaf, mod_extract_forwarded which also fail to do exactly what we want.

mod_vgremoteip

After testing out a bunch of different modules and observing that none of them fit all our requirements I ended up writing my own module based on mod_remoteip.

This have been tested thoroughly for a couple of months and seems to do the job well.

If you are interested in testing it out the source and build instructions are available on GitHub, https://github.com/vgnett/mod_vgremoteip

Example configuration:

Show code
LoadModule vgremoteip_module modules/mod_vgremoteip.so

<IfModule mod_vgremoteip.c>
# Name of header which contains the 'real' client IP†.
 VGRemoteIPHeader X-Forwarded-For

# Subnet to mark as trusted subnet (this ip will be allowed to set the X-Forwarded-For header and marked as a proxy ip).
# You should specify this.
VGTrustedProxy 10.1.0.0/26 

# You can also specify a single ip addresses. 
# Do not specify hostnames.
VGTrustedProxy 127.0.0.1 
</IfModule>

A little note on security

If you choose to make access restrictions based on the IP in X-Forwarded-For header you must ensure that the configuration do not in any way allow the client to tamper with the header.

System administrator at VG.


2 comments

  • Intangir

    hey thanks for this, this saved my sanity tonight.. i had a setup utilizing multiple GRE tunnels that mysteriously and frustratingly .. WONT WORK anymore.. i don't know why, my connection died, apparently the route changed, and the new one couldn't handle multiple tunnels going the same route? i don't know.. it didn't work..

    so i had to share one tunnel, and then set up a proxy at the other end for http.. but then the IPs were hidden, fortunately with this article i was able to reveal them again to the web server.

    thanks for putting forth the effort to write this article and share that code


  • Ole Fredrik Skudsvik

    Hi,

    Thanks for the positive feedback!
    Happy to hear that the module was useful to you :)


Leave your comment