Enabling SNAT in LVS (xt_ipvs) and iptables

How-tos Published on 3 mins Last updated

The vast majority of layer 4 load balancers use LVS in two-arm NAT mode. In this mode the load balancer can control all traffic and it's also source IP transparent.

The disadvantage of NAT mode is that the load balancer must be the default gateway for the servers, which can be a pain when you need to re-arrange the whole network to put servers behind the load balancer.

Loadbalancer.org did some work ages ago with the open source community to create SNAT mode, which is a bit like NAT without the need for being a default gateway. LVS-SNAT mode changes the source address of all the packets to be the load balancer so you don't need to change your default gateway (obviously Layer 4 SNAT is not source IP transparent)

BTW. DR mode also solves this problem while staying transparent (which is why we love it!)

NB. v8.3.1 includes full support for Layer 4 LVS-SNAT (so no need to keep reading this blog unless you are a geek who likes to know how things actually work!).

The rest of this blog is fairly old but still interesting.... so pretend you are in a time machine when you read it! (Also, feel free to check out our roadmap blog to see what we've got in the pipeline for future releases.)

Firstly this is all very bleeding edge and as yet has not made it into the current kernel it should be in 2.6.36 with a new version of iptables released not long after that.

But for those of you far to eager to use this already here is what you do. N.B I will also go through the process of enabling it so if your reading this and 2.6.36 is available as is the latest version of iptables you can probably skip the start of this article.

The patches are available as part of the LVS list, Which Should be available here http://archive.linuxvirtualserver.org/html/lvs-devel/2010-07/msg00033.html

There are 4 patches in all that you need to implement. There is also a Git repository available (at the time of writing) to get a patched version of 2.6.35-rc1. Firstly you need to install GIT

Then

git clone -b full-nat 
git://git.kernel.org/pub/scm/linux/kernel/git/horms/lvs-test-2.6.git

For instructions on building your kernel see http://howtoforge.com/kernel_compilation_centos_p2 which is the method that I used, feel free to use your own should you require.

When you come to your make menuconfig section please make sure you enable LVS and Netfilter making sure you enable  ipvs match support which can be found ->
Networking support
Networking Options
Network packet filtering framework (Netfilter)
Core Netfilter Configuration
"ipvs" match support

then

make all
make modules_install
make install

and reboot into your new kernel version.

Once you have that running you must make sure that the xt_ipvs module was installed so a quick search

find / -name xt_ipvs.*

should turn it up in your /lib/modules folder if its not there you need to check that it was enabled correctly in your kernel config.

Right now thats done time to rebuild iptables -

for this your looking for the patch "[patch v2.7 4/4] libxt_ipvs: user-space lib for netfilter matcher xt_ipvs"

which will patch iptables

I downloaded their latest version http://www.netfilter.org/projects/iptables/files/iptables-1.4.8.tar.bz2

and untared it to /usr/src then copied the patch into the iptables-1.4.8 direcory then patched it.

Then ran a

make install

after all that you should be ready to go!

Im going to detail my setup -

The Loadbalancer

IPVS 1.2.1
iptables 1.4.8 --patched
kernel - 2.6.35-rc1 --patched

eth0 ip 192.168.17.93
eth0:45 192.168.18.21 (I would have used eth1 but couldn't find a test box spare with 2 network cards in)

My test box -

eth0 192.168.18.1

The Webserver -

192.168.17.4:80

Commands to setup ipvs and iptables

IPVS

ipvsadm -A -t 192.168.18.21:80 -s rr
ipvsadm -a -t 192.168.18.21:80 -r 192.168.17.4:80 -m

iptables

/usr/local/sbin/iptables -t nat -A POSTROUTING -m ipvs --vaddr 192.168.18.21/24 --vport 80 -j SNAT --to-source 192.168.17.93

iptables shows -

iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       all  --  anywhere             anywhere            vaddr 192.168.18.0/24 vport 80 to:192.168.17.93

ipvsadm shows -

ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.18.21:80 rr
-> 192.168.17.4:80              Masq    1      0          0


Connected to the IP from my browser page loaded fine and you can see in the apache log -

"192.168.17.93 - - [21/Jul/2010:08:44:00 -0400] "GET / HTTP/1.1" 200 82"

If all that worked you should be ready to go! HAPPY SNATTING (is that even a word, ah well it is now).

Mark