Skip to content

Commit d91023c

Browse files
committed
also check channel remote address if we valid trusted proxies, some proxies don't include themselves in the forwarded-for list
1 parent c149e2b commit d91023c

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

graylog2-server/src/main/java/org/graylog2/inputs/transports/netty/HttpForwardedForHandler.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@
1818

1919
import com.google.common.base.Splitter;
2020
import com.google.common.base.Strings;
21+
import com.google.common.collect.Iterators;
2122
import com.google.common.collect.Lists;
2223
import com.google.common.net.InetAddresses;
2324
import io.netty.channel.ChannelHandlerContext;
2425
import io.netty.channel.SimpleChannelInboundHandler;
2526
import io.netty.handler.codec.http.FullHttpRequest;
2627
import io.netty.handler.codec.http.HttpHeaders;
27-
import io.netty.handler.codec.http.HttpRequest;
28-
import io.netty.util.ReferenceCountUtil;
2928
import org.graylog2.utilities.IpSubnet;
3029
import org.slf4j.Logger;
3130
import org.slf4j.LoggerFactory;
3231

32+
import javax.annotation.Nullable;
3333
import java.net.InetAddress;
3434
import java.net.InetSocketAddress;
3535
import java.net.UnknownHostException;
@@ -102,7 +102,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) thro
102102
}
103103
}
104104
if (!ipChain.isEmpty()) {
105-
final Optional<String> candidate = findOriginalIpAndCheckProxies(ipChain);
105+
final Optional<String> candidate = findOriginalIpAndCheckProxies(ipChain, getPeerAddress(ctx));
106106
if (candidate.isPresent()) {
107107
originalIp = candidate.get();
108108
LOG.debug("Found original IP address in X-Forwarded-For header: {}", originalIp);
@@ -125,7 +125,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) thro
125125
}
126126
}
127127
if (!forValues.isEmpty()) {
128-
final Optional<String> candidate = findOriginalIpAndCheckProxies(forValues);
128+
final Optional<String> candidate = findOriginalIpAndCheckProxies(forValues, getPeerAddress(ctx));
129129
if (candidate.isPresent()) {
130130
originalIp = candidate.get();
131131
LOG.debug("Found original IP address in Forwarded header: {}", originalIp);
@@ -163,7 +163,15 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) thro
163163
ctx.fireChannelRead(msg.retain());
164164
}
165165

166-
private Optional<String> findOriginalIpAndCheckProxies(List<String> ipChain) throws UnknownHostException {
166+
// in tests the remote address won't be a real InetSocketAddress
167+
@Nullable
168+
private static String getPeerAddress(ChannelHandlerContext ctx) {
169+
if (ctx.channel().remoteAddress() instanceof InetSocketAddress)
170+
return ((InetSocketAddress) ctx.channel().remoteAddress()).getHostString();
171+
return null;
172+
}
173+
174+
private Optional<String> findOriginalIpAndCheckProxies(List<String> ipChain, @Nullable String peerAddress) throws UnknownHostException {
167175
Iterator<String> iterator = ipChain.iterator();
168176
String candidate = iterator.next();
169177
if (requireTrustedProxies) {
@@ -173,12 +181,17 @@ private Optional<String> findOriginalIpAndCheckProxies(List<String> ipChain) thr
173181
return Optional.empty();
174182
} else {
175183
if (!iterator.hasNext()) {
176-
LOG.debug("Forwarded-For list only contains a single entry, cannot check relaying proxy addresses.");
184+
LOG.debug("Forwarded-For list only contains a single entry, cannot use it for checking addresses, also checking peer address: {}", peerAddress);
185+
}
186+
Iterator<String> listAndPeer = iterator;
187+
// add the peer address if we have one (might be null in tests)
188+
if (peerAddress != null) {
189+
listAndPeer = Iterators.concat(iterator, Iterators.singletonIterator(peerAddress));
177190
}
178191
// go through the remainder of the list, which should all be proxy addresses we trust
179192
// if we hit one that we don't trust, bail out and don't use the candidate IP
180-
while (iterator.hasNext()) {
181-
final String proxyIp = iterator.next();
193+
while (listAndPeer.hasNext()) {
194+
final String proxyIp = listAndPeer.next();
182195
boolean trusted = false;
183196
for (final IpSubnet subnet : trustedProxies) {
184197
if (subnet.contains(proxyIp)) {

0 commit comments

Comments
 (0)