-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IPv6 address needs normalization (without brackets) in ForwardedRequestCustomizer #1503
Comments
What's a good example of this non-normalized header causing problems in ForwardRequestCustomizer? |
First example: If you however enable the http-forwarded module and send a request using curl like: [2001:db8:cafe::17] - - [25/Apr/2017:14:16:50 +0000] "GET / HTTP/1.1" 200 2802 So the behaviour is different. With IPv4 it's the same. Second example: final String address = httpRequest != null ? httpRequest.getRemoteAddr() : null; I was wondering where it should be normalized... |
Hmmm looks like we may be returning the |
Ah I thought this was familiar - I have raised this issue with the servlet spec as the javadoc for getServerName is ambiguous: jakartaee/servlet#97 But it didn't get resolved in the current servlet 4.0 discussions |
I don't see where you use getServerName() for the ForwardedRequestCustomizer? If you want to represent a hostname, the brackets are good. If you want it to represent an IPv6 address (request.setRemoteAddr()) , the brackets should be stripped off. |
So i have found something definitely wrong in our IPv6 handling. getRemoteAddr() must return an IP address, but we return the bracketed value. So I'm thinking we should change everywhere to strip the brackets... but that's a big change to make in dot release.... |
Ah no - discussion with @sbordet it is clear now that InetAddress accepts addresses in the [] so there is no need to strip for standard java APIs. So I think perhaps |
Closing for now unless we get guidance from servlet spec EG |
@gueuselambix sorry missed your comment. I mention the other APIs because we want to be consistent with them. Either we always strip [] or never strip.
So in java at least the [] form is treated like an IP address. |
I believe you are missing the point I am trying to make. If I use IPv6 directly to a Jetty server, com.google.common.net.InetAddresses.isInetAddress(request.getRemoteAddr()) evaluates to true for an IPv6 address. If I proxy the Jetty server and configure it with the ForwardedRequestCustomizer as documented at [1]
e.g. 'Forwarded: for="[2001:db8:cafe::17]", for=192.0.2.43' So the behaviour of Jetty server and a proxied Jetty server is different, from my point of view that is a bug in the ForwardedRequestCustomizer which sets the RemoteAddr without normalizing. |
@gueuselambix I understand completely the point you are trying to make, and I have a lot of sympathy with it. However, the issue remains that the specification of IPv6 handling is ambiguous in the spec and I've not yet received the clarification from the EG needed to make such a big change to the server. More over the InetAddress class does accept the [] form as an address, so it would be handy if However, it is a fine point you make about the differences in the Addr returned when obtained directly from a connector or from a forwarded header. This could perhaps help convince me to switch to all non [] form (I already have the patch for this implemented and stashed). But I need to consult more widely before making such a change. For now I'll reopen and seek other input. |
This is not unique to ForwardRequestCustomizer btw. If you request (without ForwardRequestCustomizer) a url like |
@sbordet what do you think of the issue of the difference between a directly obtained address (from the connection) vs a header set address? Note also that the result of |
@joakime All the handling of this is via the common Although there could be an argument to leave the [] in the Name methods but strip them from the Addr methods..... hmmm |
@gregw The https://tools.ietf.org/html/rfc3986#section-3.2.2 has some other things to think about with HostPort (things like |
Alternative approach: if you are using Jetty exclusively, you can skip the entire InetSocketAddress -> String -> String -> String conversion you are doing in the hopes of not triggering a DNS lookup in the JVM (which has likely already occurred if needed by the request) and access the valid InetSocketAddress that Jetty already has in its request. InetSocketAddress remote = ((org.eclipse.jetty.server.Request) httpServletRequest).getRemoteInetSocketAddress(); |
See below for JDK API behavior. If there is no If there is a IMHO we should be bracketed in all cases, but I can live with unbracketed in all cases. Perhaps simplest solution would be to unbracket the unresolved address in
|
@sbordet The simplest solution is to change HostPort and it will change the behaviour everywhere. I've been testing this in 9.3, but I'm thinking we should only make such a change in 9.4 onwards. Let me prepare a PR against 9.4 for consideration. I'm pushing the EG for comment also. |
I've created the PR. As much as I loath system properties for configuration, I have added one that allows the original behaviour to be restored. This makes me happier to do this in the middle of the 9.y.x series rather than just in 10.0 thoughts? |
I'm wondering if we should merge this, but in 9.4 we keep the current behaviour by default, but in 10.0 we switch the default to the new behaviour? thoughts? |
It is not optional behaviour with STRIP_IPV6 false in 9.4 and true in 10.0 |
I have noticed that this only works when the IPv6 address is enclosed by brackets []. I tested this with v9.4.28.v20200408: curl -H 'X-Forwarded-For: 2001:db8:cafe::17' -g "http://[::1]:8080/" -s
tail -n1 /opt/jetty-base/logs/2020_05_19.request.log
[2001:db8:cafe::17] - - [19/May/2020:19:54:03 +0000] "GET / HTTP/1.1" 200 2722
curl -H 'X-Forwarded-For: [2001:db8:cafe::17]' -g "http://[::1]:8080/" -s
tail -n1 /opt/jetty-base/logs/2020_05_19.request.log
2001:db8:cafe::17 - - [19/May/2020:19:54:18 +0000] "GET / HTTP/1.1" 200 2722 Since X-Forwarded-For is not a real standard (as opposed to rfc7239) the precence of these brackets are arguable... However in most cases the IPv6 address is represented without brackets in the X-Forwarded-For header. This is also mentioned in RFC7239: https://tools.ietf.org/html/rfc7239#section-7.4
https://github.com/eclipse/jetty.project/blob/jetty-9.4.28.v20200408/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java#L77 I think it would be better to add those brackets only when STRIP_IPV6=false. In other words if it is true you would not expect IPv6 addresses with brackets. |
I'll reopen this one for you. |
This has been fixed with the work for #5079. |
This issue has not been fixed. Brackets are still added to the IPv6 address. The remote address is not a hostname, so brackets should not be added. curl -H 'X-Forwarded-For: 2001:db8:cafe::17' -g "http://[::1]:8080/" -s
tail -n1 /opt/jetty-base/logs/*.request.log
[2001:db8:cafe::17] - - [19/May/2020:19:54:03 +0000] "GET / HTTP/1.1" 200 2722 You marked this as fixed, but is isn't. |
@gueuselambix your issue has nothing to do with ForwardedRequestCustomizer. The reason you are seeing brackets is because Please open a new issue if you feel this is inappropriate. |
@gueuselambix can you please detail what the problem actually is? It's just a logging issue on the request log? Using the Java APIs, there is no difference if an IPv6 address is bracketed or not. Our point is that the latest specification for Since bracketing seems the way to go, I don't see a case where un-bracketing would be necessary. |
If you use |
After processing of the X-Forwarded-For, ServletRequest.getRemoteAddr() returns the bracketed address. But I would expect the unbracketed IP address according to The brackets should IMHO only be added in a context where it is not clear to distinguish it from the port. I am using a software which uses https://guava.dev/releases/19.0/api/docs/com/google/common/net/InetAddresses.html#forString(java.lang.String) which does not expect brackets. |
JDK's @gueuselambix @gregw we go back to "what's the difference between |
@sbordet "For HTTP servlets, same as the value of the CGI variable REMOTE_ADDR." If you look at the spec of REMOTE_ADDR in the CGI spec https://tools.ietf.org/html/rfc3875#section-4.1.8, it revers to "Internet Protocol Version 6 (IPv6) Addressing Architecture" https://tools.ietf.org/html/rfc3513#section-2.2 PHP suffered from a similar issue, which they fixed: https://bugs.php.net/bug.php?id=77722 |
@gueuselambix by the same rfc3875, No matter what, the moment we decide on one behavior, we break someone. I think in the long run it would be better to not care at all about bracketing, like JDK's @gregw maybe you can raise it at the Servlet Specification? |
RFC3513 is obsolete, replaced by RFC4291 in 2006. Guava has a long history of issues around IPv6 support. Guava doesn't support ...
They have no plans to support these (per their own responses in their issue trackers). The fact that the Servlet spec |
I'm very much against changing what we return by default.... again. We have been pushed back and forth by this as the world appears split between those that expect []; those that don't; and the growing group of those that can go either way. Possibnly, we could possible add a compliance mode that stripped them from |
According to https://tools.ietf.org/html/rfc7239#section-6.1 the IPv6 address should be enclosed by square brackets.
The ForwardedRequestCustomizer now extracts the header without normalization and sets in on the request (request.setRemoteAddr(InetSocketAddress)), see [1]
Code that depends on the remote address will fail because it assumes the content represents a valid IP address.
Is it possible to normalize the value to a valid IPv4 or IPv6 address (if the header contains the format "IPv6address" or "IPv4address" as specified in https://tools.ietf.org/html/rfc3986#appendix-A).
[1] https://github.com/eclipse/jetty.project/blob/5fefd5d8bd68bb87a2bad16138dfc0ee121eddcf/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java#L388
The text was updated successfully, but these errors were encountered: