PROXY Protocol Support

How to configure PROXY protocol v2 support in Radiator Server to preserve original client IP addresses when using load balancers like HAProxy or AWS NLB.

PROXY Protocol Support

Radiator Server supports the PROXY protocol (version 2) for preserving client IP addresses when connections are proxied through load balancers like HAProxy, AWS Network Load Balancer, or other TCP proxies.

Overview

When RADIUS connections (TCP or UDP) pass through a load balancer or proxy, the server sees the proxy's IP address instead of the original client's IP address. The PROXY protocol solves this by prepending connection metadata that includes the original client's IP address and port.

Radiator implements PROXY protocol v2, which provides:

  • Binary format for efficient parsing
  • Support for IPv4 and IPv6 addresses
  • Minimal overhead on connection establishment

Note: PROXY protocol v1 is not supported. Version 1 uses a text-based format which is less efficient to parse and more error-prone than the binary v2 format. All modern load balancers and proxies support v2.

Configuration

Enable PROXY protocol in your server listen configuration by adding proxy-protocol v2 in the listen block:

servers {
    radius "RADIUS_TCP_1812" {
        listen {
            protocol tcp;
            port 1812;
            ip 0.0.0.0;
            proxy-protocol v2;
            ip-accept "ACCEPT_PROXIES";
        }
        clients "CLIENTS_RADIUS_ALL";
    }
}

For UDP:

servers {
    radius "RADIUS_UDP_1812" {
        listen {
            protocol udp;
            port 1812;
            ip 0.0.0.0;
            proxy-protocol v2;
            ip-accept "ACCEPT_PROXIES";
        }
        clients "CLIENTS_RADIUS_ALL";
    }
}

Important UDP Behavior: With UDP and PROXY protocol, response packets are sent directly back to the original client IP (extracted from the PROXY header), not back through the proxy. This requires that the Radiator server has a direct route to the client network. For scenarios where responses must flow back through the proxy, use TCP instead.

Connection Flow

The following diagram shows how an incoming RADIUS connection is processed with PROXY protocol enabled:

Note: For TLS connections (RadSec), the TLS handshake occurs after IP-Accept but before PROXY protocol parsing, as the PROXY header is transmitted inside the TLS tunnel.

How It Works

1. IP-Accept Pre-admission Check

Before processing the PROXY protocol header, Radiator checks the direct peer address (the load balancer's IP) against the ip-accept list. This provides an additional security layer ensuring only trusted proxies can connect.

If the proxy's IP is not in the ip-accept list, the connection is rejected immediately.

2. PROXY Protocol Header Parsing

If ip-accept passes, Radiator reads and parses the PROXY protocol v2 header. The header contains:

  • Original client IP address and port
  • Destination IP address and port
  • Protocol information (TCP/UDP, IPv4/IPv6)

If the header is malformed or uses an unsupported version, the connection is rejected.

3. Client Lookup

After successful PROXY protocol parsing, client lookup uses the original client IP address (from the PROXY header), not the proxy's address.

This ensures that RADIUS client matching, shared secrets, and access policies apply to the actual client, not the intermediate proxy.

Statistics and Counters

Radiator tracks several counters related to PROXY protocol processing:

CounterDescription
IpAcceptDenyConnections rejected at IP-accept pre-admission check
ProxyProtocolErrorsFailed to parse or invalid PROXY protocol headers
ClientsDenyClient lookup failed for the proxied address
RequestsSuccessfully processed requests
RepliesSuccessfully sent replies

Monitor these counters to detect:

  • Misconfigured load balancers sending invalid headers
  • Unauthorized proxies attempting connections
  • Client configuration issues with proxied addresses

Logging

When PROXY protocol is enabled, logs include both addresses:

  • peer_addr: The direct connection source (load balancer IP)
  • proxy_addr: Logged when different from peer_addr, showing the proxy
  • Context uses the original client address for all processing

Example log entry:

{
  "peer_addr": "203.63.154.1",
  "proxy_addr": "10.0.1.5",
  "message": "Processing RADIUS request"
}

Security Considerations

  1. Always use ip-accept: Restrict which proxies can connect to prevent IP spoofing

    ip-accept "TRUSTED_PROXIES" {
        client "LOAD_BALANCERS" {
            source {
                ip 10.0.1.0/24;
            }
        }
    }
    
  2. Monitor ProxyProtocolErrors: Spike indicates misconfiguration or attack attempts

  3. Validate client configuration: Ensure RADIUS clients are defined using their real IP addresses, not proxy addresses

Protocol Support

PROXY protocol is supported on:

  • RADIUS TCP (including RadSec/TLS)
  • RADIUS UDP
  • TACACS+ TCP (with or without TLS)

For HTTP use X-Forwarded-For headers instead.

Performance Impact

PROXY protocol adds minimal overhead:

  • Header size: 16 bytes (IPv4) or 28 bytes (IPv6) for v2
  • Parsing: Single parse operation at connection establishment
  • Memory: No additional per-request allocations

For UDP, the header is included with each datagram. For TCP, it's sent once per connection.

See Also