Scenario

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.

Requirements

  • 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.

Equipment

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

Conceptual setup

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:

  1. Happydaddy post: https://www.dd-wrt.com/phpBB2/viewtopic.php?t=304754
  2. D0ug has an interesting setup, including kill switches. https://www.dd-wrt.com/phpBB2/viewtopic.php?t=311904
  3. 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.

General setup

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]

  1. I’m using WAN up, and configuring as a Server instead of Daemon.
  2. Also using Router server mode instead of Bridge.
  3. Don’t forget to enable “Allow client to client” so that the clients can talk to each other.
  4. 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:

root@DD-WRT:~# 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

Source