spring-cloud/spring-cloud-gateway

No X-Forwarded-For (RemoteIP) header is written due to incompatibility between XForwardedHeadersFilter and ForwardedHeadersTransformer

Open

#2,648 opened on Jun 22, 2022

View on GitHub
 (7 comments) (0 reactions) (0 assignees)Java (4,284 stars) (3,204 forks)batch import
bughelp wanted

Description

Describe the bug If ForwardedHeaderTransformer is enabled in Spring Cloud Gateway, X-Forwarded-For Header will not be sent to upstream services

Steps to reproduce

  • Enable ForwardedHeaderTransformer in Spring Cloud Gateway by setting: server.forward-headers-strategy=framework
  • Setup some upstream service to which the gateway fowards requests.
  • Use a REST client to send some request to the upstream service via gateway. Set the X-Forwarded-For header in the request.
  • Watch the request going to the upstream service. It has no X-Forwarded-For header.
  • Other headers, like X-Forwarded-Host will work.

Debugging

Since a while, ForwardedHeaderTransformer in Spring Boot supports X-Forwarded-For header:

remoteAddress = UriComponentsBuilder.parseForwardedFor(request, remoteAddress);

In UriComponentsBuilder.parseForwardedFor, the address is build as following:

return InetSocketAddress.createUnresolved(host, port);

However, in Spring Cloud Gateway, we have the following in XForwardedHeadersFilter:

if (isForEnabled() && request.getRemoteAddress() != null
				&& request.getRemoteAddress().getAddress() != null) {
			String remoteAddr = request.getRemoteAddress().getAddress().getHostAddress();
			write(updated, X_FORWARDED_FOR_HEADER, remoteAddr, isForAppend());
		}

Debugging shows, that request.getRemoteAddress().getAddress() is null and so, no X-Fowarded-For Header is written. I guess that is due to the InetSocketAddress.createUnresolved in UriComponentsBuilder.

I don't know whether ForwardedHeaderTransformer / UriComponentsBuilder or XForwardedHeadersFilter is wrong here, but together, they fail.

P.S.: createUnresolved seems to be intentionally, to avoid DNS resolution. See https://github.com/spring-projects/spring-framework/commit/c5ac8e8ab62cf7a616d5316bc6ef6d5d5e461c10 So, it would probably be the best solution if XForwardedHeadersFilter could (also) deal with an unresolved remote address.

Contributor guide