Logging the correct IP address using Apache 2.2.x
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 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.
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
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.