I needed to setup a site-to-site VPN between my home and my parent’s home, so that we can back up our stuff offsite – mostly documents and precious digital photos.
- I wanted it to be a proper routed VPN network, not a bridged one. By that I mean an OpenVPN tun setup, not an OpenVPN tap setup.
- I did not want to force the client to use the OpenVPN server as the gateway: I want both homes to use their own ISP for internet traffic. This is often referred to as split-tunnelling.
- Must run both OpenVPN client and server on same DD-WRT router: For maximum flexibility I wanted to run both an OpenVPN server and client on the same DD-WRT router/gateway.
1 x DD-WRT router at my place, acting as an openvpn server
1 x DD-WRT (technically an ASUSWRT) router at the remote location, acting as an openvpn client
Local LAN: 192.168.1.0/24
Remote LAN: 192.168.0.0/24
OpenVPN network: 10.8.0.0/24
- DD-WRT router acts as OpenVPN Server.
- LAN IP: 192.168.1.1/24. OpenVPN IP: 10.8.0.1/24
- Remote DD-WRT router acts as an OpenVPN client.
- LAN IP: 192.168.0.1/24. OpenVPN IP: 10.8.0.2/24.
If your LAN/IP setup is different, you should be able to operate a Find/Replace to change all these.
Some technical details
DD-WRT version: DD-WRT v3 – DD-WRT v3.0-r33679 std (11/04/17)
DD-WRT server assigns tunnel device as tun2
DD-WRT client assigns tunnel device as tun1
DD-WRT bridges ethernet and WLAN devices into br0
Considerations and gotchas
Most guides will get you *nearly* there
Most guides I found online for setting up DD-WRT for a site to site VPN with OpenVPN got me almost there, but didn’t quite finish the job. Many were also written over a year ago, and it seems DD-WRT has changed a bit since they were written. In addition, some threads where people were having issues seemed to give up on tun (routed) and switched to using tap (bridged) which wasn’t ideal for me.
Guides I found which may be useful to you include:
- Happydaddy post: https://www.dd-wrt.com/phpBB2/viewtopic.php?t=304754
- D0ug has an interesting setup, including kill switches. https://www.dd-wrt.com/phpBB2/viewtopic.php?t=311904
- Boogalooz guide: https://dd-wrt.com/phpBB2/viewtopic.php?t=312064
Note that you’ll need to register for the DD-WRT forums to see the images/attachments alluded to in the posts.
Open the frontdoor
If your DD-WRT device is also your gateway (that is, it has a modem connected to it, and it acts as your internet gateway) you’ll need to open up the port for the OpenVPN server using IPTABLES. Some guides seemed to skip this.
You don’t really need to mess around with IPTABLES with the latest builds of DD-WRT
It looks like in the past you had to do a lot of messing around with IPTABLES on DD-WRT to get OpenVPNs to work – mostly to pass traffic between the OpenVPN tun+ devices and the Bridged device (br0) on the router. Now you can just use the GUI, as it seems to autoconfigure everything for you.
OpenVPN client with PBR and OpenVPN server don’t play nice
If you have a VPN client, using Policy Based Routing (PBR) on the same DDWRT router as your OpenVPN server, you’ll hit this issue: http://svn.dd-wrt.com/ticket/5690. Put the suggested script from pastebin into your Startup Script and all will be well.
Symptoms for this issue are that you can ping from the Client network to computers inside the OpenVPN server’s local network, but not all IPs respond. It’ll turn out that the IPs that don’t respond will be in the PBR list for your OpenVPN client setup.
iroutes are important
One of the most common things I found was this symptom: You can ping from the client network to computers on the server’s network. But you cannot ping from the Server network back through to the Client’s LAN network. You can ping from the server network to the OpenVPN IP on the remote network (10.8.0.2 in my case) but not the IP on the other side of the router on the LAN interface (192.168.0.1 in my case).
The problem is that some of the guides you’ll find strewn around the internet don’t cover adding iroutes. Without adding an iroute to the OpenVPN client, you won’t be able to ping from the Server LAN to the Client LAN.
Create server and client keys
Sorting out the keys for the server and client is covered well in this post: https://openvpn.net/index.php/open-source/documentation/howto.html#pki. This part of the setup is outside the scope of this blog post.
Configure the OpenVPN server
OpenVPN server setup in the DD-WRT GUI
Here’s how my OpenVPN Server config looks [images below]
- I’m using WAN up, and configuring as a Server instead of Daemon.
- Also using Router server mode instead of Bridge.
- Don’t forget to enable “Allow client to client” so that the clients can talk to each other.
- In additional config add:
# add a route to the client's LAN, and send it to the OpenVPN IP of the client. route 192.168.0.0 255.255.255.0 10.8.0.2 #push a route to the client, which will send traffic for the Server's LAN over the VPN. push "route 192.168.1.0 255.255.255.0"
Here’s the server conf file in case it’s useful:
[email protected]:~# cat /tmp/openvpn/openvpn.conf dh /tmp/openvpn/dh.pem ca /tmp/openvpn/ca.crt cert /tmp/openvpn/cert.pem key /tmp/openvpn/key.pem keepalive 10 120 verb 3 mute 3 syslog writepid /var/run/openvpnd.pid management 127.0.0.1 14 management-log-cache 100 topology subnet script-security 2 port 1194 proto udp4 cipher aes-256-cbc auth sha256 client-connect /tmp/openvpn/clcon.sh client-disconnect /tmp/openvpn/cldiscon.sh client-config-dir /tmp/openvpn/ccd comp-lzo adaptive tls-server ifconfig-pool-persist /tmp/openvpn/ip-pool 86400 client-to-client tls-cipher TLS-RSA-WITH-AES-128-CBC-SHA fast-io tun-mtu 1400 mtu-disc yes server 10.8.0.0 255.255.255.0 dev tun2 #additional config route 192.168.0.0 255.255.255.0 10.8.0.2 push "route 192.168.1.0 255.255.255.0"
Example Client config ovpn file:
client dev tun proto udp remote YOURopenvpnserverhostname.yourdynamicdnsservice.blah 1194 nobind float persist-key persist-tun remote-cert-tls server auth-nocache comp-lzo no tun-mtu 1400 mssfix 1400 auth SHA256 cipher AES-256-CBC <ca>PASTE CA.crt CERT CONTENTS HERE</ca> <cert>PASTE client.crt CLIENT CERT CONTENTS HERE</cert> <key>PASTE PRIVATE client.key CLIENT KEY CONTENTS HERE</key>
Putting the contents of the ca, cert and key files into the ovpn files makes it much easier to import into an OpenVPN client. In my case, the ASUSWRT openvpn client wouldn’t accept these files individually, so I had to combine them in the ovpn profile file as above.
Additional configuration to make it all work as expected
Below are all the things I had to do in addition to general setup to make things work. That is, that both sides of the VPN could contact each other as expected in a site-to-site VPN.
Open the OpenVPN Port
Administration > Commands > Firewall Script
Add the following to the Firewall Script in DD-WRT.
# This lets the outside world connect to the port specified using the protocol specified running on the DD-WRT router. # Command assumes you're using the udp protocol for openvpn, and port 1194. # Change to tcp if you're using that. And also change the port if you're using something else. iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT
Startup script to fix routing with OpenVPN client and PBR
Administration > Commands > Startup Script
Go here for the overview: http://svn.dd-wrt.com/ticket/5690 and use the script in the pastebin link to fix the issue. Add it to startup via Administration > Commands.
Client config to provide iroute
Administration > Commands > Startup Script
Add this to the bottom of the PBR fix script text in the Startup Script section
This is what enables you to ping from server network to client network. Without this, you’ll be able to ping from client LAN to server LAN, but not from Server LAN to Client LAN. The script ensures that on each boot of the router, it re-creates the client configuration file in the /tmp/ directory on the DD-WRT router and adds the iroute command to the config file. When the remote client connects, it’ll pick up this iroute.
There’s some really good information on why this works here: http://backreference.org/2009/11/15/openvpn-and-iroute/ but basically, openvpn doesn’t quite behave like it should, so even though you may have all the right routes setup, it won’t work unless you’ve configured an iroute for the client.
Put this in your Startup Script, just after the PBR fix text:
test -d /tmp/openvpn || mkdir /tmp/openvpn test -d /tmp/openvpn/ccd || mkdir /tmp/openvpn/ccd # add the network of the Client's own LAN! Not the openvpn network, or the server's network. # Also make sure that the filename matches that of the client's name. In my case, the client users the client001 cert. echo "iroute 192.168.0.0 255.255.255.0" > /tmp/openvpn/ccd/client001