1818
1919import com .google .common .base .Splitter ;
2020import com .google .common .base .Strings ;
21+ import com .google .common .collect .Iterators ;
2122import com .google .common .collect .Lists ;
2223import com .google .common .net .InetAddresses ;
2324import io .netty .channel .ChannelHandlerContext ;
2425import io .netty .channel .SimpleChannelInboundHandler ;
2526import io .netty .handler .codec .http .FullHttpRequest ;
2627import io .netty .handler .codec .http .HttpHeaders ;
27- import io .netty .handler .codec .http .HttpRequest ;
28- import io .netty .util .ReferenceCountUtil ;
2928import org .graylog2 .utilities .IpSubnet ;
3029import org .slf4j .Logger ;
3130import org .slf4j .LoggerFactory ;
3231
32+ import javax .annotation .Nullable ;
3333import java .net .InetAddress ;
3434import java .net .InetSocketAddress ;
3535import 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