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().
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
ServerHttpRequestis often already overwritten to the client IP fromX-Forwarded-For(or from theForwardedheader), 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.
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
So by the time
XForwardedHeadersFilterruns,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().