Sangat Pedas

Filter Access To Tomcat based on IP behind Proxy Server


Another day lost on something that seemed so simple to implement. After having installed Tomcat 7 and Solr 4 I wanted to limit access to the interface based on IP. This was actually the reason I chose Tomcat over Jetty because with Jetty there’s no straight forward dummy proof way to do this. Don’t let the firewall image fool you, this is just an IP filter and can be circumvented by means of IP spoofing. However for me it’s enough for now, once it goes in production all access will be blocked completely.

Somehow most documentation of platforms like Tomcat are clear if you get the whole picture but if you’re a first-timer it’s a pain in the ass because of the lack of simple/working examples. S what seemed straightforward cost me another 6 hours and by posting I hope to spare you the time.

So my website is hosted with Webfaction, a great hosting company but due to the fact that it’s still shared hosting it comes with some challenges.

To implement IP filtering Tomcat offers the RemoteAddrValve class for filtering on IP and the RemoteHostValve for filtering on host name. Since I wanted to filter based on I added the following line to the file conf/server.xml:

Mind you, multiple IP’s are no longer separated by a comma but by a | character.

I placed this line right above the AccessLogValve which is by default the last valve in the server config file. When I tested it access was denied and after checking my public ip 10 times I concluded something was not right.

When analysing the access log files I found that Tomcat logged the originating IP of every request as meaning that there’s some proxy magic going on. Now I read somewhere that Tomcat 7 would by default use the X-Forwarded-For (the standard for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer) but apparently it doesn’t by default.

In order to get Tomcat to use the X-Forwarded-For is originating IP address you need to add another valve placed above the RemoteAddrValve, the RemoteHostValve and the AccessLogValve in order to enable those valves to use the IP taken from the X-Forwarded-For.

To enable logging to use the IP taken from the X-Forwarded-For you also need to add the RequestAttributesEnabled=”true” to the AccessLogValve:

Did this the trick and after adding the same attribute to the RemoteAddrValve everything worked just fine. So in order for everything to work make sure your server.xml looks like this:

I know it looks pretty simple, but the solution is always simple, unfortunately the way there can be painstaking. Good luck!