-
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
Issue #5224 X-Forwarded-Host support for port #5226
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -497,7 +497,67 @@ public static Stream<Arguments> cases() | |
.requestURL("http://fw.example.com:4333/") | ||
.remoteAddr("8.5.4.3").remotePort(2222) | ||
), | ||
|
||
Arguments.of(new Request("X-Forwarded-* (Multiple Ports)") | ||
.headers( | ||
"GET / HTTP/1.1", | ||
"Host: myhost:10001", | ||
"X-Forwarded-For: 127.0.0.1:8888,127.0.0.2:9999", | ||
"X-Forwarded-Port: 10002", | ||
"X-Forwarded-Proto: https", | ||
"X-Forwarded-Host: sub1.example.com:10003", | ||
"X-Forwarded-Server: sub2.example.com" | ||
), | ||
new Expectations() | ||
.scheme("https").serverName("sub1.example.com").serverPort(10003) | ||
.requestURL("https://sub1.example.com:10003/") | ||
.remoteAddr("127.0.0.1").remotePort(8888) | ||
), | ||
Arguments.of(new Request("X-Forwarded-* (Multiple Ports - Server First)") | ||
.headers( | ||
"GET / HTTP/1.1", | ||
"X-Forwarded-Server: sub2.example.com:10007", | ||
"Host: myhost:10001", | ||
"X-Forwarded-For: 127.0.0.1:8888,127.0.0.2:9999", | ||
"X-Forwarded-Proto: https", | ||
"X-Forwarded-Port: 10002", | ||
"X-Forwarded-Host: sub1.example.com:10003" | ||
), | ||
new Expectations() | ||
.scheme("https").serverName("sub1.example.com").serverPort(10003) | ||
.requestURL("https://sub1.example.com:10003/") | ||
.remoteAddr("127.0.0.1").remotePort(8888) | ||
), | ||
Arguments.of(new Request("X-Forwarded-* (Multiple Ports - setForwardedPortAsAuthority = false)") | ||
.configureCustomizer((customizer) -> customizer.setForwardedPortAsAuthority(false)) | ||
.headers( | ||
"GET / HTTP/1.1", | ||
"Host: myhost:10001", | ||
"X-Forwarded-For: 127.0.0.1:8888,127.0.0.2:9999", | ||
"X-Forwarded-Port: 10002", | ||
"X-Forwarded-Proto: https", | ||
"X-Forwarded-Host: sub1.example.com:10003", | ||
"X-Forwarded-Server: sub2.example.com" | ||
), | ||
new Expectations() | ||
.scheme("https").serverName("sub1.example.com").serverPort(10003) | ||
.requestURL("https://sub1.example.com:10003/") | ||
.remoteAddr("127.0.0.1").remotePort(8888) | ||
), | ||
Arguments.of(new Request("X-Forwarded-* (Multiple Ports Alt Order)") | ||
.headers( | ||
"GET / HTTP/1.1", | ||
"Host: myhost:10001", | ||
"X-Forwarded-For: 127.0.0.1:8888,127.0.0.2:9999", | ||
"X-Forwarded-Proto: https", | ||
"X-Forwarded-Host: sub1.example.com:10003", | ||
"X-Forwarded-Port: 10002", | ||
"X-Forwarded-Server: sub2.example.com" | ||
), | ||
new Expectations() | ||
.scheme("https").serverName("sub1.example.com").serverPort(10003) | ||
.requestURL("https://sub1.example.com:10003/") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto the port here should be 10002... in fact isn't that what the code already does? Wont the code at 👍 https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java#L662 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC, it resolves as ...
So the following headers ...
becomes in order ....
but the headers in a different order ...
Goes thru ...
Lets chat about the test cases tomm, I'll take a stab at fixing them in a more sane way (keeping iteration). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joakime the code has been explicitly designed to be order independent for host and port. That is why we have So specifically the outcome for:
should be no different from the outcome for:
My preference is for the explicit port header to always win, so the result will be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK part of the problem is here: public void handleFor(HttpField field)
{
String authority = getLeftMost(field.getValue());
if (!getForwardedPortAsAuthority() && !StringUtil.isEmpty(getForwardedPortHeader()))
{
if (_for == null)
_for = new PossiblyPartialHostPort(authority);
else if (_for instanceof PortSetHostPort)
_for = new HostPort(HostPort.normalizeHost(authority), _for.getPort());
}
else if (_for == null)
{
_for = new HostPort(authority);
}
} This code is not checking if in the case a But the code for the port header does the opposite: public void handlePort(HttpField field)
{
int port = HostPort.parsePort(getLeftMost(field.getValue()));
if (!getForwardedPortAsAuthority())
{
if (_for == null)
_for = new PortSetHostPort(_request.getRemoteHost(), port);
else if (_for instanceof PossiblyPartialHostPort && _for.getPort() <= 0)
_for = new HostPort(HostPort.normalizeHost(_for.getHost()), port);
}
else
{
if (_host == null)
_host = new PortSetHostPort(_request.getServerName(), port);
else if (_host instanceof PossiblyPartialHostPort && _host.getPort() <= 0)
_host = new HostPort(HostPort.normalizeHost(_host.getHost()), port);
}
} It is checking if there is actually a port set in the So you need to make the same policy decision in both places - either the port header has precedence or it doesn't - I guess I don't mind either way, we just need to be consistent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I opened Issue #5247, proposing a better way. |
||
.remoteAddr("127.0.0.1").remotePort(8888) | ||
), | ||
// ================================================================= | ||
// Mixed Behavior | ||
Arguments.of(new Request("RFC7239 mixed with X-Forwarded-* headers") | ||
|
@@ -585,7 +645,6 @@ public static Stream<Arguments> cases() | |
|
||
@ParameterizedTest(name = "{0}") | ||
@MethodSource("cases") | ||
@SuppressWarnings("unused") | ||
public void testDefaultBehavior(Request request, Expectations expectations) throws Exception | ||
{ | ||
request.configure(customizer); | ||
|
@@ -601,7 +660,6 @@ public void testDefaultBehavior(Request request, Expectations expectations) thro | |
|
||
@ParameterizedTest(name = "{0}") | ||
@MethodSource("cases") | ||
@SuppressWarnings("unused") | ||
public void testConfiguredBehavior(Request request, Expectations expectations) throws Exception | ||
{ | ||
request.configure(customizerConfigured); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree with this test. We should be order independent for such headers. If we decide that
X-Forwarded-Port
takes precedent over any port specified inX-Forwarded-Host
then it should do so regardless of the order of those headers!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code in ForwardedRequestCustomizer is most definitely order dependent, esp around host/port/authority. (IIRC, these are not the only tests that show this order dependency, i'll point out which other ones we have tomm.).
This order dependency was introduced when the code changed to iterating the fields from querying the fields.
If we want to change this code to not be order dependent, then we should go over all of the tests and expectations first, discuss them, then fix the code to conform to the expectations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened Issue #5247, proposing a better way.