Port based routing in Ubuntu

After a lot of research I finally found a way to do port based routing in Linux, more specifically in Ubuntu.

The solution was found based on information found on these two sites:
http://www.sparksupport.com/blog/application-based-routing-in-linux
http://www.linuxforums.org/forum/networking/141331-port-based-routing.html

The reason I needed to do port based routing was so that I could route some traffic over a VPN tunnel that otherwise was blocked. But it can also be used to route in a network with several gateways which is basically what the VPN is.

The guide expects that you have a working VPN/gateway that can do NAT or route IP traffic.

The first thing you have to do is make sure rp_filter is set to 0. The default value in the Linux kernel is 0, but on some distributions (like Ubuntu), it has been set to 1. Make sure that net.ipv4.conf.default.rp_filter and net.ipv4.conf.all.rp_filter in /etc/sysctl.conf is set to 0. You will have to reboot after this for it to have an effect.

Now for the routing part. First you have to add a mangle entry to the packet for that the Linux kernel will have a mark to look for.

iptables -t mangle -A PREROUTING -p tcp –dport 80 -j MARK –set-mark 0×1

With this entry you will add the mark 0x1 to all packets being routed using the TCP protocol on port 80, in other words all web traffic. Adjust accordingly for your own needs. Simply add more rules with the same mark to send it over the VPN or gateway that we route with a new table bellow.

Next we need to add a new IP route table in /etc/iproute2/rt_table. Add a new line with something like 100 vpntunnel.

Now we add a routing rule that sends all the 0x1 marked packets to the new table we have made.

ip rule add fwmark 0×1 lookup vpntunnel

And finally we need to add the gateway to our new table.

ip route add default via 192.168.1.1 table vpntunnel

It should now be working, you can test it by doing a curl ifconfig.me to see if your public IP has changed.

5 comments:

  1. thanks!
    (but it's –-dport 80 -j MARK –-set-mark for me)

    ReplyDelete
  2. Thanks! Exactly what I needed!

    ReplyDelete
  3. You will need a return route to your LAN right?

    ReplyDelete
  4. This post got me started in a good way, thanks; but it did not work for me.
    If ended up on this post which got the policy based routing operating correctly:

    https://serverfault.com/questions/733705/iproute-rt-table-and-mark-not-working-on-linux?newreg=e441de6f7bfe41d09cc0b430c9700d40

    ReplyDelete