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
# Name of header which contains the 'real' client IP†.
# 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.
# You can also specify a single ip addresses.
# Do not specify hostnames.
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.