Skip to content


SNI proxy

frontend https
    bind :443
    mode tcp 

    acl clienthello req.ssl_hello_type 1

    acl site1 req.ssl_sni -i
    acl site1 req.ssl_sni -i -m end

    acl site2 req.ssl_sni -i
    acl site2 req.ssl_sni -i -m end

    tcp-request inspect-delay 2s
    tcp-request content accept if clienthello

    use_backend web-https-site1 if site1
    use_backend web-https-site2 if site1
    default_backend default-site

Pass client IP to backend server

Client ---> HAProxy --(connects with client IP)--> Backend
       <---         <---(responds to client IP)---

The idea is that HAProxy connects to the backend server on a loopback address with the IP address of the client, and catches response with the help of iptables and policy routing.


Preferably, the backend server should bind to an address that no one else can reach. Loopback addresses, namely addresses in 127/8, is avoided, because to use them for routing purposes one needs to turn on sysctl route_localnet, which has security implications. We can still create a dummy interface and assign a reserved address to it to avoid route_localnet.

In the following example, the address of the dummy interface is


frontend http
    bind :80 transparent
    mode tcp 
    option tcplog

    default_backend web-http

backend web-http
    mode tcp 
    source usesrc clientip
    server nginx


-t mangle -N TRANSPROXY
-t mangle -A OUTPUT -p tcp --sport 81 -j TRANSPROXY
-t mangle -A TRANSPROXY -j CONNMARK --restore-mark
-t mangle -A TRANSPROXY -m mark ! --mark 0 -j ACCEPT
-t mangle -A TRANSPROXY -j MARK --set-mark 1
-t mangle -A TRANSPROXY -j CONNMARK --save-mark

ip rule:

ip rule add fwmark 0x1 lookup 100
ip route add local default dev lo