9 posts categorized "x-forwarded-for"

01/28/2010

Tomcat 6: First Impression of the New Remote IP Valve

First introduced for production use in the recently released 6.0.24 version, the Remote IP Valve provides tomcat with built-in support for pulling the client IP from the X-Forwarded-For header field and making that IP address available to applications.  Prior to this, if you wanted to grab the client IP address from the X-Forwarded-For header, you needed to hard-code it into your applications yourself.  If you weren't too careful, you could wind up with cases where you were getting the IP address only *most* of the time.

Setting up this valve is very straightforward.  Edit your server.xml file and insert the following lines, (which can reside within the context, host, or engine levels):

 <Valve className="org.apache.catalina.valves.RemoteIpValve"
   />

If you place the valve higher than the Access Log Valve within server.xml, you won't need to utilize a custom log file pattern to log the client ip address but I did notice some unexpected behavior with access logs when combining the Remote IP Valve with the Remote Address filter. I don't know if it is necessarily a bug, a configuration error, or if it is a lack of understanding of the behavior of the Remote Address filter on my part. In my test container, which is a non-custom, straight-from-a-mirror binary download running on Snow Leopard, I modified server.xml to include the following:

        <Valve className="org.apache.catalina.valves.RemoteIpValve"
          />

        <Valve className="org.apache.catalina.valves.RemoteAddrValve" 
          allow="10.11.12.13" deny="127.0.0.1"/>

        <Valve className="org.apache.catalina.valves.AccessLogValve" 
          directory="logs"  
          prefix="localhost_access_log." suffix=".txt" 
          pattern="combined" resolveHosts="false"/>

      </Host>
    </Engine>
  </Service>

My test script is a basic HTTP Get written in Groovy, which I'm running from within groovyConsole so that I can enable and disable the custom request header at will:

def url = new URL("http://localhost:8080/docs/introduction.html")
def connection = url.openConnection()
  connection.setRequestProperty("X-Forwarded-For","10.11.12.13")
  connection.setRequestProperty("User-Agent","benevolent-bot/blog.techstacks.com")
 
if(connection.responseCode == 200){
 println "Connection successful"
 }
else{
 println "Ouchy! Error! ${connection.responseCode}"
 }

When tailing the tomcat access log and executing the test with the X-Forwarded-For property enabled, everything works as expected. I see my successful request in the logs using the ip address 10.11.12.13. However, when disabling this property and re-sending the request along, I do see the 403 status code returned from tomcat, which is expected, but nothing gets logged in the access log, which was not expected. I was expecting to see a request logged in the access log from ip address 127.0.0.1 for /introduction.html with a 403 status code. Logging request attempts from forbidden remote IP's seems like it should be useful.

Logging issues aside, (which, again could be my fault), the new Remote IP Valve is a useful addition to apache tomcat and I encourage everyone to start making use of it. Even if you don't have a reverse proxy device sitting in front of your tomcat servers, chances are very good that your customers do go through one to get to you and the Remote IP Valve will give you the actual customer IP address, without the need for custom coding within your servlets.

12/28/2009

How To Log Client IP AND X-Forwarded-For IP in Apache

When you utilize a device like a BigIP LTM to load-balance your web servers, a typical configuration masks the client IP address.  The BigIP essentially proxies requests on behalf of the browser, so the only thing your web server sees is the IP address of the BigIP itself.  The BigIP utilizes an industry-standard (but not HTTP standard) mechanism for storing the customer IP address into an HTTP Request Header called the X-Forwarded-For header.  Typically, you configure your Apache servers to log the value from the X-Forwarded-For header instead of logging the client IP.  

This all works great except when you access the web server directly, bypassing the BigIP.  Since the BigIP (or other proxy) is inserting the X-Forwarded-For header and your browser is not, nothing gets logged in the Apache access logs so you have no simple way to determine which internal user or monitor just took your site down with that vulnerability scan.  You can still figure it out based on user-agent and communication with your peers but we sysadmins are like the police on TV—we like to have all the damning evidence at hand before "interviewing" the perp.

The following HOWTO details a mechanism for logging both, depending upon whether an X-Forwarded-For value exists or not.  HOWTO: Log Client IP AND X-Forwarded-For IP in Apache. It also includes a basic groovy script for validating.

12/23/2009

New IIS7 X-Forwarded-For Module From F5

The goodies keep coming this week!  F5 released an X-Forwarded-For module for IIS7 users, which is meant to replace the ISAPI filter for IIS7 sites, (and only for IIS7 sites).  Apparently, Microsoft wants folks to utilize IIS Modules instead of ISAPI filters, so F5 developed this one.  Binaries and Source are available for download but a DevCentral account might be required.