mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 16:07:15 +02:00
Handle malformed proxy protocol header
If the proxy protocol header contains a malformatted string, such as "PROXY UNKNOWN", instead of throwing and killing the connection, use the TCP source IP as the remote IP. Also changed how the header is read from the buffer, to avoid a potential Netty resource leak. Originally the header is read into another ByteBuf, which needs be be explicit released in order for Netty to reclaim its memory (http://netty.io/wiki/reference-counted-objects.html). Now we just read it into a byte array and let JVM GC it. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=188047084
This commit is contained in:
parent
b39e6c0d7e
commit
00bf8a999f
2 changed files with 47 additions and 8 deletions
|
@ -17,6 +17,7 @@ package google.registry.proxy.handler;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
import google.registry.util.FormattingLogger;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
@ -55,6 +56,8 @@ public class ProxyProtocolHandler extends ByteToMessageDecoder {
|
|||
public static final AttributeKey<String> REMOTE_ADDRESS_KEY =
|
||||
AttributeKey.valueOf("REMOTE_ADDRESS_KEY");
|
||||
|
||||
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
|
||||
|
||||
// The proxy header must start with this prefix.
|
||||
// Sample header: "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n".
|
||||
private static final byte[] HEADER_PREFIX = "PROXY".getBytes(US_ASCII);
|
||||
|
@ -69,20 +72,40 @@ public class ProxyProtocolHandler extends ByteToMessageDecoder {
|
|||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
super.channelRead(ctx, msg);
|
||||
if (finished) {
|
||||
String remoteIP;
|
||||
if (proxyHeader != null) {
|
||||
ctx.channel().attr(REMOTE_ADDRESS_KEY).set(proxyHeader.split(" ")[2]);
|
||||
} else {
|
||||
SocketAddress remoteAddress = ctx.channel().remoteAddress();
|
||||
if (remoteAddress instanceof InetSocketAddress) {
|
||||
ctx.channel()
|
||||
.attr(REMOTE_ADDRESS_KEY)
|
||||
.set(((InetSocketAddress) remoteAddress).getAddress().getHostAddress());
|
||||
logger.finefmt("PROXIED CONNECTION: %s", ctx.channel());
|
||||
logger.finefmt("PROXY HEADER: %s", proxyHeader);
|
||||
String[] headerArray = proxyHeader.split(" ", -1);
|
||||
if (headerArray.length == 6) {
|
||||
remoteIP = headerArray[2];
|
||||
logger.finefmt("Header parsed, using %s as remote IP.", remoteIP);
|
||||
} else {
|
||||
logger.finefmt("Cannot parse the header, use source IP as a last resort.");
|
||||
remoteIP = getSourceIP(ctx);
|
||||
}
|
||||
} else {
|
||||
logger.finefmt("No header present, using source IP directly.");
|
||||
remoteIP = getSourceIP(ctx);
|
||||
}
|
||||
if (remoteIP != null) {
|
||||
ctx.channel().attr(REMOTE_ADDRESS_KEY).set(remoteIP);
|
||||
} else {
|
||||
logger.warningfmt("Not able to obtain remote IP for %s", ctx.channel());
|
||||
}
|
||||
// ByteToMessageDecoder automatically flushes unread bytes in the ByteBuf to the next handler
|
||||
// when itself is being removed.
|
||||
ctx.pipeline().remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSourceIP(ChannelHandlerContext ctx) {
|
||||
SocketAddress remoteAddress = ctx.channel().remoteAddress();
|
||||
return (remoteAddress instanceof InetSocketAddress)
|
||||
? ((InetSocketAddress) remoteAddress).getAddress().getHostAddress()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to decode an internally accumulated buffer and find the proxy protocol header.
|
||||
*
|
||||
|
@ -115,7 +138,9 @@ public class ProxyProtocolHandler extends ByteToMessageDecoder {
|
|||
if (eol >= 0) {
|
||||
// ByteBuf.readBytes is called so that the header is processed and not passed to handlers
|
||||
// further in the pipeline.
|
||||
proxyHeader = in.readBytes(eol).toString(US_ASCII);
|
||||
byte[] headerBytes = new byte[eol];
|
||||
in.readBytes(headerBytes);
|
||||
proxyHeader = new String(headerBytes, US_ASCII);
|
||||
// Skip \r\n.
|
||||
in.skipBytes(2);
|
||||
// Proxy header processed, mark finished so that this handler is removed.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue