This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push: new 524e2cc Fix BZ 56181 - return correct remoteHost with RemoteIP[Valve|Filter] 524e2cc is described below commit 524e2ccd3fdf3ffb2830a43c414691bcbcb5f234 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Nov 26 18:57:25 2020 +0000 Fix BZ 56181 - return correct remoteHost with RemoteIP[Valve|Filter] https://bz.apache.org/bugzilla/show_bug.cgi?id=56181 --- .../catalina/filters/LocalStrings.properties | 1 + .../apache/catalina/filters/RemoteIpFilter.java | 41 +++++++++++++++++++++- .../apache/catalina/valves/LocalStrings.properties | 1 + java/org/apache/catalina/valves/RemoteIpValve.java | 19 +++++++++- webapps/docs/changelog.xml | 6 ++++ webapps/docs/config/filter.xml | 6 ++++ 6 files changed, 72 insertions(+), 2 deletions(-) diff --git a/java/org/apache/catalina/filters/LocalStrings.properties b/java/org/apache/catalina/filters/LocalStrings.properties index 2e9f564..5877b76 100644 --- a/java/org/apache/catalina/filters/LocalStrings.properties +++ b/java/org/apache/catalina/filters/LocalStrings.properties @@ -58,6 +58,7 @@ remoteCidrFilter.noRemoteIp=Client does not have an IP address. Request denied. remoteIpFilter.invalidHostHeader=Invalid value [{0}] found for Host in HTTP header [{1}] remoteIpFilter.invalidHostWithPort=Host value [{0}] in HTTP header [{1}] included a port number which will be ignored remoteIpFilter.invalidNumber=Illegal number for parameter [{0}]: [{1}] +remoteIpFilter.invalidRemoteAddress=Unable to determine the remote host because the reported remote address [{0}] is not valid requestFilter.deny=Denied request for [{0}] based on property [{1}] diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java index e8a42da..72ea1e2 100644 --- a/java/org/apache/catalina/filters/RemoteIpFilter.java +++ b/java/org/apache/catalina/filters/RemoteIpFilter.java @@ -18,6 +18,8 @@ package org.apache.catalina.filters; import java.io.IOException; import java.io.ObjectInputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -166,6 +168,13 @@ import org.apache.tomcat.util.res.StringManager; * <td>integer</td> * <td>443</td> * </tr> + * <tr> + * <td>enableLookups</td> + * <td>Should a DNS lookup be performed to provide a host name when calling {@link ServletRequest#getRemoteHost()}</td> + * <td>N/A</td> + * <td>boolean</td> + * <td>false</td> + * </tr> * </table> * <p> * <strong>Regular expression vs. IP address blocks:</strong> <code>mod_remoteip</code> allows to use address blocks (e.g. @@ -681,6 +690,8 @@ public class RemoteIpFilter extends GenericFilter { protected static final String TRUSTED_PROXIES_PARAMETER = "trustedProxies"; + protected static final String ENABLE_LOOKUPS_PARAMETER = "enableLookups"; + /** * Convert a given comma delimited list of regular expressions into an array of String * @@ -773,6 +784,8 @@ public class RemoteIpFilter extends GenericFilter { */ private Pattern trustedProxies = null; + private boolean enableLookups; + public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { boolean isInternal = internalProxies != null && @@ -823,7 +836,22 @@ public class RemoteIpFilter extends GenericFilter { if (remoteIp != null) { xRequest.setRemoteAddr(remoteIp); - xRequest.setRemoteHost(remoteIp); + if (getEnableLookups()) { + // This isn't a lazy lookup but that would be a little more + // invasive - mainly in XForwardedRequest - and if + // enableLookups is true is seems reasonable that the + // hostname 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() + xRequest.setRemoteHost(inetAddress.getCanonicalHostName()); + } catch (UnknownHostException e) { + log.debug(sm.getString("remoteIpFilter.invalidRemoteAddress", remoteIp), e); + xRequest.setRemoteHost(remoteIp); + } + } else { + xRequest.setRemoteHost(remoteIp); + } if (proxiesHeaderValue.size() == 0) { xRequest.removeHeader(proxiesHeader); @@ -1013,6 +1041,10 @@ public class RemoteIpFilter extends GenericFilter { return trustedProxies; } + public boolean getEnableLookups() { + return enableLookups; + } + @Override public void init() throws ServletException { if (getInitParameter(INTERNAL_PROXIES_PARAMETER) != null) { @@ -1070,6 +1102,10 @@ public class RemoteIpFilter extends GenericFilter { throw new NumberFormatException(sm.getString("remoteIpFilter.invalidNumber", HTTPS_SERVER_PORT_PARAMETER, e.getLocalizedMessage())); } } + + if (getInitParameter(ENABLE_LOOKUPS_PARAMETER) != null) { + setEnableLookups(Boolean.parseBoolean(getInitParameter(ENABLE_LOOKUPS_PARAMETER))); + } } /** @@ -1282,6 +1318,9 @@ public class RemoteIpFilter extends GenericFilter { } } + public void setEnableLookups(boolean enableLookups) { + this.enableLookups = enableLookups; + } /* * Log objects are not Serializable but this Filter is because it extends diff --git a/java/org/apache/catalina/valves/LocalStrings.properties b/java/org/apache/catalina/valves/LocalStrings.properties index eebf3cf..d25b3da 100644 --- a/java/org/apache/catalina/valves/LocalStrings.properties +++ b/java/org/apache/catalina/valves/LocalStrings.properties @@ -137,6 +137,7 @@ remoteCidrValve.noRemoteIp=Client does not have an IP address. Request denied. remoteIpValve.invalidHostHeader=Invalid value [{0}] found for Host in HTTP header [{1}] remoteIpValve.invalidHostWithPort=Host value [{0}] in HTTP header [{1}] included a port number which will be ignored remoteIpValve.invalidPortHeader=Invalid value [{0}] found for port in HTTP header [{1}] +remoteIpValve.invalidRemoteAddress=Unable to determine the remote host because the reported remote address [{0}] is not valid requestFilterValve.configInvalid=One or more invalid configuration settings were provided for the Remote[Addr|Host]Valve which prevented the Valve and its parent containers from starting requestFilterValve.deny=Denied request for [{0}] based on property [{1}] diff --git a/java/org/apache/catalina/valves/RemoteIpValve.java b/java/org/apache/catalina/valves/RemoteIpValve.java index 4c388c3..2497b01 100644 --- a/java/org/apache/catalina/valves/RemoteIpValve.java +++ b/java/org/apache/catalina/valves/RemoteIpValve.java @@ -17,6 +17,8 @@ package org.apache.catalina.valves; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; @@ -658,7 +660,22 @@ public class RemoteIpValve extends ValveBase { if (remoteIp != null) { request.setRemoteAddr(remoteIp); - request.setRemoteHost(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); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index c115443..746ee3e 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -106,6 +106,12 @@ <section name="Tomcat 9.0.41 (markt)" rtext="in development"> <subsection name="Catalina"> <changelog> + <fix> + <bug>56181</bug>: Update the RemoteIpValve and RemoteIpFilter so that + calls to <code>ServletRequest.getRemoteHost()</code> are consistent with + the return value of <code>ServletRequest.getRemoteAddr()</code> rather + than always returning a value for the proxy. (markt) + </fix> <add> <bug>64080</bug>: Enhance the graceful shutdown feature. Includes a new option for <code>StandardService</code>, diff --git a/webapps/docs/config/filter.xml b/webapps/docs/config/filter.xml index caa51fc..253ec44 100644 --- a/webapps/docs/config/filter.xml +++ b/webapps/docs/config/filter.xml @@ -1551,6 +1551,12 @@ FINE: Request "/docs/config/manager.html" with response status "200" <attributes> + <attribute name="enableLookups" required="false"> + <p>Should a DNS lookup be performed to provide a host name when calling + <code>ServletRequest#getRemoteHost()</code>. If not specified, the + default of <code>false</code> is used.</p> + </attribute> + <attribute name="remoteIpHeader" required="false"> <p>Name of the HTTP Header read by this valve that holds the list of traversed IP addresses starting from the requesting client. If not --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org