Class ProxyProtocolHandler

java.lang.Object
io.netty.channel.ChannelHandlerAdapter
io.netty.channel.ChannelInboundHandlerAdapter
io.netty.handler.codec.ByteToMessageDecoder
google.registry.proxy.handler.ProxyProtocolHandler
All Implemented Interfaces:
io.netty.channel.ChannelHandler, io.netty.channel.ChannelInboundHandler

public class ProxyProtocolHandler extends io.netty.handler.codec.ByteToMessageDecoder
Handler that processes possible existence of a PROXY protocol v1 header.

When an EPP client connects to the registry (through the proxy), the registry performs two validations to ensure that only known registrars are allowed. First it checks the sha265 hash of the client SSL certificate and match it to the hash stored in the database for the registrar. It then checks if the connection is from an allow-listed IP address that belongs to that registrar.

The proxy receives client connects via the GCP load balancer, which results in the loss of original client IP from the channel. Luckily, the load balancer supports the PROXY protocol v1, which adds a header with source IP information, among other things, to the TCP request at the start of the connection.

This handler determines if a connection is proxied (PROXY protocol v1 header present) and correctly sets the source IP address to the channel's attribute regardless of whether it is proxied. After that it removes itself from the channel pipeline because the proxy header is only present at the beginning of the connection.

This handler must be the very first handler in a protocol, even before SSL handlers, because PROXY protocol header comes as the very first thing, even before SSL handshake request.

See Also:
  • Nested Class Summary

    Nested classes/interfaces inherited from class io.netty.handler.codec.ByteToMessageDecoder

    io.netty.handler.codec.ByteToMessageDecoder.Cumulator

    Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler

    io.netty.channel.ChannelHandler.Sharable
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final io.netty.util.AttributeKey<String>
    Key used to retrieve origin IP address from a channel's attribute.

    Fields inherited from class io.netty.handler.codec.ByteToMessageDecoder

    COMPOSITE_CUMULATOR, MERGE_CUMULATOR
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    channelRead(io.netty.channel.ChannelHandlerContext ctx, Object msg)
     
    protected void
    decode(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in, List<Object> out)
    Attempts to decode an internally accumulated buffer and find the proxy protocol header.

    Methods inherited from class io.netty.handler.codec.ByteToMessageDecoder

    actualReadableBytes, callDecode, channelInactive, channelReadComplete, decodeLast, discardSomeReadBytes, handlerRemoved, handlerRemoved0, internalBuffer, isSingleDecode, setCumulator, setDiscardAfterReads, setSingleDecode, userEventTriggered

    Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter

    channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught

    Methods inherited from class io.netty.channel.ChannelHandlerAdapter

    ensureNotSharable, handlerAdded, isSharable

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface io.netty.channel.ChannelHandler

    handlerAdded
  • Field Details

    • REMOTE_ADDRESS_KEY

      public static final io.netty.util.AttributeKey<String> REMOTE_ADDRESS_KEY
      Key used to retrieve origin IP address from a channel's attribute.
  • Method Details

    • channelRead

      public void channelRead(io.netty.channel.ChannelHandlerContext ctx, Object msg) throws Exception
      Specified by:
      channelRead in interface io.netty.channel.ChannelInboundHandler
      Overrides:
      channelRead in class io.netty.handler.codec.ByteToMessageDecoder
      Throws:
      Exception
    • decode

      protected void decode(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in, List<Object> out)
      Attempts to decode an internally accumulated buffer and find the proxy protocol header.

      When the connection is not proxied (i. e. the initial bytes are not "PROXY"), simply set finished to true and allow the handler to be removed. Otherwise the handler waits until there's enough bytes to parse the header, save the parsed header to proxyHeader, and then mark finished.

      Specified by:
      decode in class io.netty.handler.codec.ByteToMessageDecoder
      Parameters:
      in - internally accumulated buffer, newly arrived bytes are appended to it.
      out - objects passed to the next handler, in this case nothing is ever passed because the header itself is processed and written to the attribute of the proxy, and the handler is then removed from the pipeline.