Published : 2016-05-20

Source IP tracking

In a high-availability web environment there are typically HTTP load balancers like HAProxy, or reverse proxies like Apache or Nginx, sitting in front of the application servers to spread the load and/or filter some requests.

The main problem with this kind of architecture is that the front-end web service usually masks the source IP of the client, reducing traceability on the backends. This article assumes that the front-end web service forwards the IP to the backend via an HTTP header called X-Real-IP.

The trick shown here lets you log the client IP via the X-Real-IP header when it is present, otherwise fall back to the source IP.

First, define two LogFormats, complete_realip and complete, each with a different first field:

LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Host}i\" %D" complete_realip
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Host}i\" %D" complete

Next, use the mod_setenvif module to test for the existence of the header:

SetEnvIf X-Real-IP ^.+$ real_ip_exists

Finally, set up an environment-based condition so the log switches between the two formats depending on the incoming request:

CustomLog /var/log/apache/myapp_access.log complete_realip env=real_ip_exists
CustomLog /var/log/apache/myapp_access.log complete env=!real_ip_exists

Conclusion

Your Apache server will now dynamically switch the IP it logs depending on whether the X-Real-IP header is present.

Note: if you use HAProxy in front, add the following configuration to your HAProxy backends:

http-request set-header X-Real-IP %[src]