Skip to content

Commit

Permalink
Update RemoteAddrRoutePredicateFactory to optionally respect the `X…
Browse files Browse the repository at this point in the history
…-Forwarded-For` header. Fixes spring-cloudgh-155.
  • Loading branch information
fitzoh committed Feb 14, 2018
1 parent 2797834 commit 5a11f8d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.handler.support.RoutePredicateFactoryUtils;
import org.springframework.tuple.Tuple;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
Expand All @@ -48,7 +50,7 @@ public Predicate<ServerWebExchange> apply(Tuple args) {
addSource(sources, (String) arg);
}
}
return apply(sources);
return apply(sources, false);
}

public Predicate<ServerWebExchange> apply(String... addrs) {
Expand All @@ -58,13 +60,23 @@ public Predicate<ServerWebExchange> apply(String... addrs) {
for (String addr : addrs) {
addSource(sources, addr);
}
return apply(sources);
return apply(sources, false);
}

public Predicate<ServerWebExchange> apply(List<IpSubnetFilterRule> sources) {
/**
* @param respectForwardedHeader whether to check the `X-Forwarded-For` header for the
* remote IP address.
*/
public Predicate<ServerWebExchange> apply(List<IpSubnetFilterRule> sources,
boolean respectForwardedHeader) {
Function<ServerWebExchange, InetSocketAddress> remoteIpResolver = respectForwardedHeader
? RoutePredicateFactoryUtils::parseRemoteIpRespectingForwardedHeader
: RoutePredicateFactoryUtils::parseRemoteIpIgnoringForwardedHeader;

return exchange -> {
InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
InetSocketAddress remoteAddress = remoteIpResolver.apply(exchange);
if (remoteAddress != null) {

String hostAddress = remoteAddress.getAddress().getHostAddress();
String host = exchange.getRequest().getURI().getHost();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@

package org.springframework.cloud.gateway.handler.support;

import java.net.InetSocketAddress;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.web.server.ServerWebExchange;

/**
* @author Spencer Gibb
* @author Andrew Fitzgerald
*/
public class RoutePredicateFactoryUtils {

public static final String X_FORWARDED_FOR = "X-Forwarded-For";

private static final Log logger = LogFactory.getLog(RoutePredicateFactory.class);

public static void traceMatch(String prefix, Object desired, Object actual, boolean match) {
Expand All @@ -34,4 +42,19 @@ public static void traceMatch(String prefix, Object desired, Object actual, bool
logger.trace(message);
}
}


public static InetSocketAddress parseRemoteIpRespectingForwardedHeader(ServerWebExchange exchange) {
List<String> xForwardedValues = exchange.getRequest().getHeaders().get(X_FORWARDED_FOR);
if (xForwardedValues != null && xForwardedValues.size() != 0) {
String remoteAddress = xForwardedValues.get(0).split(", ")[0];
return InetSocketAddress.createUnresolved(remoteAddress, 0);
}
return parseRemoteIpIgnoringForwardedHeader(exchange);
}

public static InetSocketAddress parseRemoteIpIgnoringForwardedHeader(ServerWebExchange exchange) {
return exchange.getRequest().getRemoteAddress();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.springframework.cloud.gateway.handler.support;

import static org.assertj.core.api.Assertions.assertThat;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

import org.junit.Test;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;

public class RoutePredicateFactoryUtilsTest {

private final InetSocketAddress remote0000Addres = InetSocketAddress.createUnresolved("0.0.0.0", 1234);
}

@Test
public void parseRemoteIpPrioritizesFirstForwardedIp() {
MockServerHttpRequest request = MockServerHttpRequest.get("someUrl")
.remoteAddress(remote0000Addres)
.header("X-Forwarded-For", "0.0.0.1, 0.0.0.2, 0.0.0.3").build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
InetSocketAddress actualIp = RoutePredicateFactoryUtils
.parseRemoteIpRespectingForwardedHeader(exchange);

assertThat(actualIp.getHostName()).isEqualTo("0.0.0.1");
}

@Test
public void parseRemoteIpFallsBackToRemoteIp() {
MockServerHttpRequest request = MockServerHttpRequest.get("someUrl")
.remoteAddress(remote0000Addres).build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
InetSocketAddress actualIp = RoutePredicateFactoryUtils
.parseRemoteIpRespectingForwardedHeader(exchange);

assertThat(actualIp.getHostName()).isEqualTo("0.0.0.0");
}

@Test
public void parseRemoteIpReturnsNullIfNoForwardedOrRemoteIp() {
MockServerHttpRequest request = MockServerHttpRequest.get("someUrl").build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
InetSocketAddress actualIp = RoutePredicateFactoryUtils
.parseRemoteIpRespectingForwardedHeader(exchange);

assertThat(actualIp).isEqualTo(null);
}
}

0 comments on commit 5a11f8d

Please sign in to comment.