Class RemoteIpFilter
- All Implemented Interfaces:
Filter, FilterConfig, Serializable
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:
- Loop on the comma-delimited list of IPs and hostnames passed by the preceding load balancer or proxy in the given
request's Http header named
$remoteIpHeader(default valuex-forwarded-for). Values are processed in right-to-left order. - For each ip/host of the list:
- if it matches the internal proxies list, the ip/host is swallowed
- if it matches the trusted proxies list, the ip/host is added to the created proxies header
- otherwise, the ip/host is declared to be the remote ip and looping is stopped.
- If the request http header named
$protocolHeader(default valueX-Forwarded-Proto) consists only of forwards that matchprotocolHeaderHttpsValueconfiguration parameter (defaulthttps) thenrequest.isSecure = true,request.scheme = httpsandrequest.serverPort = 443. Note that 443 can be overwritten with the$httpsServerPortconfiguration parameter. - Mark the request with the attribute
Globals.REQUEST_FORWARDED_ATTRIBUTEand valueBoolean.TRUEto indicate that this request has been forwarded by one or more proxies.
| RemoteIpFilter 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 | Either a comma separated list of CIDR blocks or a single 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 | Comma separated list of CIDR blocks or a single regular expression Pattern |
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,100.64.0.0/10,127.0.0.0/8,::1/128,fe80::/10,fc00::/7 |
| 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 | Either a comma separated list of CIDR blocks or a single regular expression that matches the IP addresses of
internal proxies. If they appear in the remoteIpHeader value, they will be trusted and will appear in
the proxiesHeader value |
RemoteIPTrustedProxy | Comma separated list of CIDR blocks or a single regular expression Pattern |
|
| 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 a 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 |
Sample with internal 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/31</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>
| 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 |
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/31</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>
| 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/31</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>
| 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/31</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>
| 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.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classWrapper forHttpServletRequestthat allows modification of headers, remote address, scheme, and other properties used by the RemoteIpFilter. -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected static final StringParameter name for the change local name configuration.protected static final StringParameter name for the change local port configuration.protected static final StringParameter name for the enable lookups configuration.protected static final StringParameter name for the host header configuration.protected static final StringParameter name for the HTTP server port configuration.protected static final StringParameter name for the HTTPS server port configuration.protected static final StringParameter name for the internal proxies configuration.protected static final StringParameter name for the port header configuration.protected static final StringParameter name for the protocol header HTTPS value configuration.protected static final StringParameter name for the protocol header configuration.protected static final StringParameter name for the proxies header configuration.protected static final StringParameter name for the remote IP header configuration.protected static final StringManagerString manager for internationalized messages.protected static final StringParameter name for the trusted proxies configuration. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoiddoFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) Process the incoming request, updating the remote address, scheme, and headers based on the configured forwarded headers when the request comes from a trusted proxy.voiddoFilter(ServletRequest request, ServletResponse response, FilterChain chain) Wrap the incomingrequestin aRemoteIpFilter.XForwardedRequestif the http headerx-forwarded-foris not empty.booleanReturns whether DNS lookups are enabled for remote address resolution.intReturns the configured HTTPS server port.Deprecated.Deprecated.This method will be renamed togetInternalProxies()as of Tomcat 12Returns the configured port header name.Returns the configured protocol header name.Returns the configured HTTPS value for the protocol header.Returns the configured proxies header name.Returns the configured remote IP header name.booleanReturns whether request attributes for access logging are enabled.Deprecated.The implementation of this method will be replaced with the implementation ofgetTrustedProxiesAsString()in Tomcat 12 onwards with the return type changing toStringDeprecated.This method will be renamed togetInternalProxies()as of Tomcat 12voidinit()Convenience method for subclasses to save them having to callsuper.init(config).booleanReturns whether the local name is changed by this filter.booleanReturns whether the local port is changed by this filter.voidsetChangeLocalName(boolean changeLocalName) Iftrue, the return values for bothServletRequest.getLocalName()andServletRequest.getServerName()will be modified by this Filter rather than justServletRequest.getServerName().voidsetChangeLocalPort(boolean changeLocalPort) Iftrue, the return values for bothServletRequest.getLocalPort()andServletRequest.getServerPort()will be modified by this Filter rather than justServletRequest.getServerPort().voidsetEnableLookups(boolean enableLookups) Set whether DNS lookups are enabled.voidsetHostHeader(String hostHeader) Header that holds the incoming host, usually namedX-Forwarded-Host.voidsetHttpServerPort(int httpServerPort) Server Port value if theprotocolHeaderindicates HTTP (i.e.voidsetHttpsServerPort(int httpsServerPort) Server Port value if theprotocolHeaderindicates HTTPSvoidsetInternalProxies(String internalProxies) Set the internal proxies either as a comma separated list of CIDR blocks or a single regular expression.voidsetPortHeader(String portHeader) Header that holds the incoming port, usually namedX-Forwarded-Port.voidsetProtocolHeader(String protocolHeader) Header that holds the incoming protocol, usually namedX-Forwarded-Proto.voidsetProtocolHeaderHttpsValue(String protocolHeaderHttpsValue) Case-insensitive value of the protocol header to indicate that the incoming http request uses HTTPS.voidsetProxiesHeader(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.voidsetRemoteIpHeader(String remoteIpHeader) Name of the http header from which the remote ip is extracted.voidsetRequestAttributesEnabled(boolean requestAttributesEnabled) Should this filter set request attributes for IP address, Hostname, protocol and port used for the request?voidsetTrustedProxies(String trustedProxies) Set the trusted proxies either as a comma separated list of CIDR blocks or a single regular expression.Methods inherited from class GenericFilter
getFilterConfig, getFilterName, getInitParameter, getInitParameterNames, getServletContext, init
-
Field Details
-
HTTP_SERVER_PORT_PARAMETER
Parameter name for the HTTP server port configuration.- See Also:
-
HTTPS_SERVER_PORT_PARAMETER
Parameter name for the HTTPS server port configuration.- See Also:
-
INTERNAL_PROXIES_PARAMETER
Parameter name for the internal proxies configuration.- See Also:
-
sm
String manager for internationalized messages. -
PROTOCOL_HEADER_PARAMETER
Parameter name for the protocol header configuration.- See Also:
-
PROTOCOL_HEADER_HTTPS_VALUE_PARAMETER
Parameter name for the protocol header HTTPS value configuration.- See Also:
-
HOST_HEADER_PARAMETER
Parameter name for the host header configuration.- See Also:
-
PORT_HEADER_PARAMETER
Parameter name for the port header configuration.- See Also:
-
CHANGE_LOCAL_NAME_PARAMETER
Parameter name for the change local name configuration.- See Also:
-
CHANGE_LOCAL_PORT_PARAMETER
Parameter name for the change local port configuration.- See Also:
-
PROXIES_HEADER_PARAMETER
Parameter name for the proxies header configuration.- See Also:
-
REMOTE_IP_HEADER_PARAMETER
Parameter name for the remote IP header configuration.- See Also:
-
TRUSTED_PROXIES_PARAMETER
Parameter name for the trusted proxies configuration.- See Also:
-
ENABLE_LOOKUPS_PARAMETER
Parameter name for the enable lookups configuration.- See Also:
-
-
Constructor Details
-
RemoteIpFilter
public RemoteIpFilter()Default constructor.
-
-
Method Details
-
doFilter
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException Process the incoming request, updating the remote address, scheme, and headers based on the configured forwarded headers when the request comes from a trusted proxy.- Parameters:
request- The servlet request to be processedresponse- The servlet response to be createdchain- The filter chain- Throws:
IOException- if an input/output error occursServletException- if a servlet error occurs
-
doFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException Wrap the incomingrequestin aRemoteIpFilter.XForwardedRequestif the http headerx-forwarded-foris not empty. ThedoFiltermethod of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed in to this method allows the Filter to pass on the request and response to the next entity in the chain.A typical implementation of this method would follow the following pattern:-
1. Examine the request
2. Optionally wrap the request object with a custom implementation to filter content or headers for input filtering
3. Optionally wrap the response object with a custom implementation to filter content or headers for output filtering
4. a) Either invoke the next entity in the chain using the FilterChain object (chain.doFilter()),
4. b) or not pass on the request/response pair to the next entity in the filter chain to block the request processing
5. Directly set headers on the response after invocation of the next entity in the filter chain.- Parameters:
request- The request to processresponse- The response associated with the requestchain- Provides access to the next filter in the chain for this filter to pass the request and response to for further processing- Throws:
IOException- if an I/O error occurs during this filter's processing of the requestServletException- if the processing fails for any other reason
-
isChangeLocalName
public boolean isChangeLocalName()Returns whether the local name is changed by this filter.- Returns:
- true if the local name is changed
-
isChangeLocalPort
public boolean isChangeLocalPort()Returns whether the local port is changed by this filter.- Returns:
- true if the local port is changed
-
getHttpsServerPort
public int getHttpsServerPort()Returns the configured HTTPS server port.- Returns:
- the HTTPS server port
-
getInternalProxies
Deprecated.The implementation of this method will be replaced with the implementation ofgetInternalProxiesAsString()in Tomcat 12 onwards with the return type changing toStringObtain the currently configured regular expression Pattern for internal proxies.- Returns:
- The currently configured regular expression Pattern for internal proxies
-
getInternalProxiesAsString
Deprecated.This method will be renamed togetInternalProxies()as of Tomcat 12Obtain the currently configured internal proxies.- Returns:
- The currently configured internal proxies.
-
getProtocolHeader
Returns the configured protocol header name.- Returns:
- the protocol header name
-
getPortHeader
Returns the configured port header name.- Returns:
- the port header name
-
getProtocolHeaderHttpsValue
Returns the configured HTTPS value for the protocol header.- Returns:
- the protocol header HTTPS value
-
getProxiesHeader
Returns the configured proxies header name.- Returns:
- the proxies header name
-
getRemoteIpHeader
Returns the configured remote IP header name.- Returns:
- the remote IP header name
-
getRequestAttributesEnabled
public boolean getRequestAttributesEnabled()Returns whether request attributes for access logging are enabled.- Returns:
trueif the attributes will be logged, otherwisefalse- See Also:
-
getTrustedProxies
Deprecated.The implementation of this method will be replaced with the implementation ofgetTrustedProxiesAsString()in Tomcat 12 onwards with the return type changing toStringObtain the currently configured regular expression Pattern for trusted proxies.- Returns:
- The currently configured regular expression Pattern for trusted proxies
-
getTrustedProxiesAsString
Deprecated.This method will be renamed togetInternalProxies()as of Tomcat 12Obtain the currently configured trusted proxies.- Returns:
- The currently configured trusted proxies.
-
getEnableLookups
public boolean getEnableLookups()Returns whether DNS lookups are enabled for remote address resolution.- Returns:
- true if DNS lookups are enabled
-
init
Description copied from class:jakarta.servlet.GenericFilterConvenience method for subclasses to save them having to callsuper.init(config). This is a NO-OP by default.- Overrides:
initin classGenericFilter- Throws:
ServletException- If an exception occurs that interrupts the Filter's normal operation
-
setChangeLocalName
public void setChangeLocalName(boolean changeLocalName) If
true, the return values for bothServletRequest.getLocalName()andServletRequest.getServerName()will be modified by this Filter rather than justServletRequest.getServerName().Default value :
false- Parameters:
changeLocalName- The new flag value
-
setChangeLocalPort
public void setChangeLocalPort(boolean changeLocalPort) If
true, the return values for bothServletRequest.getLocalPort()andServletRequest.getServerPort()will be modified by this Filter rather than justServletRequest.getServerPort().Default value :
false- Parameters:
changeLocalPort- The new flag value
-
setHttpServerPort
public void setHttpServerPort(int httpServerPort) Server Port value if the
protocolHeaderindicates HTTP (i.e.protocolHeaderis not null and has a value different ofprotocolHeaderHttpsValue).Default value : 80
- Parameters:
httpServerPort- The server port to use
-
setHttpsServerPort
public void setHttpsServerPort(int httpsServerPort) Server Port value if the
protocolHeaderindicates HTTPSDefault value : 443
- Parameters:
httpsServerPort- The server port to use
-
setInternalProxies
Set the internal proxies either as a comma separated list of CIDR blocks or a single regular expression.- Parameters:
internalProxies- The new internal proxies
-
setHostHeader
Header that holds the incoming host, usually named
X-Forwarded-Host.Default value :
null- Parameters:
hostHeader- The header name
-
setPortHeader
Header that holds the incoming port, usually named
X-Forwarded-Port. Ifnull,httpServerPortorhttpsServerPortwill be used.Default value :
null- Parameters:
portHeader- The header name
-
setProtocolHeader
Header that holds the incoming protocol, usually named
X-Forwarded-Proto. Ifnull, request.scheme and request.secure will not be modified.Default value :
X-Forwarded-Proto- Parameters:
protocolHeader- The header name
-
setProtocolHeaderHttpsValue
Case-insensitive value of the protocol header to indicate that the incoming http request uses HTTPS.
Default value :
https- Parameters:
protocolHeaderHttpsValue- The header value
-
setProxiesHeader
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- Parameters:
proxiesHeader- The header name
-
setRemoteIpHeader
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- The header name
-
setRequestAttributesEnabled
public void setRequestAttributesEnabled(boolean requestAttributesEnabled) Should this filter set request attributes for IP address, Hostname, protocol and port used for the request? These are typically used in conjunction with anAccessLogwhich will otherwise log the original values. Default istrue. The attributes set are:- org.apache.catalina.AccessLog.RemoteAddr
- org.apache.catalina.AccessLog.RemoteHost
- org.apache.catalina.AccessLog.Protocol
- org.apache.catalina.AccessLog.ServerPort
- org.apache.tomcat.remoteAddr
- Parameters:
requestAttributesEnabled-truecauses the attributes to be set,falsedisables the setting of the attributes.
-
setTrustedProxies
Set the trusted proxies either as a comma separated list of CIDR blocks or a single regular expression.- Parameters:
trustedProxies- The new trusted proxies
-
setEnableLookups
public void setEnableLookups(boolean enableLookups) Set whether DNS lookups are enabled.- Parameters:
enableLookups-trueto enable DNS lookups
-
getInternalProxiesAsString()in Tomcat 12 onwards with the return type changing toString