Preserving client IP w/ apache reverse proxy

We recently had a scenario where an apache reverse proxy needed to be deployed in front of a pair of tomcat servers. Due to security concerns, this reverse proxy was hosting mod_security and acting as a web application firewall (WAF)

However, a critical requirement was that the tomcat applications would be able to see the original IP address of the client. This presented a problem because unlike squid, apache has no configurable option to act as a fully transparent proxy. In other words, once traffic was redirected through the apache reverse proxy, the traffic forwarded to the tomcat server was forwarded with it’s source IP address changed to the proxy, effectively hiding the public IP the client used to connect to the site.

The first solution that sprang to mind was the “X-Forwarded-For” headers, which is an HTTP header inserted into the original HTTP GET request whose value is equal to the client’s public IP. Turns out apache reverse proxy inserts this header by default, and even so the tomcat application could not extract the client’s IP. We somehow needed to instruct the tomcat server itself to provide the application with the correct client IP.

The solution that worked in my case was the RemoteIP tomcat valve. Official documentation lives here:

It’s quite simple to configure in that all that needs to be done is to modify tomcat server.xml to recognise original client IP rather than the proxy IP by adding the following to server.xml:

<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="127\.0\.0\.1" />

make sure to change to the address of the apache reverse proxy.

The application could now recognise the original client IP.


PS as per the tomcat documentation, the apache equivalent of the above method is using the mod_remoteip


Monitoring Tomcat via JMX–Lessons Learned: Part 2

In my previous post I mentioned that the check_jmx plugin I’ve used for monitoring JMX does not output perfdata data, which is useful for programs such as Centreon and Nagios which use this data to graph the output of the plugin.

The developers have made an excellent job with this plugin, and I hope they take the below script and incorporate into their official script Smile

I’ve written an “add-on” script which basically wraps around the official script and outputs the data in a perfdata friendly way, while keeping the nagios plugin OK/WARNING/CRITICAL states. The script isn’t perfect in the sense it could do with some input validation and a more helpful help, but it does work Smile

Below are the contents of the script “check_jmx_perfdata”, and assumes the plugin is located at /usr/local/nagios/libexec/check_jmx:
# IMPORTANT, do not forget the ” ” when using this command as per example below
# example usage:
# ./check_jmx_perfdata “-U service:jmx:rmi:///jndi/rmi://localhost:9003/jmxrmi –O #Catalina:type=ThreadPool,name=http-8080 -A currentThreadCount”

# grab the original output from the check_jmx plugin

plugin_output=$(/usr/local/nagios/libexec/check_jmx $1)

# set the variables, where metric = attribute being monitored

# value = numeric value of the attribute


metric=$(echo $plugin_output | cut -d ” ” -f 4)
value=$(echo $plugin_output | cut -d ” ” -f 6)
result=$(echo $plugin_output | cut -d ” ” -f 2)

# output the result with the added perfdata output
echo “$plugin_output | $metric=$value”

case “$result” in


exit 0
; ;


exit 1
;  ;


exit 2
; ;


exit 3


Instead of calling the check_jmx script from nagios, you will call the above script, using the exact same syntax but using the inverted commas. So for exmaple if you used:

check_jmx -U service:jmx:rmi:///jndi/rmi://localhost:9003/jmxrmi -O Catalina:type=Manager,path=/servlets-examples,host=localhost -A activeSessions

You’d now use:

check_jmx_perfdata “-U service:jmx:rmi:///jndi/rmi://localhost:9003/jmxrmi -O Catalina:type=Manager,path=/servlets-examples,host=localhost -A activeSessions”

Enjoy! Smile