route tables: powerful and selective use of VPNs

Background

I regularly use a VPN. Unfortunately there are some sites (ie http://grooveshark.com ) that are viewable with my connection, but not with VPN’s one (yes, the opposite of the typical case).
I need to handle them.

Rules

Just ip-rule

Routing tables are cool. Here’s how to force every connection to $IP using 192.168.1.1 as gateway. This will bypass any other gateway (tipically, a VPN)

echo 200 forcelocal | sudo tee -a /etc/iproute2/rt_tables
 sudo ip route add to default via 192.168.1.1 dev eth0 table forcelocal
 sudo ip rule add to $IP table forcelocal

Of course the last line could be repeated for any IP you want to “enforce”.

More advanced filters

iptables can filter in such a good way that we want to use it. so:

sudo iptables -t mangle -A OUTPUT -m owner --uid-owner 42 -j MARK --set-mark 1
sudo iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source=$YOUR_LOCAL_IP
sudo ip rule add fwmark 1 pri 100 table forcelocal

here, 42 is the UID of “privoxy”, so that we can run a SOCKS proxy having access just to “direct” connection. Anyway you can use any user (so you can create a “novpn” user) or any iptables rule. Powerful and simple.

An opt-out configuration (based on firefox+privoxy)

Usually, I want my traffic to be tunneled through VPN. Sometimes I don’t.

So I set up a local privoxy instance. As the privoxy UID is “forcelocal”ed, it will run directly

If I want to force local connection for a website, I configure FireProxy to use a local privoxy instance as proxy for that site. This is easy and works well. And I can easily switch behaviour if I need.

If I want to force local connection for a different protocol/application, I just write an iptables rule that matches it. An example is bittorrent, for which I still don’t have a solution