Scheduled restarts for your DD-WRT router

DD-WRT is an excellent router OS that can allow you to have complete control over your home or office network. I highly recommend it.

If you want to restart your DD-WRT router every night for whatever reason, there’s an easy way to go about it. You can define bootup/startup scripts for your router to run whenever it starts. These can be defined in Administration -> Commands on your the DD-WRT router’s web interface.

To restart your router every night at 11:45pm, add these commands to startup:

printf "#!/bin/sh\nstartservice run_rc_shutdown; /sbin/reboot" > /tmp/restart_router
chmod a+x /tmp/restart_router
echo "45 23 * * * root /tmp/restart_router" > /tmp/cron.d/restartrouter

And that’s it! (Make sure you either ssh in and run these commands manually when you set this up for the first time, or save the startup script and restart your router once, to kick everything off initially. After that it’ll do it by itself every night at 11:45pm).

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 1.2.3.4/32 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 1.2.3.4 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/update-ip-rules.sh
echo 'while true; do' >> /tmp/update-ip-rules.sh
echo '	ip rule add to 1.2.3.4/32 table 10' >> /tmp/update-ip-rules.sh
echo '	ip route flush cache' >> /tmp/update-ip-rules.sh
echo '	sleep 300' >> /tmp/update-ip-rules.sh
echo 'done' >> /tmp/update-ip-rules.sh
chmod +x /tmp/update-ip-rules.sh
nohup /tmp/update-ip-rules.sh >> /dev/null 2>&1 &

Policy based routing for PPTP VPN client on DD-WRT router

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 MASQUERADE
ip rule add from 192.168.0.105 table 200
ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 200
ip rule add from 192.168.0.106 table 201
ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 201
ip 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 120
iptables –table nat –append POSTROUTING –out-interface ppp0 –jump MASQUERADE
ip rule add from 192.168.0.105 table 200
ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 200
ip rule add from 192.168.0.106 table 201
ip route add default via $(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 201
ip route flush cache
head -n -1 /tmp/pptpd_client/ip-up > /tmp/pptpd_client/ip-up.new
mv /tmp/pptpd_client/ip-up.new /tmp/pptpd_client/ip-up
echo “iptables –table nat –append POSTROUTING –out-interface ppp0 –jump MASQUERADE” >> /tmp/pptpd_client/ip-up
echo “ip rule delete from 0/0 to 0/0 table 200” >> /tmp/pptpd_client/ip-up
echo “ip route delete table 200” >> /tmp/pptpd_client/ip-up
echo “ip rule add from 192.168.0.105 table 200” >> /tmp/pptpd_client/ip-up
echo “ip route add default via \$(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 200” >> /tmp/pptpd_client/ip-up
echo “ip rule delete from 0/0 to 0/0 table 201” >> /tmp/pptpd_client/ip-up
echo “ip route delete table 201” >> /tmp/pptpd_client/ip-up
echo “ip rule add from 192.168.0.105 table 201” >> /tmp/pptpd_client/ip-up
echo “ip route add default via \$(ifconfig ppp0 | sed -n ‘s/.*inet *addr:\([0-9\.]*\).*/\1/p’) dev ppp0 table 201” >> /tmp/pptpd_client/ip-up
chmod a+x /tmp/pptpd_client/ip-up
Just a quick breakdown of the script above: the first command, sleep 120, ensures that enough time passes for the router to boot up, and the PPTP VPN client to connect at least once. The next few commands are the same as above… they set up the policy based routing for the current PPTP connection. The next several commands write to the “/tmp/pptpd_client/ip-up” script, which is run whenever the PPTP connection is re-established (in case it gets dropped due to whatever temporary network connectivity issue). Note: the final line of the default “ip-up” script is “exit 0” so any commands appended to the script after that line won’t get executed. Hence, I have the head command to get everything from the current ip-up script except the last line. It’s also important to note that this ip-up script is re-created any time you restart the DD-WRT router, hence it’s important to re-append the commands to it on every restart when the startup script is called.