Introduction to Capturing Client Information in AWS EKS

Capturing client IP information becomes challenging when deploying applications on AWS EKS (Elastic Kubernetes Service) behind a Network Load Balancer (NLB). This is especially true for TCP connections, where headers aren’t typically accessible. Proxy Protocol V2 comes to the rescue by allowing us to retrieve this client data. By implementing Proxy Protocol V2, we can capture and utilize client details such as IP addresses and ports, which are vital for monitoring, logging, and security purposes.

In this guide, we’ll walk through setting up Proxy Protocol V2 with a TCP server on AWS EKS, parsing the Proxy Protocol V2 headers in Java, and implementing sample Java code for handling and parsing these headers.

Prerequisites for Implementing Proxy Protocol V2

To implement Proxy Protocol V2 with AWS EKS, you will need:

  1. AWS Account with EKS Permissions – Set up an EKS cluster with appropriate permissions.
  2. Network Load Balancer (NLB) – Ensure your NLB is configured to work with the EKS service and supports Proxy Protocol V2.
  3. Java Development Environment – You’ll need Java and a compatible IDE to develop the TCP server code.
  4. AWS CLI and Kubectl – Ensure these tools are installed and configured to manage your AWS resources and Kubernetes clusters.

Enabling Proxy Protocol V2 in AWS Network Load Balancer

AWS Network Load Balancers support Proxy Protocol V2, which allows the NLB to send client connection information to backend services. To enable Proxy Protocol V2:

  1. Create or Modify an NLB – Go to the AWS Management Console, select your NLB, and navigate to the Listeners section.
  2. Enable Proxy Protocol V2 – For each listener, add a policy that enables Proxy Protocol V2. This can also be done using the AWS CLI:
    aws elbv2 modify-load-balancer-attributes \

  –load-balancer-arn <your-nlb-arn> \

  –attributes Key=proxy_protocol_v2.enabled,Value=true

Java Implementation for Parsing Proxy Protocol V2 Headers

Proxy Protocol V2 encapsulates client information in a binary format. You’ll need to parse the binary data in your Java application to capture these headers.

Sample Java TCP Server Code for Handling Proxy Protocol V2

Here is a sample Java TCP server that listens for connections from an NLB with Proxy Protocol V2 enabled. This server captures and parses client information:

import java.io.InputStream;

import java.net.ServerSocket;

import java.net.Socket;

import java.nio.ByteBuffer;

import java.nio.charset.StandardCharsets;

public class ProxyProtocolV2Server {

    

    private static final int PORT = 8080;

    public static void main(String[] args) throws Exception {

        try (ServerSocket serverSocket = new ServerSocket(PORT)) {

            System.out.println(“Server is listening on port ” + PORT);

            

            while (true) {

                Socket socket = serverSocket.accept();

                System.out.println(“New client connected”);

                InputStream input = socket.getInputStream();

                handleClient(input);

                socket.close();

            }

        }

    }

    private static void handleClient(InputStream input) throws Exception {

        byte[] proxyHeader = new byte[16];

        input.read(proxyHeader);

        if (isValidProxyProtocolHeader(proxyHeader)) {

            ByteBuffer buffer = ByteBuffer.wrap(proxyHeader);

            parseProxyProtocolHeader(buffer);

        }

    }

    private static boolean isValidProxyProtocolHeader(byte[] header) {

        String signature = new String(header, 0, 12, StandardCharsets.UTF_8);

        return “PROXY”.equals(signature);

    }

    private static void parseProxyProtocolHeader(ByteBuffer buffer) {

        buffer.position(12);

        byte familyAndProtocol = buffer.get();

        byte srcAddress[] = new byte[4];

        byte destAddress[] = new byte[4];

        buffer.get(srcAddress);

        buffer.get(destAddress);

        

        System.out.printf(“Client IP: %d.%d.%d.%d\n”, srcAddress[0] & 0xFF, srcAddress[1] & 0xFF, srcAddress[2] & 0xFF, srcAddress[3] & 0xFF);

    }

}

Explanation of the Java Code for Parsing Proxy Protocol Headers

The code above does the following:

  1. Server Setup: The server listens on port 8080, accepting incoming connections.
  2. Reading Proxy Protocol Header: It reads the initial bytes of each connection, which contain the Proxy Protocol V2 header.
  3. Validating Header: The isValidProxyProtocolHeader() method checks the initial bytes to ensure they match the Proxy Protocol V2 signature.
  4. Parsing Header Data: The parseProxyProtocolHeader() method extracts client details from the header, including IP addresses and ports.

Additional Considerations for Using Proxy Protocol V2

  • Compatibility: Ensure your application server and other backend services are configured to support Proxy Protocol V2.
  • Security: Always validate headers carefully, as this approach could expose client IP addresses.
  • Load Testing: Proxy Protocol V2 introduces additional overhead; test your setup under various loads to verify performance.

References

Preserving client IP address with Proxy protocol v2 and Network Load Balancer

How do I capture client IP addresses in the web server logs behind an elastic load balancer?