Client IP preservation

Add a Forwarded header

Available since

  • HAProxy 2.8
  • HAProxy Enterprise 2.8r1
  • HAProxy ALOHA 15.5

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. However, when relaying HTTP messages, it can store the client’s address in the HTTP forwarded header. The backend server can then be configured to read the value from that header to retrieve the client’s IP address and related information.

The forwarded header is the IETF RFC7239 header and supersedes the non-standard X-Forwarded-For header.

Add a forwarded header Jump to heading

To configure the load balancer to add a forwarded header to an incoming request, set the option forwarded directive in a defaults or backend section:

haproxy
backend webservers
option forwarded
haproxy
backend webservers
option forwarded

The unmodified directive option forwarded is equivalent to option forwarded proto for. So this creates a forwarded header like the one shown below:

text
forwarded: proto=http;for=192.168.56.5
text
forwarded: proto=http;for=192.168.56.5

Change the fields to include Jump to heading

Set any combination of the proto, host, by, by_port, and for fields to override the information included in the header’s value. Below, we include all of these fields, which will be populated automatically:

haproxy
backend webservers
option forwarded proto host by by_port for
haproxy
backend webservers
option forwarded proto host by by_port for

This creates a forwarded header like this:

text
forwarded: proto=http;host="example.com";by="192.168.56.10:80";for=192.168.56.5
text
forwarded: proto=http;host="example.com";by="192.168.56.10:80";for=192.168.56.5

Override the values with expressions Jump to heading

Override the values of the host, by, by_port, or for fields by replacing them with expressions that use hardcoded values or fetch methods. Use any of:

  • host-expr
  • by-expr
  • by_port-expr
  • for-expr
  • for_port-expr

A common way to use this is to obfuscate the a user’s personal identifying information by storing only hashes of their IP address and source port. Below, we add a forwarded header that contains a host value of example.com, a by value of loadbalancer, and a for value composed of a hash of the client’s source IP address and a hash of the client’s source port:

haproxy
backend webservers
option forwarded host-expr str(example.com) by-expr str(loadbalancer1) for-expr src,xxh32,hex for_port-expr dst_port,xxh32,hex
haproxy
backend webservers
option forwarded host-expr str(example.com) by-expr str(loadbalancer1) for-expr src,xxh32,hex for_port-expr dst_port,xxh32,hex

This creates a forwarded header like this:

text
forwarded: host="example.com";by=_loadbalancer1;for="_000000008D7250D3:_000000006BABCF75"
text
forwarded: host="example.com";by=_loadbalancer1;for="_000000008D7250D3:_000000006BABCF75"

Converters Jump to heading

The following converters let you validate and read the fowarded header:

  • rfc7239_is_valid
  • rfc7239_field
  • rfc7239_n2nn
  • rfc7239_n2np

See also Jump to heading

Do you have any suggestions on how we can improve the content of this page?