Hi,

I'm trying to setup an HAProxy instance to transparently load balance a
group of web servers. The HAProxy server and web servers each have two
interfaces; eth0 as the public interface and eth1 the private. I'm trying to
configure the load balancer to accept requests on port 80 on eth0 and
transparently proxy the connections to the web servers over the private
interfaces on eth1. I've configured the load balancer in the normal way for
tproxy, and have the web servers routing out through it.

i.e.

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

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

root@haproxy:~# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

root@web:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use
Iface
xxx.xxx.97.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.0.0     0.0.0.0         255.255.252.0   U     0      0        0 eth1
0.0.0.0         xxx.xxx.97.155  0.0.0.0         UG    0      0        0 eth0

...
server web1 192.168.3.65:80 source 192.168.3.64 usesrc clientip
...

When testing this setup, the connection is correctly proxied to the web
server through eth1 and a response is sent back to the HAProxy server on
eth0, but it's ignored and the connection hangs.


Here's some netstat output during the connection:

HAProxy:

Proto Recv-Q Send-Q Local Address           Foreign Address
State       PID/Program name
tcp        0      1 xxx.xxx.48.1:42424      192.168.3.65:80
SYN_SENT    1386/haproxy
tcp        0      0 xxx.xxx.97.155:80       xxx.xxx.48.1:42424
ESTABLISHED 1386/haproxy

Web Server:

Proto Recv-Q Send-Q Local Address           Foreign Address
State       PID/Program name
tcp        0      0 192.168.3.65:80         xxx.xxx.48.1:42424
SYN_RECV    -


And the relevant entries from a tcpdump on each interface on each server:

HAProxy/eth0  IP xxx.xxx.48.1.42424 > xxx.xxx.97.155.80: Flags [S], seq
1021535895, win 5840, options [mss 1418,sackOK,TS val 2448718 ecr
0,nop,wscale 7], length 0

HAProxy/eth0  IP xxx.xxx.97.155.80 > xxx.xxx.48.1.42424: Flags [S.], seq
504489330, ack 1158274356, win 5792, options [mss 1460,sackOK,TS val 230477
ecr 1407043,nop,wscale 7], length 0

HAProxy/eth0  IP xxx.xxx.48.1.42424 > xxx.xxx.97.155.80: Flags [.], ack 1,
win 46, options [nop,nop,TS val 1407043 ecr 230477], length 0

HAproxy/eth1 IP xxx.xxx.48.1.42424 > 192.168.3.65.80: Flags [S], seq
391399045, win 5840, options [mss 1460,sackOK,TS val 230550 ecr 0,nop,wscale
7], length 0

Web/eth1 IP xxx.xxx.48.1.42424 > 192.168.3.65.80: Flags [S], seq 391399045,
win 5840, options [mss 1460,sackOK,TS val 230550 ecr 0,nop,wscale 7], length
0

Web/eth0 IP 192.168.3.65.80 > xxx.xxx.48.1.42424: Flags [S.], seq
4033028970, ack 391399046, win 5792, options [mss 1460,sackOK,TS val 6751967
ecr 230550,nop,wscale 7], length 0

HAproxy/eth0 IP 192.168.3.65.80 > xxx.xxx.48.1.42424: Flags [S.], seq
4033028970, ack 391399046, win 5792, options [mss 1460,sackOK,TS val 6751967
ecr 230550,nop,wscale 7], length 0


NB. In this example I had set the usesrc setting to client so the client's
port was used for readability, but the same occurs with clientip.

I'm sure this is occurring because the response connection is arriving on a
different interface to the one HAProxy originated the connection to the web
server on. Does anyone know of a way around this? Is there an iptables or ip
rule that can be set to switch the return traffic from eth0 to eth1?

I have tried testing the setup by proxying the connections to the web
server's public interface on eth0 instead:

...
server web1 xxx.xxx.97.156:80 source xxx.xxx.97.155 usesrc clientip
...

And the transparent proxying works perfectly.

Any thoughts or suggestions appreciated.


Many thanks,

REW

Reply via email to