Top Description Inners Fields Constructors Methods
org.apache.catalina.filters

public Class RemoteIpFilter

extends GenericFilter
Class Inheritance
Imports
java.io.IOException, .ObjectInputStream, java.net.InetAddress, .UnknownHostException, java.util.ArrayDeque, .Collections, .Deque, .Enumeration, .HashMap, .Iterator, .LinkedList, .List, .Map, java.util.regex.Pattern, jakarta.servlet.FilterChain, .GenericFilter, .ServletException, .ServletRequest, .ServletRequestWrapper, .ServletResponse, jakarta.servlet.http.HttpServletRequest, .HttpServletRequestWrapper, .HttpServletResponse, .PushBuilder, org.apache.catalina.AccessLog, .Globals, org.apache.catalina.connector.RequestFacade, org.apache.catalina.util.RequestUtil, org.apache.juli.logging.Log, .LogFactory, org.apache.tomcat.util.buf.StringUtils, org.apache.tomcat.util.http.FastHttpDateFormat, org.apache.tomcat.util.http.parser.Host, org.apache.tomcat.util.res.StringManager

Servlet filter to integrate "X-Forwarded-For" and "X-Forwarded-Proto" HTTP headers.

Most of the design of this Servlet Filter is a port of mod_remoteip, this servlet filter 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 (e.g. "X-Forwarded-For").

Another feature of this servlet filter is to replace the apparent scheme (http/https) and server port with the scheme presented by a proxy or a load balancer via a request header (e.g. "X-Forwarded-Proto").

This servlet filter proceeds as follows:

If the incoming request.getRemoteAddr() matches the servlet filter's list of internal or trusted proxies:

Configuration parameters
XForwardedFilter property Description Equivalent mod_remoteip directive Format Default Value
remoteIpHeader Name of the Http Header read by this servlet filter that holds the list of traversed IP addresses starting from the requesting client RemoteIPHeader Compliant http header name x-forwarded-for
internalProxies Regular expression that matches the IP addresses of internal proxies. If they appear in the remoteIpHeader value, they will be trusted and will not appear in the proxiesHeader value RemoteIPInternalProxy Regular expression (in the syntax supported by java.util.regex) 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}| 100\.6[4-9]{1}\.\d{1,3}\.\d{1,3}|100\.[7-9]{1}\d{1}\.\d{1,3}\.\d{1,3}| 100\.1[0-1]{1}\d{1}\.\d{1,3}\.\d{1,3}|100\.12[0-7]{1}\.\d{1,3}\.\d{1,3}| 172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}| 172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}| 0:0:0:0:0:0:0:1|::1
By default, 10/8, 192.168/16, 169.254/16, 127/8, 100.64/10, 172.16/12, and 0:0:0:0:0:0:0:1 are allowed.
proxiesHeader Name of the http header created by this servlet filter to hold the list of proxies that have been processed in the incoming remoteIpHeader RemoteIPProxiesHeader Compliant http header name x-forwarded-by
trustedProxies Regular expression that matches the IP addresses of trusted proxies. If they appear in the remoteIpHeader value, they will be trusted and will appear in the proxiesHeader value RemoteIPTrustedProxy Regular expression (in the syntax supported by java.util.regex)  
protocolHeader Name of the http header read by this servlet filter that holds the flag that this request N/A Compliant http header name like X-Forwarded-Proto, X-Forwarded-Ssl or Front-End-Https X-Forwarded-Proto
protocolHeaderHttpsValue Value of the protocolHeader to indicate that it is an Https request N/A String like https or ON https
httpServerPort Value returned by ServletRequest#getServerPort() when the protocolHeader indicates http protocol N/A integer 80
httpsServerPort Value returned by ServletRequest#getServerPort() when the protocolHeader indicates https protocol N/A integer 443
enableLookups Should a DNS lookup be performed to provide a host name when calling ServletRequest#getRemoteHost() N/A boolean false

Regular expression vs. IP address blocks: mod_remoteip allows to use address blocks (e.g. 192.168/16) to configure RemoteIPInternalProxy and RemoteIPTrustedProxy ; as the JVM doesn't have a library similar to apr_ipsubnet_test, we rely on regular expressions.


Sample with internal proxies

XForwardedFilter configuration:

<filter> <filter-name>RemoteIpFilter</filter-name> <filter-class>org.apache.catalina.filters.RemoteIpFilter</filter-class> <init-param> <param-name>internalProxies</param-name> <param-value>192\.168\.0\.10|192\.168\.0\.11</param-value> </init-param> <init-param> <param-name>remoteIpHeader</param-name> <param-value>x-forwarded-for</param-value> </init-param> <init-param> <param-name>remoteIpProxiesHeader</param-name> <param-value>x-forwarded-by</param-value> </init-param> <init-param> <param-name>protocolHeader</param-name> <param-value>x-forwarded-proto</param-value> </init-param> </filter> <filter-mapping> <filter-name>RemoteIpFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
Request Values
property Value Before RemoteIpFilter Value After RemoteIpFilter
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
request.header['x-forwarded-proto'] https https
request.scheme http https
request.secure false true
request.serverPort 80 443
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 trusted proxies

RemoteIpFilter configuration:

<filter> <filter-name>RemoteIpFilter</filter-name> <filter-class>org.apache.catalina.filters.RemoteIpFilter</filter-class> <init-param> <param-name>internalProxies</param-name> <param-value>192\.168\.0\.10|192\.168\.0\.11</param-value> </init-param> <init-param> <param-name>remoteIpHeader</param-name> <param-value>x-forwarded-for</param-value> </init-param> <init-param> <param-name>remoteIpProxiesHeader</param-name> <param-value>x-forwarded-by</param-value> </init-param> <init-param> <param-name>trustedProxies</param-name> <param-value>proxy1|proxy2</param-value> </init-param> </filter> <filter-mapping> <filter-name>RemoteIpFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
Request Values
property Value Before RemoteIpFilter Value After RemoteIpFilter
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

RemoteIpFilter configuration:

<filter> <filter-name>RemoteIpFilter</filter-name> <filter-class>org.apache.catalina.filters.RemoteIpFilter</filter-class> <init-param> <param-name>internalProxies</param-name> <param-value>192\.168\.0\.10|192\.168\.0\.11</param-value> </init-param> <init-param> <param-name>remoteIpHeader</param-name> <param-value>x-forwarded-for</param-value> </init-param> <init-param> <param-name>remoteIpProxiesHeader</param-name> <param-value>x-forwarded-by</param-value> </init-param> <init-param> <param-name>trustedProxies</param-name> <param-value>proxy1|proxy2</param-value> </init-param> </filter> <filter-mapping> <filter-name>RemoteIpFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
Request Values
property Value Before RemoteIpFilter Value After RemoteIpFilter
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 an untrusted proxy

RemoteIpFilter configuration:

<filter> <filter-name>RemoteIpFilter</filter-name> <filter-class>org.apache.catalina.filters.RemoteIpFilter</filter-class> <init-param> <param-name>internalProxies</param-name> <param-value>192\.168\.0\.10|192\.168\.0\.11</param-value> </init-param> <init-param> <param-name>remoteIpHeader</param-name> <param-value>x-forwarded-for</param-value> </init-param> <init-param> <param-name>remoteIpProxiesHeader</param-name> <param-value>x-forwarded-by</param-value> </init-param> <init-param> <param-name>trustedProxies</param-name> <param-value>proxy1|proxy2</param-value> </init-param> </filter> <filter-mapping> <filter-name>RemoteIpFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
Request Values
property Value Before RemoteIpFilter Value After RemoteIpFilter
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 cannot trust that untrusted-proxy is the actual remote ip. request.remoteAddr is untrusted-proxy that is an IP verified by proxy1.


Nested and Inner Type Summary

Modifier and TypeClass and Description
public static class

Field Summary

Modifier and TypeField and Description
protected static final String
protected static final String
private boolean
private boolean
private static final Pattern
commaSeparatedValuesPattern

Pattern for a comma delimited string that support whitespace characters

protected static final String
private boolean
protected static final String
private String
protected static final String
protected static final String
private int
private int
protected static final String
private Pattern
private transient Log
protected static final String
private String
protected static final String
protected static final String
private String
private String
protected static final String
private String
protected static final String
private String
private boolean
private static final long
protected static final StringManager
protected static final String
private Pattern

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
protected static String[]

Returns:

array of patterns (non null)
commaDelimitedListToStringArray
(String
The string to split
commaDelimitedStrings
)

Convert a given comma delimited list of regular expressions into an array of String

public void
public void
doFilter(ServletRequest
The request to process
request
,
ServletResponse
The response associated with the request
response
,
FilterChain
Provides access to the next filter in the chain for this filter to pass the request and response to for further processing
chain
)

Implements jakarta.servlet.Filter.doFilter.

Wrap the incoming request in a XForwardedRequest if the http header x-forwarded-for is not empty.

public boolean
public int
public Pattern
public String
public String
public String
public String
public String
public boolean

Returns:

true if the attributes will be logged, otherwise false
getRequestAttributesEnabled
()

public Pattern
public void
init()

Overrides jakarta.servlet.GenericFilter.init.

Convenience method for sub-classes to save them having to call super.init(config).

public boolean
public boolean
private boolean
protected static String

Returns:

concatenated string
listToCommaDelimitedString
(List<String>
List of strings
stringList
)
Deprecated Unused. Will be removed in Tomcat 11 onwards

Convert a list of strings in a comma delimited string.

private void
public void
setChangeLocalName(boolean
The new flag value
changeLocalName
)

If true, the return values for both ServletRequest#getLocalName() and ServletRequest#getServerName() will be modified by this Filter rather than just ServletRequest#getServerName().

public void
setChangeLocalPort(boolean
The new flag value
changeLocalPort
)

If true, the return values for both ServletRequest#getLocalPort() and ServletRequest#getServerPort() will be modified by this Filter rather than just ServletRequest#getServerPort().

public void
setEnableLookups(boolean enableLookups)

public void
setHostHeader(String
The header name
hostHeader
)

Header that holds the incoming host, usually named X-Forwarded-Host.

public void
setHttpServerPort(int
The server port to use
httpServerPort
)

Server Port value if the protocolHeader indicates HTTP (i.e. protocolHeader is not null and has a value different of protocolHeaderHttpsValue).

public void
setHttpsServerPort(int
The server port to use
httpsServerPort
)

Server Port value if the protocolHeader indicates HTTPS

Default value : 443

public void
setInternalProxies(String
The regexp
internalProxies
)

Regular expression that defines the internal proxies.

public void
setPortHeader(String
The header name
portHeader
)

Header that holds the incoming port, usually named X-Forwarded-Port.

private void
setPorts(RemoteIpFilter.XForwardedRequest xrequest, int defaultPort)

public void
setProtocolHeader(String
The header name
protocolHeader
)

Header that holds the incoming protocol, usually named X-Forwarded-Proto.

public void
setProtocolHeaderHttpsValue(String
The header value
protocolHeaderHttpsValue
)

Case insensitive value of the protocol header to indicate that the incoming http request uses HTTPS.

public void
setProxiesHeader(String
The header name
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.

public void
setRemoteIpHeader(String
The header name
remoteIpHeader
)

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

public void
setRequestAttributesEnabled(boolean
true causes the attributes to be set, false disables the setting of the attributes.
requestAttributesEnabled
)

Should this filter set request attributes for IP address, Hostname, protocol and port used for the request?

public void
setTrustedProxies(String
The trusted proxies regexp
trustedProxies
)

Regular expression defining proxies that are trusted when they appear in the remoteIpHeader header.

Inherited from jakarta.servlet.GenericFilter:
getFilterConfiggetFilterNamegetInitParametergetInitParameterNamesgetServletContextinit