Remove X-Forwarded-For from RemoteAddressFilter

This commit is contained in:
Chris Eager
2024-04-10 17:40:55 -05:00
committed by Chris Eager
parent 39fd955f13
commit 05a92494bb
10 changed files with 59 additions and 161 deletions

View File

@@ -332,10 +332,6 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
MetricsUtil.configureRegistries(config, environment, dynamicConfigurationManager);
final boolean useRemoteAddress = Optional.ofNullable(
System.getenv("SIGNAL_USE_REMOTE_ADDRESS"))
.isPresent();
if (config.getServerFactory() instanceof DefaultServerFactory defaultServerFactory) {
defaultServerFactory.getApplicationConnectors()
.forEach(connectorFactory -> {
@@ -823,7 +819,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
final List<Filter> filters = new ArrayList<>();
filters.add(remoteDeprecationFilter);
filters.add(new RemoteAddressFilter(useRemoteAddress));
filters.add(new RemoteAddressFilter());
for (Filter filter : filters) {
environment.servlets()

View File

@@ -6,15 +6,12 @@
package org.whispersystems.textsecuregcm.filters;
import java.io.IOException;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.util.HttpServletRequestUtil;
@@ -22,19 +19,15 @@ import org.whispersystems.textsecuregcm.util.HttpServletRequestUtil;
/**
* Sets a {@link HttpServletRequest} attribute (that will also be available as a
* {@link javax.ws.rs.container.ContainerRequestContext} property) with the remote address of the connection, using
* either the {@link HttpServletRequest#getRemoteAddr()} or the {@code X-Forwarded-For} HTTP header value, depending on
* whether {@link #preferRemoteAddress} is {@code true}.
* {@link HttpServletRequest#getRemoteAddr()}.
*/
public class RemoteAddressFilter implements Filter {
public static final String REMOTE_ADDRESS_ATTRIBUTE_NAME = RemoteAddressFilter.class.getName() + ".remoteAddress";
private static final Logger logger = LoggerFactory.getLogger(RemoteAddressFilter.class);
private final boolean preferRemoteAddress;
public RemoteAddressFilter(boolean preferRemoteAddress) {
this.preferRemoteAddress = preferRemoteAddress;
public RemoteAddressFilter() {
}
@Override
@@ -43,16 +36,7 @@ public class RemoteAddressFilter implements Filter {
if (request instanceof HttpServletRequest httpServletRequest) {
final String remoteAddress;
if (preferRemoteAddress) {
remoteAddress = HttpServletRequestUtil.getRemoteAddress(httpServletRequest);
} else {
final String forwardedFor = httpServletRequest.getHeader(com.google.common.net.HttpHeaders.X_FORWARDED_FOR);
remoteAddress = getMostRecentProxy(forwardedFor)
.orElseGet(() -> HttpServletRequestUtil.getRemoteAddress(httpServletRequest));
}
final String remoteAddress = HttpServletRequestUtil.getRemoteAddress(httpServletRequest);
request.setAttribute(REMOTE_ADDRESS_ATTRIBUTE_NAME, remoteAddress);
} else {
@@ -62,23 +46,4 @@ public class RemoteAddressFilter implements Filter {
chain.doFilter(request, response);
}
/**
* Returns the most recent proxy in a chain described by an {@code X-Forwarded-For} header.
*
* @param forwardedFor the value of an X-Forwarded-For header
* @return the IP address of the most recent proxy in the forwarding chain, or empty if none was found or
* {@code forwardedFor} was null
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For">X-Forwarded-For - HTTP |
* MDN</a>
*/
public static Optional<String> getMostRecentProxy(@Nullable final String forwardedFor) {
return Optional.ofNullable(forwardedFor)
.map(ff -> {
final int idx = forwardedFor.lastIndexOf(',') + 1;
return idx < forwardedFor.length()
? forwardedFor.substring(idx).trim()
: null;
})
.filter(StringUtils::isNotBlank);
}
}

View File

@@ -15,10 +15,11 @@ import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.filters.RemoteAddressFilter;
import org.whispersystems.textsecuregcm.storage.ClientPublicKeysManager;
/**
@@ -113,7 +114,7 @@ class WebsocketHandshakeCompleteHandler extends ChannelInboundHandlerAdapter {
if (trustForwardedFor && handshakeCompleteEvent.requestHeaders().contains(FORWARDED_FOR_HEADER)) {
final String forwardedFor = handshakeCompleteEvent.requestHeaders().get(FORWARDED_FOR_HEADER);
return RemoteAddressFilter.getMostRecentProxy(forwardedFor).map(mostRecentProxy -> {
return getMostRecentProxy(forwardedFor).map(mostRecentProxy -> {
try {
return InetAddresses.forString(mostRecentProxy);
} catch (final IllegalArgumentException e) {
@@ -131,4 +132,25 @@ class WebsocketHandshakeCompleteHandler extends ChannelInboundHandlerAdapter {
}
}
}
/**
* Returns the most recent proxy in a chain described by an {@code X-Forwarded-For} header.
*
* @param forwardedFor the value of an X-Forwarded-For header
* @return the IP address of the most recent proxy in the forwarding chain, or empty if none was found or
* {@code forwardedFor} was null
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For">X-Forwarded-For - HTTP |
* MDN</a>
*/
@VisibleForTesting
static Optional<String> getMostRecentProxy(@Nullable final String forwardedFor) {
return Optional.ofNullable(forwardedFor)
.map(ff -> {
final int idx = forwardedFor.lastIndexOf(',') + 1;
return idx < forwardedFor.length()
? forwardedFor.substring(idx).trim()
: null;
})
.filter(StringUtils::isNotBlank);
}
}