Routing destination IPs through OpenVPN on DD-WRT routers

DD-WRT is an excellent router OS. It comes with an OpenVPN client, so you can route all (or selective) outbound traffic through a VPN.

The OpenVPN client in DD-WRT makes it easy to specify the source IP addresses that need to have all their traffic routed through the VPN connection. This is done by specifying the source IP addresses (corresponding to devices on your internal network) in policy based routing.

However, there’s no way to specify what destination IP addresses you want routed through the VPN. For example, if it doesn’t matter what the originating source device is on your network, but you want only a certain set of destination addresses (out on the Internet) routed through the VPN connection.

To do this is pretty straight forward. You can ssh into your router (you’ll need to enable ssh management) and run this command:

ip rule add to table 10
ip route flush cache

And that’s it. Table 10 is the routing table for the VPN connection, and thus this command will make any traffic destined to the IP route through the VPN connection.

A couple caveats: the OpenVPN client will need to be already connected before you create this routing rule, the routing rule won’t persist through system reboots, and if the OpenVPN connection is dropped for whatever reason, the client software will reconnect it, but the rule will need to be created again.

A crude way around all this is to create a script that runs at bootup/startup for the router. You can define this startup script Administration -> Commands in the DD-WRT interface. The script can run every 5 minutes and create the rule. So when the router is restarted, or if the OpenVPN client connection drops and reconnects, the routing rule will just get re-created. *Note: this is obviously a very inelegant way of getting this done, but it does the job. I’m sure you can improve on this in many ways.

You can add this to your bootup/startup commands for the router:

echo '#!/bin/sh' > /tmp/
echo 'while true; do' >> /tmp/
echo '	ip rule add to table 10' >> /tmp/
echo '	ip route flush cache' >> /tmp/
echo '	sleep 300' >> /tmp/
echo 'done' >> /tmp/
chmod +x /tmp/
nohup /tmp/ >> /dev/null 2>&1 &