Skip to content

X-Forwarded-Port is sometimes ignored #2751

Closed
@rickie

Description

@rickie

Expected Behavior

It is expected that reactor-netty always honors the provided X-Forwarded-Port when calling HttpServerRequest#hostPort.

Actual Behavior

The problem is that reactor-netty does not honor the X-Forwarded-Port header if X-Forwarded-Host isn’t set, and thus it can report the port of a proxied connection rather than the actual (forwarded) host port.

As a result, reactor-netty incorrectly reports port 80, while the scheme is https and X-Forwarded-Port is set. This becomes a problem in our setup which is as follows:

We have AWS Application Load Balancers (ALBs) which perform TLS termination and proxy requests to pods running within our Kubernetes clusters. ALBs only add the following headers to a proxied request, as per the documentation:

  • X-Forwarded-For
  • X-Forwarded-Proto
  • X-Forwarded-Port

In addition, the Host header is set by the original request. However, when we call HttpServerRequest#hostPort for a request that requests a URL of the format https://some-host.domain, we would expect hostPort to return 443. Instead, it returns 80.

The following issue may be related: #2714.
This became a problem in combination with the following commit from Spring framework: spring-projects/spring-framework@a2b7a90, where they (correctly) prefer the host address rather than parsing the Host header themselves.

Steps to Reproduce

@Test
void xForwardedForAndHost() {
	testClientRequest(
			clientRequestHeaders -> {
				clientRequestHeaders.add("Host", "a.example.com");
				clientRequestHeaders.add("X-Forwarded-For", "192.168.0.1");
				clientRequestHeaders.add("X-Forwarded-Port", "443");
				clientRequestHeaders.add("X-Forwarded-Proto", "https");
			},
			serverRequest -> {
				Assertions.assertThat(serverRequest.hostPort()).isEqualTo(443);
				Assertions.assertThat(serverRequest.hostName()).isEqualTo("a.example.com");
				Assertions.assertThat(serverRequest.scheme()).isEqualTo("https");
			});
}

This test fails as the port returned is 80 instead of 443.

Possible Solution

Adding the following line results in the expected result:

clientRequestHeaders.add("X-Forwarded-Host", "a.example.com");

Your Environment

  • Reactor version(s) used: 2020.0.30, we use the reactor-bom.
  • Other relevant libraries versions (eg. netty, ...): Netty 1.0.30.
  • JVM version (java -version):
$ java -version
openjdk version "17.0.3" 2022-04-19 LTS
OpenJDK Runtime Environment Zulu17.34+19-CA (build 17.0.3+7-LTS)
OpenJDK 64-Bit Server VM Zulu17.34+19-CA (build 17.0.3+7-LTS, mixed mode, sharing)
  • OS and version (eg. uname -a):
$ uname -a
Linux rick-ommitted 5.15.0-67-generic #74~20.04.1-Ubuntu SMP Wed Feb 22 14:52:34 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions