Source port routing

From lxadm | Linux administration tips, tutorials, HOWTOs and articles
Jump to: navigation, search

Sometimes, you may want some services (i.e. web) to be routed through a different interface. Here is a quick setup with some common problems.

Assumptions:

  • 10.4.0.1 – your additional gateway, through which you only want to route web traffic (TCP port 80),
  • 10.4.0.2 – server which needs source port routing altered,
  • tun0 – device on 10.4.0.2 which will be used for source port routing.

Now, we’re ready to start configuration:

  • first, add a new routing table to /etc/iproute2/rt_tables – we’ll call it “http” and it will be table “1” – with it, your /etc/iproute2/rt_tables file should look much like below:
#
# reserved values
#
255    local
254    main
253    default
0    unspec
#
# local
#
#1    inr.ruhep
1    http


  • assuming the peer through which you want to push http traffic is behind tun0 interface and has 10.4.0.1 address, we have to manipulate routing with the two rules below:
ip route add default via 10.4.0.1 dev tun0 table http
ip rule add from all fwmark 1 table http

Basically, they mean that “http” table traffic need to go through tun0, 10.4.0.1, and packets marked with “1” value should get there.


  • we also need to mark the packets – we’ll use iptables for that:
iptables -t mangle -A OUTPUT -p tcp -o eth0 -s 10.4.0.2 --sport 80 -j MARK --set-mark 1

This means that in the mangle table, locally-generated packets with 10.4.0.2 source which would by default go through eth0, will be marked with “1” value.

Still doesn’t work? Check these things below:

  • rp_filter has to be set to 0 for given interfaces – 0 is the default value set by the Linux kernel, but some distributions (i.e. Ubuntu, Mandriva) alter it and set it to 1; just adding that to /etc/sysctl.conf should do the trick to make sure this value is set to 0 after reboot:
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0


If you’re not rebooting any time soon, see what these value currently are with:

find /proc/sys/net -name rp_filter | xargs cat
  • there has to be direct, not routed traffic between the hosts – for example, if you have more than one hop, source port routing will not work:
# traceroute 10.0.0.10
traceroute to 10.0.0.10 (10.0.0.10), 30 hops max, 60 byte packets
1  10.255.255.254 (10.255.255.254)  0.978 ms  1.185 ms  1.218 ms
2  10.0.0.10 (10.0.0.10)  0.159 ms  0.154 ms  0.179 ms

It has to look like below:

# traceroute 10.4.0.1
traceroute to 10.4.0.1 (10.4.0.1), 30 hops max, 60 byte packets
1  10.4.0.1 (10.4.0.1)  0.597 ms  0.593 ms  0.590 ms


  • not sure what you have to change on your new gateway (10.4.0.1 in this example)? The below should be enough:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE


  • note that web traffic should also come from 10.4.0.1