Class XForwardedRequestWrapperFactory
- java.lang.Object
-
- org.apache.wicket.protocol.http.servlet.AbstractRequestWrapperFactory
-
- org.apache.wicket.protocol.http.servlet.XForwardedRequestWrapperFactory
-
public class XForwardedRequestWrapperFactory extends AbstractRequestWrapperFactory
Request wrapper factory 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 wrapper proceeds as follows:
If the incoming
request.getRemoteAddr()matches the servlet filter's list of internal 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(e.g.x-forwarded-for) equals to the value ofprotocolHeaderHttpsValueconfiguration parameter (defaulthttps) thenrequest.isSecure = true,request.scheme = httpsandrequest.serverPort = 443. Note that 443 can be overwritten with the$httpsServerPortconfiguration parameter.
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 allowedInternalProxies List of internal proxies ip adress. If they appear in the remoteIpHeadervalue, they will be trusted and will not appear in theproxiesHeadervalueRemoteIPInternalProxy Comma delimited list of regular expressions (in the syntax supported by the Patternlibrary)10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3}, 172\\.(?:1[6-9]|2\\d|3[0-1]).\\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, 172.16/12, 169.254/16 and 127/8 are allowedproxiesHeader Name of the http header created by this servlet filter to hold the list of proxies that have been processed in the incoming remoteIPHeaderRemoteIPProxiesHeader Compliant http header name x-forwarded-by trustedProxies List of trusted proxies ip adress. If they appear in the remoteIpHeadervalue, they will be trusted and will appear in theproxiesHeadervalueRemoteIPTrustedProxy Comma delimited list of regular expressions (in the syntax supported by the Patternlibrary)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-SslorFront-End-HttpsnullprotocolHeaderHttpsValue Value of the protocolHeaderto indicate that it is an Https requestN/A String like httpsorONhttpshttpServerPort Value returned by ServletRequest.getServerPort()when theprotocolHeaderindicateshttpprotocolN/A integer 80 httpsServerPort Value returned by ServletRequest.getServerPort()when theprotocolHeaderindicateshttpsprotocolN/A integer 443 Regular expression vs. IP address blocks:
mod_remoteipallows to use address blocks (e.g.192.168/16) to configureRemoteIPInternalProxyandRemoteIPTrustedProxy; as the JVM doesnt have a library similar to apr_ipsubnet_test.
Sample with internal proxies
XForwardedFilter configuration:
<filter> <filter-name>XForwardedFilter</filter-name> <filter-class>fr.xebia.servlet.filter.XForwardedFilter</filter-class> <init-param> <param-name>allowedInternalProxies</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>XForwardedFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>Request values:
Note :property Value Before XForwardedFilter Value After XForwardedFilter 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-byheader is null because only internal proxies as been traversed by the request.x-forwarded-byis null because all the proxies are trusted or internal.
Sample with trusted proxies
XForwardedFilter configuration:
<filter> <filter-name>XForwardedFilter</filter-name> <filter-class>fr.xebia.servlet.filter.XForwardedFilter</filter-class> <init-param> <param-name>allowedInternalProxies</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>XForwardedFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>Request values:
Note :property Value Before XForwardedFilter Value After XForwardedFilter 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 proxy1andproxy2are both trusted proxies that come inx-forwarded-forheader, they both are migrated inx-forwarded-byheader.x-forwarded-byis null because all the proxies are trusted or internal.
Sample with internal and trusted proxies
XForwardedFilter configuration:
<filter> <filter-name>XForwardedFilter</filter-name> <filter-class>fr.xebia.servlet.filter.XForwardedFilter</filter-class> <init-param> <param-name>allowedInternalProxies</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>XForwardedFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>Request values:
Note :property Value Before XForwardedFilter Value After XForwardedFilter 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 proxy1andproxy2are both trusted proxies that come inx-forwarded-forheader, they both are migrated inx-forwarded-byheader. As192.168.0.10is an internal proxy, it does not appear inx-forwarded-by.x-forwarded-byis null because all the proxies are trusted or internal.
Sample with an untrusted proxy
XForwardedFilter configuration:
<filter> <filter-name>XForwardedFilter</filter-name> <filter-class>fr.xebia.servlet.filter.XForwardedFilter</filter-class> <init-param> <param-name>allowedInternalProxies</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>XForwardedFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>Request values:
Note :property Value Before XForwardedFilter Value After XForwardedFilter 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 x-forwarded-byholds the trusted proxyproxy1.x-forwarded-byholds140.211.11.130becauseuntrusted-proxyis not trusted and thus, we can not trust thatuntrusted-proxyis the actual remote ip.request.remoteAddrisuntrusted-proxythat is an IP verified byproxy1.- Author:
- Cyrille Le Clerc, Juergen Donnerstag
- 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
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classXForwardedRequestWrapperFactory.ConfigFilter Config
-
Field Summary
Fields Modifier and Type Field Description protected static java.lang.StringHTTP_SERVER_PORT_PARAMETERprotected static java.lang.StringHTTPS_SERVER_PORT_PARAMETERprotected static java.lang.StringINTERNAL_PROXIES_PARAMETERprotected static java.lang.StringPROTOCOL_HEADER_PARAMETERprotected static java.lang.StringPROTOCOL_HEADER_SSL_VALUE_PARAMETERprotected static java.lang.StringPROXIES_HEADER_PARAMETERprotected static java.lang.StringREMOTE_IP_HEADER_PARAMETERprotected static java.lang.StringTRUSTED_PROXIES_PARAMETER
-
Constructor Summary
Constructors Constructor Description XForwardedRequestWrapperFactory()Construct.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description XForwardedRequestWrapperFactory.ConfiggetConfig()voidinit(javax.servlet.FilterConfig filterConfig)booleanneedsWrapper(javax.servlet.http.HttpServletRequest request)javax.servlet.http.HttpServletRequestnewRequestWrapper(javax.servlet.http.HttpServletRequest request)voidsetConfig(XForwardedRequestWrapperFactory.Config config)The Wicket application might want to provide its own config-
Methods inherited from class org.apache.wicket.protocol.http.servlet.AbstractRequestWrapperFactory
commaDelimitedListToPatternArray, commaDelimitedListToStringArray, getWrapper, isEnabled, listToCommaDelimitedString, matchesOne, setEnabled
-
-
-
-
Field Detail
-
HTTP_SERVER_PORT_PARAMETER
protected static final java.lang.String HTTP_SERVER_PORT_PARAMETER
- See Also:
- Constant Field Values
-
HTTPS_SERVER_PORT_PARAMETER
protected static final java.lang.String HTTPS_SERVER_PORT_PARAMETER
- See Also:
- Constant Field Values
-
INTERNAL_PROXIES_PARAMETER
protected static final java.lang.String INTERNAL_PROXIES_PARAMETER
- See Also:
- Constant Field Values
-
PROTOCOL_HEADER_PARAMETER
protected static final java.lang.String PROTOCOL_HEADER_PARAMETER
- See Also:
- Constant Field Values
-
PROTOCOL_HEADER_SSL_VALUE_PARAMETER
protected static final java.lang.String PROTOCOL_HEADER_SSL_VALUE_PARAMETER
- See Also:
- Constant Field Values
-
PROXIES_HEADER_PARAMETER
protected static final java.lang.String PROXIES_HEADER_PARAMETER
- See Also:
- Constant Field Values
-
REMOTE_IP_HEADER_PARAMETER
protected static final java.lang.String REMOTE_IP_HEADER_PARAMETER
- See Also:
- Constant Field Values
-
TRUSTED_PROXIES_PARAMETER
protected static final java.lang.String TRUSTED_PROXIES_PARAMETER
- See Also:
- Constant Field Values
-
-
Method Detail
-
getConfig
public final XForwardedRequestWrapperFactory.Config getConfig()
- Returns:
- XForwarded filter specific config
-
setConfig
public final void setConfig(XForwardedRequestWrapperFactory.Config config)
The Wicket application might want to provide its own config- Parameters:
config-
-
needsWrapper
public boolean needsWrapper(javax.servlet.http.HttpServletRequest request)
- Specified by:
needsWrapperin classAbstractRequestWrapperFactory- Returns:
- True, if a wrapper is needed
-
newRequestWrapper
public javax.servlet.http.HttpServletRequest newRequestWrapper(javax.servlet.http.HttpServletRequest request)
- Specified by:
newRequestWrapperin classAbstractRequestWrapperFactory- Parameters:
request-- Returns:
- Either the original request or the wrapper
-
init
public void init(javax.servlet.FilterConfig filterConfig)
- Parameters:
filterConfig-
-
-