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

XForwardedHeadersFilter uses wrong remote address for trusted-proxies check

Open
#4,074 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

The org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter uses request.getRemoteAddress() to match with the trustedProxies. This incorrect, because getRemoteAddress() returns something you didn't expect.

Problem:
When the gateway is behind a proxy (e.g. in a cloud), the remote address visible on ServerHttpRequest is often already overwritten to the client IP from X-Forwarded-For (or from the Forwarded header), so it is not the nearest proxy. That overwriting, depends on forward-headers-strategy configuration, can happen in:

  • DefaultNettyHttpForwardedHeaderHandler, which in turn uses parseXForwardedInfo / parseForwardedInfo and overwrites the connection’s remote address with the left-most (client) IP from the XFF header.

    left-most ip from XFF it is a client ip according to the https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For
    X-Forwarded-For: client, proxy, …, proxyN

  • org.springframework.web.server.adapter.ForwardedHeaderTransformer, which is uses ForwardedHeaderUtils to parse left-most ip from the XFF header and sets as a remote address

       * Parse the first "Forwarded: for=..." or "X-Forwarded-For" header value to
       * an {@code InetSocketAddress} representing the address of the client.
      remoteAddress = ForwardedHeaderUtils.parseForwardedFor(originalUri, headers, remoteAddress);
      if (remoteAddress != null) {
          	builder.remoteAddress(remoteAddress);
      }
      
    

So by the time XForwardedHeadersFilter runs, request.getRemoteAddress() is often the client IP, not the nearest proxy. Using it for “is the direct peer trusted?” is incorrect.

Solution:

We could get the real remote (peer) address using ServerHttpRequestDecorator.getNativeRequest(request).getRemoteAddress().

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 by reading org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter and trace how request.getRemoteAddress() is populated by the forwarded-header handlers described in the issue. Compare that value with the native request address obtained through ServerHttpRequestDecorator. Done means the trusted-proxies check uses the nearest peer address rather than the transformed client address, with behavior verified for a gateway behind a proxy.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.