spring-cloud / spring-cloud/spring-cloud-gateway

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

Open
#2,648 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug help wanted
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with XForwardedHeadersFilter and trace how ForwardedHeaderTransformer and UriComponentsBuilder.parseForwardedFor produce the remote address when server.forward-headers-strategy=framework is enabled. Reproduce the request through the gateway with X-Forwarded-For set, then verify that the upstream request preserves X-Forwarded-For while the other forwarded headers continue to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, backend, networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.