Closed
Description
Hi,
I see a problem with IPv6 remote addresses and the org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilter.
When a remote address is in IPv6 format then in the Forwarded header I miss the '[' and ']' around the IPv6 address (see https://tools.ietf.org/html/rfc7239).
Example:
For '2001:db8:cafe:0:0:0:0:17' and port 4711 the result header should include 'for="[2001:db8:cafe:0:0:0:0:17]:4711"' but I see only 'for="2001:db8:cafe:0:0:0:0:17:4711"' (missing '[' and ']' around the IPv6 address).
Possible test:
public class ForwardedHeadersFilterTests {
...
@Test
public void correctIPv6RemoteAddressMapping() throws UnknownHostException {
MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost/get")
.remoteAddress(new InetSocketAddress(InetAddress.getByName("2001:db8:cafe:0:0:0:0:17"), 80))
.header(HttpHeaders.HOST, "myhost").build();
ForwardedHeadersFilter filter = new ForwardedHeadersFilter();
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers.get(FORWARDED_HEADER)).hasSize(1);
List<Forwarded> forwardeds = ForwardedHeadersFilter.parse(headers.get(FORWARDED_HEADER));
assertThat(forwardeds).hasSize(1);
Forwarded forwarded = forwardeds.get(0);
assertThat(forwarded.getValues()).containsEntry("for", "\"[2001:db8:cafe:0:0:0:0:17]:80\"");
}
Possible fix:
public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered {
...
@Override
public HttpHeaders filter(HttpHeaders input, ServerWebExchange exchange) {
...
URI uri = request.getURI();
String host = original.getFirst(HttpHeaders.HOST);
Forwarded forwarded = new Forwarded().put("host", host).put("proto", uri.getScheme());
InetSocketAddress remoteAddress = request.getRemoteAddress();
if (remoteAddress != null) {
// If remoteAddress is unresolved, calling getHostAddress() would cause a
// NullPointerException.
String forValue;
if (remoteAddress.isUnresolved()) {
forValue = remoteAddress.getHostName();
} else {
InetAddress address = remoteAddress.getAddress();
forValue = remoteAddress.getAddress().getHostAddress();
if (address instanceof Inet6Address) {
forValue = "[" + forValue + "]";
}
}
int port = remoteAddress.getPort();
if (port >= 0) {
forValue = forValue + ":" + port;
}
forwarded.put("for", forValue);
}
// TODO: support by?
updated.add(FORWARDED_HEADER, forwarded.toHeaderValue());
return updated;
}
Thanks!