All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.catalina.valves.RemoteIpValve Maven / Gradle / Ivy

There is a newer version: 11.0.0-M26
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.valves;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.ServletException;

import org.apache.catalina.AccessLog;
import org.apache.catalina.Globals;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.StringUtils;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.parser.Host;

/**
 * 

* 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 (e.g. "X-Forwarded-For"). *

*

* Another feature of this valve 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 valve proceeds as follows: *

*

* If the incoming request.getRemoteAddr() matches the valve'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 value x-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 value X-Forwarded-Proto) * consists only of forwards that match protocolHeaderHttpsValue configuration parameter (default * https) then request.isSecure = true, request.scheme = https and * request.serverPort = 443. Note that 443 can be overwritten with the $httpsServerPort * configuration parameter.
  • *
  • Mark the request with the attribute {@link Globals#REQUEST_FORWARDED_ATTRIBUTE} and value {@code Boolean.TRUE} to * indicate that this request has been forwarded by one or more proxies.
  • *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Configuration parameters
RemoteIpValve propertyDescriptionEquivalent mod_remoteip directiveFormatDefault Value
remoteIpHeaderName of the Http Header read by this valve that holds the list of traversed IP addresses starting from the * requesting clientRemoteIPHeaderCompliant http header namex-forwarded-for
internalProxiesRegular 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 * valueRemoteIPInternalProxyRegular expression (in the syntax supported by {@link java.util.regex.Pattern 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 ::1 are allowed.
proxiesHeaderName of the http header created by this valve to hold the list of proxies that have been processed in the * incoming remoteIpHeaderproxiesHeaderCompliant http header namex-forwarded-by
trustedProxiesRegular 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 valueRemoteIPTrustedProxyRegular expression (in the syntax supported by {@link java.util.regex.Pattern java.util.regex}) 
protocolHeaderName of the http header read by this valve that holds the flag that this requestN/ACompliant http header name like X-Forwarded-Proto, X-Forwarded-Ssl or * Front-End-HttpsX-Forwarded-Proto
protocolHeaderHttpsValueValue of the protocolHeader to indicate that it is an Https requestN/AString like https or ONhttps
httpServerPortValue returned by {@link javax.servlet.ServletRequest#getServerPort()} when the protocolHeader * indicates http protocolN/Ainteger80
httpsServerPortValue returned by {@link javax.servlet.ServletRequest#getServerPort()} when the protocolHeader * indicates https protocolN/Ainteger443
*

* 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 {@link RequestFilterValve} does. *

*
*

* Sample with internal proxies *

*

* RemoteIpValve configuration: *

* * <Valve * className="org.apache.catalina.valves.RemoteIpValve" * internalProxies="192\.168\.0\.10|192\.168\.0\.11" * remoteIpHeader="x-forwarded-for" * proxiesHeader="x-forwarded-by" * protocolHeader="x-forwarded-proto" * /> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Request Values
propertyValue Before RemoteIpValveValue After RemoteIpValve
request.remoteAddr192.168.0.10140.211.11.130
request.header['x-forwarded-for']140.211.11.130, 192.168.0.10null
request.header['x-forwarded-by']nullnull
request.header['x-forwarded-proto']httpshttps
request.schemehttphttps
request.securefalsetrue
request.serverPort80443
*

* 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 *

*

* RemoteIpValve configuration: *

* * <Valve * className="org.apache.catalina.valves.RemoteIpValve" * internalProxies="192\.168\.0\.10|192\.168\.0\.11" * remoteIpHeader="x-forwarded-for" * proxiesHeader="x-forwarded-by" * trustedProxies="proxy1|proxy2" * /> * * * * * * * * * * * * * * * * * * * * * * *
Request Values
propertyValue Before RemoteIpValveValue After RemoteIpValve
request.remoteAddr192.168.0.10140.211.11.130
request.header['x-forwarded-for']140.211.11.130, proxy1, proxy2null
request.header['x-forwarded-by']nullproxy1, 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.valves.RemoteIpValve" * internalProxies="192\.168\.0\.10|192\.168\.0\.11" * remoteIpHeader="x-forwarded-for" * proxiesHeader="x-forwarded-by" * trustedProxies="proxy1|proxy2" * /> * * * * * * * * * * * * * * * * * * * * * * *
Request Values
propertyValue Before RemoteIpValveValue After RemoteIpValve
request.remoteAddr192.168.0.10140.211.11.130
request.header['x-forwarded-for']140.211.11.130, proxy1, proxy2, 192.168.0.10null
request.header['x-forwarded-by']nullproxy1, 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 *

*

* RemoteIpValve configuration: *

* * <Valve * className="org.apache.catalina.valves.RemoteIpValve" * internalProxies="192\.168\.0\.10|192\.168\.0\.11" * remoteIpHeader="x-forwarded-for" * proxiesHeader="x-forwarded-by" * trustedProxies="proxy1|proxy2" * /> * * * * * * * * * * * * * * * * * * * * * * *
Request Values
propertyValue Before RemoteIpValveValue After RemoteIpValve
request.remoteAddr192.168.0.10untrusted-proxy
request.header['x-forwarded-for']140.211.11.130, untrusted-proxy, proxy1140.211.11.130
request.header['x-forwarded-by']nullproxy1
*

* 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. *

*/ public class RemoteIpValve extends ValveBase { /** * {@link Pattern} for a comma delimited string that support whitespace characters */ private static final Pattern commaSeparatedValuesPattern = Pattern.compile("\\s*,\\s*"); /** * Logger */ private static final Log log = LogFactory.getLog(RemoteIpValve.class); /** * Convert a given comma delimited String into an array of String * * @param commaDelimitedStrings The string to convert * * @return array of String (non null) */ protected static String[] commaDelimitedListToStringArray(String commaDelimitedStrings) { return (commaDelimitedStrings == null || commaDelimitedStrings.length() == 0) ? new String[0] : commaSeparatedValuesPattern.split(commaDelimitedStrings); } /** * Convert an array of strings in a comma delimited string * * @param stringList The string list to convert * * @return The concatenated string * * @deprecated Unused. This will be removed in Tomcat 10.1.x onwards. Use * {@link StringUtils#join(java.util.Collection)} instead */ @Deprecated protected static String listToCommaDelimitedString(List stringList) { if (stringList == null) { return ""; } StringBuilder result = new StringBuilder(); for (Iterator it = stringList.iterator(); it.hasNext();) { Object element = it.next(); if (element != null) { result.append(element); if (it.hasNext()) { result.append(", "); } } } return result.toString(); } private String hostHeader = null; private boolean changeLocalName = false; /** * @see #setHttpServerPort(int) */ private int httpServerPort = 80; /** * @see #setHttpsServerPort(int) */ private int httpsServerPort = 443; private String portHeader = null; private boolean changeLocalPort = false; /** * @see #setInternalProxies(String) */ private Pattern internalProxies = Pattern .compile("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"); /** * @see #setProtocolHeader(String) */ private String protocolHeader = "X-Forwarded-Proto"; /** * @see #setProtocolHeaderHttpsValue(String) */ private String protocolHeaderHttpsValue = "https"; /** * @see #setProxiesHeader(String) */ private String proxiesHeader = "X-Forwarded-By"; /** * @see #setRemoteIpHeader(String) */ private String remoteIpHeader = "X-Forwarded-For"; /** * @see #setRequestAttributesEnabled(boolean) */ private boolean requestAttributesEnabled = true; /** * @see RemoteIpValve#setTrustedProxies(String) */ private Pattern trustedProxies = null; /** * Default constructor that ensures {@link ValveBase#ValveBase(boolean)} is called with true. */ public RemoteIpValve() { // Async requests are supported with this valve super(true); } /** * Obtain the name of the HTTP header used to override the value returned by {@link Request#getServerName()} and * (optionally depending on {link {@link #isChangeLocalName()} {@link Request#getLocalName()}. * * @return The HTTP header name */ public String getHostHeader() { return hostHeader; } /** * Set the name of the HTTP header used to override the value returned by {@link Request#getServerName()} and * (optionally depending on {link {@link #isChangeLocalName()} {@link Request#getLocalName()}. * * @param hostHeader The HTTP header name */ public void setHostHeader(String hostHeader) { this.hostHeader = hostHeader; } public boolean isChangeLocalName() { return changeLocalName; } public void setChangeLocalName(boolean changeLocalName) { this.changeLocalName = changeLocalName; } public int getHttpServerPort() { return httpServerPort; } public int getHttpsServerPort() { return httpsServerPort; } /** * Obtain the name of the HTTP header used to override the value returned by {@link Request#getServerPort()} and * (optionally depending on {link {@link #isChangeLocalPort()} {@link Request#getLocalPort()}. * * @return The HTTP header name */ public String getPortHeader() { return portHeader; } /** * Set the name of the HTTP header used to override the value returned by {@link Request#getServerPort()} and * (optionally depending on {link {@link #isChangeLocalPort()} {@link Request#getLocalPort()}. * * @param portHeader The HTTP header name */ public void setPortHeader(String portHeader) { this.portHeader = portHeader; } public boolean isChangeLocalPort() { return changeLocalPort; } public void setChangeLocalPort(boolean changeLocalPort) { this.changeLocalPort = changeLocalPort; } /** * @see #setInternalProxies(String) * * @return Regular expression that defines the internal proxies */ public String getInternalProxies() { if (internalProxies == null) { return null; } return internalProxies.toString(); } /** * @see #setProtocolHeader(String) * * @return the protocol header (e.g. "X-Forwarded-Proto") */ public String getProtocolHeader() { return protocolHeader; } /** * @see RemoteIpValve#setProtocolHeaderHttpsValue(String) * * @return the value of the protocol header for incoming https request (e.g. "https") */ public String getProtocolHeaderHttpsValue() { return protocolHeaderHttpsValue; } /** * @see #setProxiesHeader(String) * * @return the proxies header name (e.g. "X-Forwarded-By") */ public String getProxiesHeader() { return proxiesHeader; } /** * @see #setRemoteIpHeader(String) * * @return the remote IP header name (e.g. "X-Forwarded-For") */ public String getRemoteIpHeader() { return remoteIpHeader; } /** * @see #setRequestAttributesEnabled(boolean) * * @return true if the attributes will be logged, otherwise false */ public boolean getRequestAttributesEnabled() { return requestAttributesEnabled; } /** * @see #setTrustedProxies(String) * * @return Regular expression that defines the trusted proxies */ public String getTrustedProxies() { if (trustedProxies == null) { return null; } return trustedProxies.toString(); } @Override public void invoke(Request request, Response response) throws IOException, ServletException { final String originalRemoteAddr = request.getRemoteAddr(); final String originalRemoteHost = request.getRemoteHost(); final String originalScheme = request.getScheme(); final boolean originalSecure = request.isSecure(); final String originalServerName = request.getServerName(); final String originalLocalName = isChangeLocalName() ? request.getLocalName() : null; final int originalServerPort = request.getServerPort(); final int originalLocalPort = request.getLocalPort(); final String originalProxiesHeader = request.getHeader(proxiesHeader); final String originalRemoteIpHeader = request.getHeader(remoteIpHeader); boolean isInternal = internalProxies != null && internalProxies.matcher(originalRemoteAddr).matches(); if (isInternal || (trustedProxies != null && trustedProxies.matcher(originalRemoteAddr).matches())) { String remoteIp = null; Deque proxiesHeaderValue = new ArrayDeque<>(); StringBuilder concatRemoteIpHeaderValue = new StringBuilder(); for (Enumeration e = request.getHeaders(remoteIpHeader); e.hasMoreElements();) { if (concatRemoteIpHeaderValue.length() > 0) { concatRemoteIpHeaderValue.append(", "); } concatRemoteIpHeaderValue.append(e.nextElement()); } String[] remoteIpHeaderValue = commaDelimitedListToStringArray(concatRemoteIpHeaderValue.toString()); int idx; if (!isInternal) { proxiesHeaderValue.addFirst(originalRemoteAddr); } // loop on remoteIpHeaderValue to find the first trusted remote ip and to build the proxies chain for (idx = remoteIpHeaderValue.length - 1; idx >= 0; idx--) { String currentRemoteIp = remoteIpHeaderValue[idx]; remoteIp = currentRemoteIp; if (internalProxies != null && internalProxies.matcher(currentRemoteIp).matches()) { // do nothing, internalProxies IPs are not appended to the } else if (trustedProxies != null && trustedProxies.matcher(currentRemoteIp).matches()) { proxiesHeaderValue.addFirst(currentRemoteIp); } else { idx--; // decrement idx because break statement doesn't do it break; } } // continue to loop on remoteIpHeaderValue to build the new value of the remoteIpHeader Deque newRemoteIpHeaderValue = new ArrayDeque<>(); for (; idx >= 0; idx--) { String currentRemoteIp = remoteIpHeaderValue[idx]; newRemoteIpHeaderValue.addFirst(currentRemoteIp); } if (remoteIp != null) { request.setRemoteAddr(remoteIp); if (request.getConnector().getEnableLookups()) { // This isn't a lazy lookup but that would be a little more // invasive - mainly in Request.getRemoteHost() - and if // enableLookups is true it seems reasonable that the // hotsname will be required so look it up here. try { InetAddress inetAddress = InetAddress.getByName(remoteIp); // We know we need a DNS look up so use getCanonicalHostName() request.setRemoteHost(inetAddress.getCanonicalHostName()); } catch (UnknownHostException e) { log.debug(sm.getString("remoteIpValve.invalidRemoteAddress", remoteIp), e); request.setRemoteHost(remoteIp); } } else { request.setRemoteHost(remoteIp); } if (proxiesHeaderValue.size() == 0) { request.getCoyoteRequest().getMimeHeaders().removeHeader(proxiesHeader); } else { String commaDelimitedListOfProxies = StringUtils.join(proxiesHeaderValue); request.getCoyoteRequest().getMimeHeaders().setValue(proxiesHeader) .setString(commaDelimitedListOfProxies); } if (newRemoteIpHeaderValue.size() == 0) { request.getCoyoteRequest().getMimeHeaders().removeHeader(remoteIpHeader); } else { String commaDelimitedRemoteIpHeaderValue = StringUtils.join(newRemoteIpHeaderValue); request.getCoyoteRequest().getMimeHeaders().setValue(remoteIpHeader) .setString(commaDelimitedRemoteIpHeaderValue); } } if (protocolHeader != null) { String protocolHeaderValue = request.getHeader(protocolHeader); if (protocolHeaderValue == null) { // Don't modify the secure, scheme and serverPort attributes // of the request } else if (isForwardedProtoHeaderValueSecure(protocolHeaderValue)) { request.setSecure(true); request.getCoyoteRequest().scheme().setString("https"); setPorts(request, httpsServerPort); } else { request.setSecure(false); request.getCoyoteRequest().scheme().setString("http"); setPorts(request, httpServerPort); } } if (hostHeader != null) { String hostHeaderValue = request.getHeader(hostHeader); if (hostHeaderValue != null) { try { int portIndex = Host.parse(hostHeaderValue); if (portIndex > -1) { log.debug(sm.getString("remoteIpValve.invalidHostWithPort", hostHeaderValue, hostHeader)); hostHeaderValue = hostHeaderValue.substring(0, portIndex); } request.getCoyoteRequest().serverName().setString(hostHeaderValue); if (isChangeLocalName()) { request.getCoyoteRequest().localName().setString(hostHeaderValue); } } catch (IllegalArgumentException iae) { log.debug(sm.getString("remoteIpValve.invalidHostHeader", hostHeaderValue, hostHeader)); } } } request.setAttribute(Globals.REQUEST_FORWARDED_ATTRIBUTE, Boolean.TRUE); if (log.isDebugEnabled()) { log.debug("Incoming request " + request.getRequestURI() + " with originalRemoteAddr [" + originalRemoteAddr + "], originalRemoteHost=[" + originalRemoteHost + "], originalSecure=[" + originalSecure + "], originalScheme=[" + originalScheme + "], originalServerName=[" + originalServerName + "], originalServerPort=[" + originalServerPort + "] will be seen as newRemoteAddr=[" + request.getRemoteAddr() + "], newRemoteHost=[" + request.getRemoteHost() + "], newSecure=[" + request.isSecure() + "], newScheme=[" + request.getScheme() + "], newServerName=[" + request.getServerName() + "], newServerPort=[" + request.getServerPort() + "]"); } } else { if (log.isDebugEnabled()) { log.debug("Skip RemoteIpValve for request " + request.getRequestURI() + " with originalRemoteAddr '" + request.getRemoteAddr() + "'"); } } if (requestAttributesEnabled) { request.setAttribute(AccessLog.REMOTE_ADDR_ATTRIBUTE, request.getRemoteAddr()); request.setAttribute(Globals.REMOTE_ADDR_ATTRIBUTE, request.getRemoteAddr()); request.setAttribute(AccessLog.REMOTE_HOST_ATTRIBUTE, request.getRemoteHost()); request.setAttribute(AccessLog.PROTOCOL_ATTRIBUTE, request.getProtocol()); request.setAttribute(AccessLog.SERVER_NAME_ATTRIBUTE, request.getServerName()); request.setAttribute(AccessLog.SERVER_PORT_ATTRIBUTE, Integer.valueOf(request.getServerPort())); } try { getNext().invoke(request, response); } finally { if (!request.isAsync()) { request.setRemoteAddr(originalRemoteAddr); request.setRemoteHost(originalRemoteHost); request.setSecure(originalSecure); request.getCoyoteRequest().scheme().setString(originalScheme); request.getCoyoteRequest().serverName().setString(originalServerName); if (isChangeLocalName()) { request.getCoyoteRequest().localName().setString(originalLocalName); } request.setServerPort(originalServerPort); request.setLocalPort(originalLocalPort); MimeHeaders headers = request.getCoyoteRequest().getMimeHeaders(); if (originalProxiesHeader == null || originalProxiesHeader.length() == 0) { headers.removeHeader(proxiesHeader); } else { headers.setValue(proxiesHeader).setString(originalProxiesHeader); } if (originalRemoteIpHeader == null || originalRemoteIpHeader.length() == 0) { headers.removeHeader(remoteIpHeader); } else { headers.setValue(remoteIpHeader).setString(originalRemoteIpHeader); } } } } /* * Considers the value to be secure if it exclusively holds forwards for {@link #protocolHeaderHttpsValue}. */ private boolean isForwardedProtoHeaderValueSecure(String protocolHeaderValue) { if (!protocolHeaderValue.contains(",")) { return protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue); } String[] forwardedProtocols = commaDelimitedListToStringArray(protocolHeaderValue); if (forwardedProtocols.length == 0) { return false; } for (String forwardedProtocol : forwardedProtocols) { if (!protocolHeaderHttpsValue.equalsIgnoreCase(forwardedProtocol)) { return false; } } return true; } private void setPorts(Request request, int defaultPort) { int port = defaultPort; if (portHeader != null) { String portHeaderValue = request.getHeader(portHeader); if (portHeaderValue != null) { try { port = Integer.parseInt(portHeaderValue); } catch (NumberFormatException nfe) { if (log.isDebugEnabled()) { log.debug(sm.getString("remoteIpValve.invalidPortHeader", portHeaderValue, portHeader), nfe); } } } } request.setServerPort(port); if (changeLocalPort) { request.setLocalPort(port); } } /** *

* Server Port value if the {@link #protocolHeader} is not null and does not indicate HTTP *

*

* Default value : 80 *

* * @param httpServerPort The server port */ public void setHttpServerPort(int httpServerPort) { this.httpServerPort = httpServerPort; } /** *

* Server Port value if the {@link #protocolHeader} indicates HTTPS *

*

* Default value : 443 *

* * @param httpsServerPort The server port */ public void setHttpsServerPort(int httpsServerPort) { this.httpsServerPort = httpsServerPort; } /** *

* Regular expression that defines the internal proxies. *

*

* Default value : * 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}|0:0:0:0:0:0:0:1 *

* * @param internalProxies The proxy regular expression */ public void setInternalProxies(String internalProxies) { if (internalProxies == null || internalProxies.length() == 0) { this.internalProxies = null; } else { this.internalProxies = Pattern.compile(internalProxies); } } /** *

* Header that holds the incoming protocol, usually named X-Forwarded-Proto. If null, * request.scheme and request.secure will not be modified. *

*

* Default value : X-Forwarded-Proto *

* * @param protocolHeader The header name */ public void setProtocolHeader(String protocolHeader) { this.protocolHeader = protocolHeader; } /** *

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

*

* Default value : https *

* * @param protocolHeaderHttpsValue The header name */ public void setProtocolHeaderHttpsValue(String protocolHeaderHttpsValue) { this.protocolHeaderHttpsValue = protocolHeaderHttpsValue; } /** *

* 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 *

* * @param proxiesHeader The header name */ public void setProxiesHeader(String proxiesHeader) { this.proxiesHeader = proxiesHeader; } /** *

* 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 *

* * @param remoteIpHeader The header name */ public void setRemoteIpHeader(String remoteIpHeader) { this.remoteIpHeader = remoteIpHeader; } /** * Should this valve set request attributes for IP address, Hostname, protocol and port used for the request? This * are typically used in conjunction with the {@link AccessLog} which will otherwise log the original values. * Default is true. 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
  • *
* * @param requestAttributesEnabled true causes the attributes to be set, false disables * the setting of the attributes. */ public void setRequestAttributesEnabled(boolean requestAttributesEnabled) { this.requestAttributesEnabled = requestAttributesEnabled; } /** *

* Regular expression defining proxies that are trusted when they appear in the {@link #remoteIpHeader} header. *

*

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

* * @param trustedProxies The regular expression */ public void setTrustedProxies(String trustedProxies) { if (trustedProxies == null || trustedProxies.length() == 0) { this.trustedProxies = null; } else { this.trustedProxies = Pattern.compile(trustedProxies); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy