HAProxy works as a reverse proxy. This means it maintains 2 connections when allowing a client to cross it:

  • 1 connection between HAProxy and the client

  • 1 connection between HAProxy and the server

HAProxy then manipulates buffers between these two connections. One of the drawbacks of this mode is that HAProxy will let the kernel establish the connection to the server. The kernel is going to use a local IP address to do this. Because of this, HAProxy “hides” the client IP with its own one: this can be an issue in some cases.

Here comes the transparent proxy modeHAProxy can be configured to spoof the client IP address when establishing the TCP connection to the server. That way, the server thinks the connection comes from the client directly (of course, the server must answer back to HAProxy and not to the client; otherwise, it can’t work: the client will get an acknowledgment from the server IP while it has established the connection on HAProxy‘s IP).

Transparent Binding

By default, when one wants HAProxy to get traffic, we have to tell it to bind an IP address and a port. The IP address must exist on the operating system (unless you have setup the sysctl net.ipv4.ipnonlocalbind) and the OS must announce the availability to the other devices on the network through ARP protocol.

Well, in some cases we want HAProxy to be able to catch traffic on the fly without configuring any IP address or VRRP or whatever…

This is where transparent binding comes in: HAProxy can be configured to catch traffic on the fly even if the destination IP address is not configured on the server.
These IP addresses will never be pingable, but they’ll deliver the services configured in HAProxy.

HAProxy & the Linux Kernel

Unfortunately, HAProxy can’t do transparent binding or proxying alone. It must stand on a compiled and tuned Linux Kernel and operating system. Below, I’ll explain how to do this in a standard Linux distribution.

Here is the checklist to meet:

  1. appropriate HAProxy compilation option

  2. appropriate Linux Kernel compilation option

  3. sysctl settings

  4. iptables rules

  5. ip route rules

  6. HAProxy configuration

HAProxy compilation requirements

First of all, HAProxy must be compiled with the option TPROXY enabled. It is enabled by default when you use the target LINUX26 or LINUX2628.

Linux Kernel requirements

You have to ensure your kernel has been compiled with the following options:

  • CONFIG_NETFILTER_TPROXY

  • CONFIG_NETFILTER_XT_TARGET_TPROXY

Of course, iptables must be enabled as well in your kernel 🙂

Sysctl settings

The following sysctls must be enabled:

  • net.ipv4.ip_forward

  • net.ipv4.ipnonlocalbind

Iptables rules

You must setup the following iptables rules:

iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT

The purpose is to mark packets that match a socket bound locally (by HAProxy).

IP route rules

Then, tell the Operating System to forward packets marked by iptables to the loopback where HAProxy can catch them:

ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100

HAProxy configuration

Finally, you can configure HAProxy.

  • Transparent binding can be configured like this:

[...]
frontend ft_application
  bind 1.1.1.1:80 transparent
[...]
  • Transparent proxying can be configured like this:

[...]
backend bk_application
  source 0.0.0.0 usesrc clientip
[...]

Transparent Mode in the ALOHA Load-Balancer

Now, the same steps in the ALOHA Load-balancer, which is an HAProxy-based load-balancing appliance:
1-5. not required, the ALOHA kernel is deeply tuned for this purpose
6. HAProxy configuration

LB Admin tab (AKA click mode)

  • Transparent binding can be configured like this when editing a Frontend listener:

frontend listener transparent
  • Transparent proxying can be configured like this when editing a farm:

backend transparent

LB Layer 7 tab (vi in a browser mode)

  • Transparent binding can be configured like this:

[...]
frontend ft_application
  bind 1.1.1.1:80 transparent
[...]
  • Transparent proxying can be configured like this:

[...]
backend bk_application
  source 0.0.0.0 usesrc clientip
[...]

Links

Subscribe to our blog. Get the latest release updates, tutorials, and deep-dives from HAProxy experts.