org.apache.catalina.connector
Class RemoteIpValve

java.lang.Object
  extended by org.apache.catalina.valves.ValveBase
      extended by org.apache.catalina.connector.RemoteIpValve
All Implemented Interfaces:
MBeanRegistration, Contained, Valve

public class RemoteIpValve
extends ValveBase

Tomcat port of mod_remoteip, this valve replaces the apparent client remote IP address and hostname for the request with the IP address list presented by a proxy or a load balancer via a request headers.

This valve proceeds as follows:

Configuration parameters:

RemoteIpValve property Equivalent mod_remoteip directive Format Default Value
remoteIPHeader RemoteIPHeader Compliant http header string x-forwarded-for
internalProxies RemoteIPInternalProxy Comma delimited list of regular expressions (in the syntax supported by the Pattern library) 10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3}, 169\.254\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3}
By default, 10/8, 192.168/16, 169.254/16 and 127/8 are allowed ; 172.16/12 has not been enabled by default because it is complex to describe with regular expressions
proxiesHeader RemoteIPProxiesHeader Compliant http header String x-forwarded-by
trustedProxies RemoteIPTrustedProxy Comma delimited list of regular expressions (in the syntax supported by the Pattern library)  

This Valve may be attached to any Container, depending on the granularity of the filtering you wish to perform.

Regular expression vs. IP address blocks: mod_remoteip allows to use address blocks (e.g. 192.168/16) to configure RemoteIPInternalProxy and RemoteIPTrustedProxy ; as Tomcat doesn't have a library similar to apr_ipsubnet_test, RemoteIpValve uses regular expression to configure internalProxies and trustedProxies in the same fashion as RequestFilterValve does.

Package org.apache.catalina.connector vs. org.apache.catalina.valves: This valve is temporarily located in org.apache.catalina.connector package instead of org.apache.catalina.valves because it uses protected visibility of Request.remoteAddr and Request.remoteHost. This valve could move to org.apache.catalina.valves if Request.setRemoteAddr(String) and Request.setRemoteHost(String) were modified to no longer be no-op but actually set the underlying property.


Sample with trusted proxies

RemoteIpValve configuration:

 <Valve 
   className="org.apache.catalina.connector.RemoteIpValve"
   allowedInternalProxies="192\.168\.0\.10, 192\.168\.0\.11"
   remoteIPHeader="x-forwarded-for"
   remoteIPProxiesHeader="x-forwarded-by"
   trustedProxies="proxy1, proxy2"
   />

Request values:

property Value Before RemoteIpValve Value After RemoteIpValve
request.remoteAddr 192.168.0.10 140.211.11.130
request.header['x-forwarded-for'] 140.211.11.130, proxy1, proxy2 null
request.header['x-forwarded-by'] null proxy1, proxy2
Note : proxy1 and proxy2 are both trusted proxies that come in x-forwarded-for header, they both are migrated in x-forwarded-by header. x-forwarded-by is null because all the proxies are trusted or internal.


Sample with internal and trusted proxies

RemoteIpValve configuration:

 <Valve 
   className="org.apache.catalina.connector.RemoteIpValve"
   allowedInternalProxies="192\.168\.0\.10, 192\.168\.0\.11"
   remoteIPHeader="x-forwarded-for"
   remoteIPProxiesHeader="x-forwarded-by"
   trustedProxies="proxy1, proxy2"
   />

Request values:

property Value Before RemoteIpValve Value After RemoteIpValve
request.remoteAddr 192.168.0.10 140.211.11.130
request.header['x-forwarded-for'] 140.211.11.130, proxy1, proxy2, 192.168.0.10 null
request.header['x-forwarded-by'] null proxy1, proxy2
Note : proxy1 and proxy2 are both trusted proxies that come in x-forwarded-for header, they both are migrated in x-forwarded-by header. As 192.168.0.10 is an internal proxy, it does not appear in x-forwarded-by. x-forwarded-by is null because all the proxies are trusted or internal.


Sample with internal proxies

RemoteIpValve configuration:

 <Valve 
   className="org.apache.catalina.connector.RemoteIpValve"
   allowedInternalProxies="192\.168\.0\.10, 192\.168\.0\.11"
   remoteIPHeader="x-forwarded-for"
   remoteIPProxiesHeader="x-forwarded-by"
   />

Request values:

property Value Before RemoteIpValve Value After RemoteIpValve
request.remoteAddr 192.168.0.10 140.211.11.130
request.header['x-forwarded-for'] 140.211.11.130, 192.168.0.10 null
request.header['x-forwarded-by'] null null
Note : x-forwarded-by header is null because only internal proxies as been traversed by the request. x-forwarded-by is null because all the proxies are trusted or internal.


Sample with an untrusted proxy

RemoteIpValve configuration:

 <Valve 
   className="org.apache.catalina.connector.RemoteIpValve"
   allowedInternalProxies="192\.168\.0\.10, 192\.168\.0\.11"
   remoteIPHeader="x-forwarded-for"
   remoteIPProxiesHeader="x-forwarded-by"
   trustedProxies="proxy1, proxy2"
   />

Request values:

property Value Before RemoteIpValve Value After RemoteIpValve
request.remoteAddr 192.168.0.10 untrusted-proxy
request.header['x-forwarded-for'] 140.211.11.130, untrusted-proxy, proxy1 140.211.11.130
request.header['x-forwarded-by'] null proxy1
Note : x-forwarded-by holds the trusted proxy proxy1. x-forwarded-by holds 140.211.11.130 because untrusted-proxy is not trusted and thus, we can not trust that untrusted-proxy is the actual remote ip. request.remoteAddr is untrusted-proxy that is an IP verified by proxy1.


TODO : add "remoteIpValve.syntax" NLSString.


Field Summary
private static Pattern commaSeparatedValuesPattern
          Pattern for a comma delimited string that support whitespace characters
private static String info
          The descriptive information related to this implementation.
private  Pattern[] internalProxies
           
private static Log log
          Logger
private  String proxiesHeader
           
private  String remoteIPHeader
           
protected static StringManager sm
          The StringManager for this package.
private  Pattern[] trustedProxies
           
 
Fields inherited from class org.apache.catalina.valves.ValveBase
container, containerLog, controller, domain, mserver, next, oname
 
Constructor Summary
RemoteIpValve()
           
 
Method Summary
protected static Pattern[] commaDelimitedListToPatternArray(String commaDelimitedPatterns)
          Convert a given comma delimited list of regular expressions into an array of compiled Pattern
protected static String[] commaDelimitedListToStringArray(String commaDelimitedStrings)
          Convert a given comma delimited list of regular expressions into an array of String
 String getInfo()
          Return descriptive information about this Valve implementation.
 void invoke(Request request, Response response)
          
protected static String listToCommaDelimitedString(List<String> stringList)
          Convert an array of strings in a comma delimited string
protected static boolean matchesOne(String str, Pattern... patterns)
          Return true if the given str matches at least one of the given patterns.
 void setInternalProxies(String commaAllowedInternalProxies)
           Comma delimited list of internal proxies.
 void setProxiesHeader(String proxiesHeader)
           The proxiesHeader directive specifies a header into which mod_remoteip will collect a list of all of the intermediate client IP addresses trusted to resolve the actual remote IP.
 void setRemoteIPHeader(String remoteIPHeader)
           Name of the http header from which the remote ip is extracted.
 void setTrustedProxies(String commaDelimitedTrustedProxies)
           Comma delimited list of proxies that are trusted when they appear in the remoteIPHeader header.
 
Methods inherited from class org.apache.catalina.valves.ValveBase
backgroundProcess, createObjectName, event, getContainer, getContainerName, getController, getDomain, getNext, getObjectName, getParentName, postDeregister, postRegister, preDeregister, preRegister, setContainer, setController, setNext, setObjectName, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

log

private static Log log
Logger


commaSeparatedValuesPattern

private static final Pattern commaSeparatedValuesPattern
Pattern for a comma delimited string that support whitespace characters


info

private static final String info
The descriptive information related to this implementation.

See Also:
Constant Field Values

sm

protected static StringManager sm
The StringManager for this package.


internalProxies

private Pattern[] internalProxies
See Also:
setInternalProxies(String)

remoteIPHeader

private String remoteIPHeader
See Also:
setRemoteIPHeader(String)

proxiesHeader

private String proxiesHeader
See Also:
setProxiesHeader(String)

trustedProxies

private Pattern[] trustedProxies
See Also:
setTrustedProxies(String)
Constructor Detail

RemoteIpValve

public RemoteIpValve()
Method Detail

commaDelimitedListToPatternArray

protected static Pattern[] commaDelimitedListToPatternArray(String commaDelimitedPatterns)
Convert a given comma delimited list of regular expressions into an array of compiled Pattern


commaDelimitedListToStringArray

protected static String[] commaDelimitedListToStringArray(String commaDelimitedStrings)
Convert a given comma delimited list of regular expressions into an array of String


listToCommaDelimitedString

protected static String listToCommaDelimitedString(List<String> stringList)
Convert an array of strings in a comma delimited string


matchesOne

protected static boolean matchesOne(String str,
                                    Pattern... patterns)
Return true if the given str matches at least one of the given patterns.


getInfo

public String getInfo()
Return descriptive information about this Valve implementation.

Specified by:
getInfo in interface Valve
Overrides:
getInfo in class ValveBase

invoke

public void invoke(Request request,
                   Response response)
            throws IOException,
                   ServletException

Specified by:
invoke in interface Valve
Specified by:
invoke in class ValveBase
Throws:
IOException
ServletException

setInternalProxies

public void setInternalProxies(String commaAllowedInternalProxies)

Comma delimited list of internal proxies. Can be expressed with regular expressions.

Default value : 10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3}


setRemoteIPHeader

public void setRemoteIPHeader(String remoteIPHeader)

Name of the http header from which the remote ip is extracted.

The value of this header can be comma delimited.

Default value : X-Forwarded-For

Parameters:
remoteIPHeader -

setProxiesHeader

public void setProxiesHeader(String proxiesHeader)

The proxiesHeader directive specifies a header into which mod_remoteip will collect a list of all of the intermediate client IP addresses trusted to resolve the actual remote IP. Note that intermediate RemoteIPTrustedProxy addresses are recorded in this header, while any intermediate RemoteIPInternalProxy addresses are discarded.

Name of the http header that holds the list of trusted proxies that has been traversed by the http request.

The value of this header can be comma delimited.

Default value : X-Forwarded-By


setTrustedProxies

public void setTrustedProxies(String commaDelimitedTrustedProxies)

Comma delimited list of proxies that are trusted when they appear in the remoteIPHeader header. Can be expressed as a regular expression.

Default value : empty list, no external proxy is trusted.