spring-cloud / spring-cloud/spring-cloud-gateway
No X-Forwarded-For (RemoteIP) header is written due to incompatibility between XForwardedHeadersFilter and ForwardedHeadersTransformer
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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