I'm trying to use iptables to load balance web traffic over multiple DSL lines by marking the packets and routing based on the mark. I'm working with CentOS 6.6, Kernel 2.6.32-504.16.2.el6.x86_64, Iptables v1.4.7.
For now I've done the following, as a proof of concept:
iptables -t mangle -A PREROUTING -j MARK --set-mark 2 iptables -t mangle -A OUTPUT -j MARK --set-mark 2
Plus some logging and failsafe for the remote connection:
iptables -t mangle -A PREROUTING -p tcp --dport 22 -j ACCEPT iptables -t mangle -A OUTPUT -j LOG --log-prefix "output " iptables -t mangle -A PREROUTING -j LOG --log-prefix "prerouting "
iptables -t mangle -L -v gives me
Chain PREROUTING (policy ACCEPT 177 packets, 93050 bytes) pkts bytes target prot opt in out source destination 164 13112 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh 7687 4287K MARK all -- any any anywhere anywhere MARK set 0x2 7687 4287K LOG all -- any any anywhere anywhere LOG level warning prefix `prerouting ' Chain INPUT (policy ACCEPT 184 packets, 91203 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 25 packets, 3100 bytes) pkts bytes target prot opt in out source destination 304 38367 MARK all -- any any anywhere anywhere MARK set 0x2 304 38367 LOG all -- any any anywhere anywhere LOG level warning prefix `output ' Chain POSTROUTING (policy ACCEPT 25 packets, 3100 bytes) pkts bytes target prot opt in out source destination
I've set up alternative routing tables.
ip route show table DSL2 gives me
10.77.0.0/16 via 220.127.116.11 dev eth4 18.104.22.168/16 via 22.214.171.124 dev eth4 default via 10.177.55.33 dev eth2
(126.96.36.199/16 and 10.77.0.0/16 via eth4 is the LAN, 10.177.55.33 via eth2 is one of the DSL routers.)
And I added a policy to use table DSL2 when mark is set to 2.
ip rule shows:
0: from all lookup local 32764: from all fwmark 0x2 lookup DSL2 32765: from all fwmark 0x1 lookup DSL1 32766: from all lookup main 32767: from all lookup default
(Ignore DSL1 for now. It comes into play when it's working so far.)
The logs show that the mark is being applied: (end of the line)
Jun 1 17:05:03 squidXXX kernel: output IN= OUT=eth4 SRC=112.112.xxx.xxx DST=10.77.xxx.xxx LEN=312 TOS=0x08 PREC=0x00 TTL=64 ID=60789 DF PROTO=TCP SPT=22 DPT=49328 WINDOW=543 RES=0x00 ACK PSH URGP=0 MARK=0x2
But when I try to connect to an outside address I get a network unreachable reply, both when pinging from the local machine or when connecting to the proxy from another machine. Note: I have a squid proxy running on that machine as well which is working as intended. When I add 10.177.55.33 as the default route in the main routing table I can reach outside networks just fine.
Now I've read about someone having the same problem and solving it be replacing the default route with target net 0.0.0.0/1. Not only is this wrong (any addresses above 188.8.131.52 wouldn't be accessible) but it also doesn't work in my case. Anyways what I get from it is that my routing table could be faulty so it takes the main routing table instead, but I don't see any errors. Or are there known bugs?
Following this lead I tried adding
ip rule add from all lookup DSL2 prio 1002 which routes the packets as expected, so that's probably not it.
So it looks to me as if
ip rule can't properly read the MARK or not use the table specified. But why?