This post is a change from my usual software programming related posts. I usually don’t write about networking related issues, but I struggled with this issue a bit recently so I thought I’d write about it.
In plain English, when I say policy based routing, I mean to accomplish the following: if you want a computer or device on your home or work network to go over a VPN connection, but you don’t want the rest of the computers or devices on your home or work network to use the VPN connection, you can accomplish that by setting up policy based routing on your router. I’ve also heard this being referred to as “source based routing” or “split tunneling”.
This post specifically addresses split tunneling on a DD-WRT router (an awesome Linux based router) that has a PPTP VPN client connection configured. I want some computers on my network to have all their traffic routed through VPN connection, but not the rest of the network.
First of all, you’ll need to configure the PPTP VPN client connection on your DD-WRT router. You can read up on doing that here: https://www.dd-wrt.com/wiki/index.php/Static_PPTP_VPN_Client.
Next, assuming your PPTP VPN client connection is configured and working properly, you’ll want to set up some rules for your router. (BTW, figuring out if the PPTP VPN client connection worked wasn’t easy or obvious–I had to ssh into the router, and run “ps w” to ensure pptp and pppd were running, and “ifconfig” to ensure the “ppp0” interface was set up, which was telling of a successful PPTP connection). Assuming your home or work network address is 192.168.0.0/255.255.255.0, and you have two computers that you want traffic routed for through the VPN: 192.168.0.105 and 192.168.0.106, you’ll need to run the following commands:
iptables –table nat –append POSTROUTING –out-interface ppp0 –jump MASQUERADEip rule add from 192.168.0.105 table 200ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 200ip rule add from 192.168.0.106 table 201ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 201ip route flush cache
The first command preps your router for forwarding (NAT’ing) packets over ppp0 (the interface for the PPTP VPN client). The next few commands add rules for all traffic from 192.168.0.105 and 192.168.0.106 to get sent over ppp0 and hence the VPN connection (note that the ifconfig/sed sub-command gets the IP address for ppp0, which is the IP given to your PPTP VPN client by the PPTP VPN server). And the final command flushes any cache on the routing tables on the router, which cleans it up to work for the new rules.
And that’s it!
However, you may not want to have to manually run these commands whenever your router is restarted. So, I set up the following “startup” script to run these commands for me, and also add them to the “ip-up” script for the PPTP client so they’re executed if the interface goes down and back up (due to network connectivity interruption or something else). You can enter the script commands below to your stratup script on your DD-WRT router, and they will ensure that if your router is ever restarted, or the PPTP client connection drops and gets reconnected, the special routes will get set up again. (You can create the startup script like so: https://www.dd-wrt.com/wiki/index.php/Startup_Scripts):
sleep 120iptables –table nat –append POSTROUTING –out-interface ppp0 –jump MASQUERADEip rule add from 192.168.0.105 table 200ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 200ip rule add from 192.168.0.106 table 201ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 201ip route flush cachehead -n -1 /tmp/pptpd_client/ip-up > /tmp/pptpd_client/ip-up.newmv /tmp/pptpd_client/ip-up.new /tmp/pptpd_client/ip-upecho “iptables –table nat –append POSTROUTING –out-interface ppp0 –jump MASQUERADE” >> /tmp/pptpd_client/ip-upecho “ip rule delete from 0/0 to 0/0 table 200” >> /tmp/pptpd_client/ip-upecho “ip route delete table 200” >> /tmp/pptpd_client/ip-upecho “ip rule add from 192.168.0.105 table 200” >> /tmp/pptpd_client/ip-upecho “ip route add default via \$(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 200” >> /tmp/pptpd_client/ip-upecho “ip rule delete from 0/0 to 0/0 table 201” >> /tmp/pptpd_client/ip-upecho “ip route delete table 201” >> /tmp/pptpd_client/ip-upecho “ip rule add from 192.168.0.105 table 201” >> /tmp/pptpd_client/ip-upecho “ip route add default via \$(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 201” >> /tmp/pptpd_client/ip-upchmod a+x /tmp/pptpd_client/ip-up