Enable the PROXY protocol (original) (raw)

When the load balancer proxies a TCP connection, it overwrites the client’s source IP address with its own when communicating with the backend server. The PROXY protocol adds a header to a TCP connection to preserve the client’s IP address. This method solves the lost-client-IP problem for any application-layer protocol that transmits its messages over TCP/IP. To work, both the sender and receiver must support the protocol and have it enabled.

The load balancer adds the header to TCP connections before relaying them to upstream servers. When placed behind another proxy, it can also receive the PROXY protocol header attached to the incoming connection. This feature supports IPv4 and IPv6 addresses.

Receive the PROXY protocol Jump to heading

To accept a PROXY protocol header on incoming TCP connections:

  1. Add an accept-proxy argument to the bind line in a frontend section. This argument detects both PROXY protocol version 1 (text format) and PROXY protocol version 2 (binary format).
    The example below accepts the PROXY protocol header from incoming connections:
    haproxy
    frontend mywebsite bind :80 accept-proxy default_backend webservers
    haproxy
    frontend mywebsite bind :80 accept-proxy default_backend webservers

Send the PROXY protocol Jump to heading

To send a PROXY protocol version 1 header (text format) to the backend servers:

To send a PROXY protocol version 2 header (binary format) to the backend servers:

PROXY protocol on AWS Network Load Balancers Jump to heading

AWS NLB can use the PROXY protocol to set the IP address in requests. Enable this feature as described here:

Then add the keyword accept-proxy to your bind line, as described in the section Receive the PROXY protocol. The requests will then automatically have the right source IP address.

This section applies to:

While the PROXY protocol’s primary function is to preserve a client’s source IP address when traffic traverses one or more reverse proxies, it can also serve as a way to attach metadata to TCP connections. In the PROXY Protocol v2 (binary header format), Type-Length-Value (TLV) vectors store variable-length data in the PROXY protocol header, allowing you to transmit information relevant to the sender and receiver.

Here are a few use cases for TLV vectors:

TLV format Jump to heading

TLV vectors have the following format:

The PROXY protocol defines several types, which you can learn more about in the PROXY protocol specification:

`#define PP2_TYPE_ALPN 0x01

#define PP2_TYPE_AUTHORITY 0x02

#define PP2_TYPE_CRC32C 0x03

#define PP2_TYPE_NOOP 0x04

#define PP2_TYPE_UNIQUE_ID 0x05

#define PP2_TYPE_SSL 0x20

#define PP2_SUBTYPE_SSL_VERSION 0x21

#define PP2_SUBTYPE_SSL_CN 0x22

#define PP2_SUBTYPE_SSL_CIPHER 0x23

#define PP2_SUBTYPE_SSL_SIG_ALG 0x24

#define PP2_SUBTYPE_SSL_KEY_ALG 0x25

#define PP2_TYPE_NETNS 0x30

`

`#define PP2_TYPE_ALPN 0x01

#define PP2_TYPE_AUTHORITY 0x02

#define PP2_TYPE_CRC32C 0x03

#define PP2_TYPE_NOOP 0x04

#define PP2_TYPE_UNIQUE_ID 0x05

#define PP2_TYPE_SSL 0x20

#define PP2_SUBTYPE_SSL_VERSION 0x21

#define PP2_SUBTYPE_SSL_CN 0x22

#define PP2_SUBTYPE_SSL_CIPHER 0x23

#define PP2_SUBTYPE_SSL_SIG_ALG 0x24

#define PP2_SUBTYPE_SSL_KEY_ALG 0x25

#define PP2_TYPE_NETNS 0x30

`

In addition, 16 type values are reserved for application-specific data, such as those used by Azure and AWS.

`#define PP2_TYPE_MIN_CUSTOM 0xE0

#define PP2_TYPE_MAX_CUSTOM 0xEF

`

`#define PP2_TYPE_MIN_CUSTOM 0xE0

#define PP2_TYPE_MAX_CUSTOM 0xEF

`

A range of 8 type values are reserved for temporary, experimental use by application developers and protocol designers. You shouldn’t use these in production:

`#define PP2_TYPE_MIN_EXPERIMENT 0xF0

#define PP2_TYPE_MAX_EXPERIMENT 0xF7

`

`#define PP2_TYPE_MIN_EXPERIMENT 0xF0

#define PP2_TYPE_MAX_EXPERIMENT 0xF7

`

Receive TLV fields Jump to heading

Use the fc_pp_tlv fetch method to receive TLV vectors from a PROXY protocol header. The fetch returns a string type.

Azure example:

haproxy

`frontend fe_main

bind :80 accept-proxy

tcp-request content set-var(sess.azure_vpcid) fc_pp_tlv(0xEE),bytes(1) if { fc_pp_tlv(0xEE),bytes(0,1),hex eq 01 }

`

haproxy

`frontend fe_main

bind :80 accept-proxy

tcp-request content set-var(sess.azure_vpcid) fc_pp_tlv(0xEE),bytes(1) if { fc_pp_tlv(0xEE),bytes(0,1),hex eq 01 }

`

AWS example:

haproxy

`frontend fe_main

bind :80 accept-proxy

tcp-request content set-var(sess.aws_linkid) fc_pp_tlv(0xEA),bytes(1) if { fc_pp_tlv(0xEA),bytes(0,1),hex eq 01 }

`

haproxy

`frontend fe_main

bind :80 accept-proxy

tcp-request content set-var(sess.aws_linkid) fc_pp_tlv(0xEA),bytes(1) if { fc_pp_tlv(0xEA),bytes(0,1),hex eq 01 }

`

Send TLV fields Jump to heading

Add the set-proxy-v2-tlv-fmt argument to server directives to send TLV fields to a backend server. This argument must be accompanied by the send-proxy-v2 argument.

Azure example:

haproxy

`backend webapp

server srv1 192.168.1.10:80 send-proxy-v2 set-proxy-v2-tlv-fmt(0xEE) %[fc_pp_tlv(0xEE)]

`

haproxy

`backend webapp

server srv1 192.168.1.10:80 send-proxy-v2 set-proxy-v2-tlv-fmt(0xEE) %[fc_pp_tlv(0xEE)]

`

AWS example:

haproxy

`backend webapp

server srv1 192.168.1.10:80 send-proxy-v2 set-proxy-v2-tlv-fmt(0xEA) %[fc_pp_tlv(0xEA)]

`

haproxy

`backend webapp

server srv1 192.168.1.10:80 send-proxy-v2 set-proxy-v2-tlv-fmt(0xEA) %[fc_pp_tlv(0xEA)]

`

See also Jump to heading

See the latest PROXY protocol definition: PROXY protocol

For complete information on the actions and fetches related to the PROXY protocol, see the HAProxy Configuration Manual:

Consult your cloud provider documentation for details about any PROXY TLV fields they may use: