in java/org/apache/catalina/valves/RemoteIpValve.java [568:746]
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<String> proxiesHeaderValue = new ArrayDeque<>();
StringBuilder concatRemoteIpHeaderValue = new StringBuilder();
for (Enumeration<String> e = request.getHeaders(remoteIpHeader); e.hasMoreElements();) {
if (!concatRemoteIpHeaderValue.isEmpty()) {
concatRemoteIpHeaderValue.append(", ");
}
concatRemoteIpHeaderValue.append(e.nextElement());
}
String[] remoteIpHeaderValue = StringUtils.splitCommaSeparated(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<String> 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.isEmpty()) {
request.getCoyoteRequest().getMimeHeaders().removeHeader(proxiesHeader);
} else {
String commaDelimitedListOfProxies = StringUtils.join(proxiesHeaderValue);
request.getCoyoteRequest().getMimeHeaders().setValue(proxiesHeader)
.setString(commaDelimitedListOfProxies);
}
if (newRemoteIpHeaderValue.isEmpty()) {
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.isTraceEnabled()) {
log.trace("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.isTraceEnabled()) {
log.trace("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.isEmpty()) {
headers.removeHeader(proxiesHeader);
} else {
headers.setValue(proxiesHeader).setString(originalProxiesHeader);
}
if (originalRemoteIpHeader == null || originalRemoteIpHeader.isEmpty()) {
headers.removeHeader(remoteIpHeader);
} else {
headers.setValue(remoteIpHeader).setString(originalRemoteIpHeader);
}
}
}
}