How to configure your DD-WRT OpenVPN

In this blog post, I’m going to cover how to configure your DD-WRT OpenVPN (Virtual Private Network). Now there are a number of ways to use a VPN but I’m going to set up the router so we can connect to it with a computer. We could connect a second router and have so-called site-to-site connectivity, but for this post, we’ll stick with using a laptop as a client.

For this article, I’ll be using OpenVPN but DD-WRT supports PPTP which is an older protocol and considered insecure, as well as more modern alternatives like Wireguard. I’ll be covering how to connect with Wireguard in another blog. Unless you need to have a centralized Certificate Authority, then Wireguard looks like the way to go because it’s a lot simpler to set up.

Preparing the router

The hardware we were running for the server was a fairly old TP-Link TL-WR1043ND with 32Mb of RAM that has been flashed with Firmware: DD-WRT v3.0-r42729 std (03/18/20). It’s fairly good for an old router though and has Gigabit Ethernet ports for the LAN and WAN as well as Wifi and a USB port so it can be used to connect a USB hard drive and used as an FTP server. Once the VPN is setup you can securely access your home network from the Internet.

1: We begin by turning on VPN Server functionality.

Login to the GUI > Browse to the tab Services > VPN and select the enable radio button.

Turning on the VPN server from the Services > VPN tab of the DD-WRT GUI
Turning on the VPN server from the Services > VPN tab of the DD-WRT GUI.

2: The following image shows which settings I used. For the moment we don’t need the advanced settings so we can concentrate on the others.
Enable OpenVPN and CVE-2019-14899-Mitigation. Select Start Type System (so the VPN server will be up even if the WAN is down, (you can still use the VPN internally and stop your kids sniffing your FTP password :)). Select Config as Server, Server mode TUN, add in your chosen IP network and mask, choose your port, protocol encryption cypher and algorithm and apply settings.

Setting up the OpenVPN server from using the DD-WRT GUI.
Setting up the OpenVPN server from using the DD-WRT GUI.

Unfortunately, that’s not all there is to it. In the image above you can see entries for the Public Server Cert, the CA Cert, and the TLS Key. There’s also a Private Server Key and a DH PEM certificate to go along with those.

None of the above-mentioned certificates will be present and they need to be formed in a particular way for the server and the clients. The client certificates also need to be signed by the same root CA as the VPN server. All of that is covered in the next sections.

Creating the the certificates for a DD-WRT OpenVPN server

For the certificate creation, we’ll be using OpenSSL. It’s available for Windows as well as Linux, MAC, et al, it’s open-source and free to use for commercial or non-commercial purposes. Install it if you don’t have it already, make sure it’s in your path, then create a folder for your for CA and certificate files. I created a TestCA folder in my Home directory for this blog.

3: Open a terminal window for your OS and change to the directory you created for your certificates, (I’m using a Linux box so the tilda ~/ points to my Home directory.
cd ~/TestCA

Create a root certificate authority

4: Create the rootCA key, this is used to self sign the rootCA.crt and all of the client certificates going forward. You’ll be prompted for a password which you’ll need to sign certs going forward, so don’t forget it.
openssl genrsa -des3 -out rootCA.key 4096

5: Create the rootCA certificate, note, use at least sha256 and choose the number of days you’d like the certificate to last for. You’ll need the password for the rootCA.key you set up in the previous step.
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt
You’ll be prompted for various entries

At this point, your CA folder will have two certificates named rootCA.key and rootCA.crt and we have the first certificate required for the router, the CA Cert. Let’s go ahead and create two other certificates before doing the client certs in OpenSSL. The DH PEM and the TLS key.

Create the DH.pem and TLS.key certificates

6: Create the DH PEM certificate. There are no particular requirements for this one so the line below will generate the cert with no further intervention.
openssl dhparam -out DH.pem 2048

7: Create the TLS key, and we now have three of the five keys needed for the server.
openvpn –genkey –secret TLS.key
*careful when copying and pasting this line that the double hyphens –, doesn’t get pasted in your terminal as a single -.

Prepare files for creating the client certificates

8: We now need to create some files before we go on to create the certificates for the router (our OpenVPN server) and any clients that connect to it. The files also make creating the certificates a bit quicker because they’ll contain default values for most of the settings. You can choose your own names for the files but I went with the following, “openssl-server.cnf” with settings for the server, “openssl-client.cnf” with the client settings as well as “openssl-extensions-server.cnf” and “openssl-extensions-client.cnf” for the server and client extensions respectively.
The contents of the four files are below.

openssl-server.cnf
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = UK
stateOrProvinceName = stateOrProvinceName
stateOrProvinceName_default = County
localityName = localityName
localityName_default = Town
organizationalUnitName = Organizational Unit Name
organizationalUnitName_default = Street
commonName = commonName CN
commonName_default = server FQDN or YOUR name
commonName_max = 64
emailAddress = emailAddress
emailAddress_default = your@email.address
emailAddress_max = 40

[v3_req] keyUsage = keyEncipherment, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.yourFQDN.com
DNS.2 = *.yourFQDN.local

openssl-client.cnf
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = UK
stateOrProvinceName = stateOrProvinceName
stateOrProvinceName_default = County
localityName = localityName
localityName_default = Town
organizationalUnitName = Organizational Unit Name
organizationalUnitName_default = Street
commonName = commonName CN
commonName_default = server FQDN or YOUR name
commonName_max = 64
emailAddress = emailAddress
emailAddress_default = your@email.address
emailAddress_max = 40

[v3_req]
keyUsage = keyEncipherment, keyAgreement
extendedKeyUsage = clientAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.yourFQDN.com
DNS.2 = *.yourFQDN.local

openssl-extensions-server.cnf
[v3_ca]
keyUsage = keyEncipherment, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.yourFQDN.com
DNS.2 = *.yourFQDN.local

openssl-extensions-client.cnf
[v3_ca]
keyUsage = keyEncipherment, keyAgreement
extendedKeyUsage = clientAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.yourFQDN.com
DNS.2 = *.yourFQDN.local

So when we generate the CSR certificate signing request for each client we reference the openssl-server.cnf or openssl-client.cnf file and when we generate the certificate, we reference the openssl-extensions-server.cnf, or openssl-extensions-client.cnf file. The difference is in the EKU (clientAuth or serverAuth), but the values in the KU are important and must include at least one of the keyEncipherment or keyAgreement tags as explained here.

It might seem a bit long winded but the final .crt file needs to include the KU and EKU in the certificate and it isn’t carried across from the .csr. We can now generate the client’s CSR client files.

Create the client key and CSR files

9: First we need to generate a key file for each server or client.
openssl genrsa -out dd-wrt-server.key 2048

openssl genrsa -out client.key 2048

10: Then using the keys generated above we can create the CSR for each device.
openssl req -new -key ./dd-wrt-server.key -out ./dd-wrt-server.csr -config ./openssl-server.cnf

openssl req -new -key ./client.key -out ./client.csr -config ./openssl-client.cnf
For each of the steps, you can just press return and the defaults are accepted, you just need to choose a value for the CN when you get to it.
For the server, I went with dd-wrt-server and for the client, I chose to go with client. Imaginative!

Create the client certificates

11: So finally ladies and gentlemen, (drum roll) we can generate the certificates.
openssl x509 -req -in ./dd-wrt-server.csr -CA ./rootCA.crt -CAkey ./rootCA.key -CAcreateserial -out ./dd-wrt-server.crt -days 3650 -sha256 -extensions v3_ca -extfile ./openssl-extensions-server.cnf

openssl x509 -req -in ./client.csr -CA ./rootCA.crt -CAkey ./rootCA.key -CAcreateserial -out ./client.crt -days 3650 -sha256 -extensions v3_ca -extfile ./openssl-extensions-client.cnf

That’s all the files we need to connect one client to the DD-WRT OpenVPN server but first, we should probably check the files contain what’s required.

Checking the certificates

12: We can check the CSR of the server with the following
openssl req -in dd-wrt-server.csr -noout -text
and we can see that our CN is there and it include the requested extensions.

Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = UK, ST = County, L = Town, OU = Street, CN = dd-wrt-server, emailAddress = your@email.address
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:e8:34:15:
<content removed>
53:bd
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:.yourFQDN.com, DNS:.yourFQDN.local

Signature Algorithm: sha256WithRSAEncryption
49:e7:ef:cd:2
<content removed>
ab:75:2b:28

We can also check the CRT of the server with the following
openssl x509 -in dd-wrt-server.crt -noout -text
and we can see it has the required KU and EKU, who issued the certificate (the Issuer CN) and a few other things like the validity period.
Checking the client certificate should produce something similar, with the same issuer CN, but with the EKU set to TLS Web Client Authentication.

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
37:b6:01:32:a2:e1:bf:3d:1e:13:25:65:39:54:60:8e:a4:81:dd:2f
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = UK, ST = County, L = Town, O = Co, OU = Street, CN = YourCA.YourFQDN.com, emailAddress = your@email.address
Validity
Not Before: Mar 30 00:46:14 2020 GMT
Not After : Mar 28 00:46:14 2030 GMT

Subject: C = UK, ST = County, L = Town, OU = Street, CN = dd-wrt-server, emailAddress = your@email.address
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:e8:34:15:36:50:4e:b3:66:ca:29:e2:80:a4:88:
<content removed>
53:bd
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Key Encipherment, Key Agreement
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:.yourFQDN.com, DNS:.yourFQDN.local

Signature Algorithm: sha256WithRSAEncryption
7e:7a:41:1f:b6:6d:

13: We can now cut and paste all of the certificate details into the GUI for the DD-WRT router. The rootCA.crt goes into the CA Cert box, the DH.pem, into the DH PEM box, the TLS.key file into the TLS Key box. Finally the dd-wrt-server.crt goes into the Public Server Cert box and the dd-wrt-server.key goes into the Private Server Key box.
For each instance above open the file with a text editor and copy everything in the file, including the
—–BEGIN CERTIFICATE—–
—–END CERTIFICATE—–
and everything in-between.
For the key file
—–BEGIN RSA PRIVATE KEY—–
—–END RSA PRIVATE KEY—–
The DH.pem file will be slightly different again with
—–BEGIN DH PARAMETERS—–
—–END DH PARAMETERS—–
and the TLS.key file will have
—–BEGIN OpenVPN Static key V1—–
—–END OpenVPN Static key V1—–

14: Once that’s done, Apply Settings and we’re nearly done but we need to do a little more work on the client-side to connect.

Creating the VPN profile

15: Create a file for the VPN connection, in my case I created a file called dd-wrt-server.ovpn and it contained the below entries.

client
dev tun
proto tcp-client
remote 192.168.1.1 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca /home/username/TestCA/rootCA.crt
cert /home/username/TestCA/client.crt
key /home/username/TestCA/client.key
tls-auth /home/username/TestCA/TLS.key
–remote-cert-tls server
comp-lzo
verb 3
cipher AES-128-CBC
auth SHA256
key-direction 1
redirect-gateway def1

Now if we compare the settings in the file with the “Setting up the OpenVPN server from using the DD-WRT GUI” the second figure in the blog post we can see that the Server Mode is set to Tun, Tunnel Protocol is set to TCP. We can also see the Port 1194, and the Encryption Cypher AES-128-CBC and Hash Algorithm SHA256. The IP address used is the LAN IP of the router, which bears no relationship with the Network configured for the VPN, but is used to allocate IP addresses to the connected VPN clients. The redirect-gateway def1 line adds a default route to the connected client so that all traffic is tunneled via the VPN, (use it if you don’t need split-tunneling).

Initiating the connection from a linux terminal

16: You can import the above file into your VPN GUI client and connect that way or, for Ubuntu you can run the command below in a terminal window
sudo openvpn –script-security 2 –config ~/TestCA/dd-wrt-server.ovpn

Running the command in the terminal does have advantages, because you can see the logs as it tries to connect without checking the syslogs. We can see the VERIFY (for the CA and server certs), VERIFY KU, VERIFY EKU and route add messages among others, followed by Initialization Sequence Completed :).

Mon Mar 30 22:40:09 2020 OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on May 14 2019
Mon Mar 30 22:40:09 2020 library versions: OpenSSL 1.1.1 11 Sep 2018, LZO 2.08
Mon Mar 30 22:40:09 2020 Outgoing Control Channel Authentication: Using 256 bit message hash ‘SHA256’ for HMAC authentication
Mon Mar 30 22:40:09 2020 Incoming Control Channel Authentication: Using 256 bit message hash ‘SHA256’ for HMAC authentication
Mon Mar 30 22:40:09 2020 TCP/UDP: Preserving recently used remote address: [AF_INET]192.168.1.1:1194
Mon Mar 30 22:40:09 2020 Socket Buffers: R=[131072->131072] S=[16384->16384]
Mon Mar 30 22:40:09 2020 Attempting to establish TCP connection with [AF_INET]192.168.1.1:1194 [nonblock]
Mon Mar 30 22:40:10 2020 TCP connection established with [AF_INET]192.168.1.1:1194
Mon Mar 30 22:40:10 2020 TCP_CLIENT link local: (not bound)
Mon Mar 30 22:40:10 2020 TCP_CLIENT link remote: [AF_INET]192.168.1.1:1194
Mon Mar 30 22:40:10 2020 TLS: Initial packet from [AF_INET]192.168.1.1:1194, sid=beb33178 00992f2b
Mon Mar 30 22:40:10 2020 VERIFY OK: depth=1, C=UK, ST=County, L=Town, O=Co, OU=Street, CN=YourCA.YourFQDN.com, emailAddress=your@email.address
Mon Mar 30 22:40:10 2020 VERIFY KU OK
Mon Mar 30 22:40:10 2020 Validating certificate extended key usage
Mon Mar 30 22:40:10 2020 ++ Certificate has EKU (str) TLS Web Server Authentication, expects TLS Web Server Authentication
Mon Mar 30 22:40:10 2020 VERIFY EKU OK
Mon Mar 30 22:40:10 2020 VERIFY OK: depth=0, C=UK, ST=County, L=Town, OU=Street, CN=dd-wrt-server, emailAddress=your@email.address
Mon Mar 30 22:40:10 2020 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 2048 bit RSA
Mon Mar 30 22:40:10 2020 [dd-wrt-server] Peer Connection Initiated with [AF_INET]192.168.1.1:1194
Mon Mar 30 22:40:11 2020 SENT CONTROL [dd-wrt-server]: ‘PUSH_REQUEST’ (status=1)
Mon Mar 30 22:40:11 2020 PUSH: Received control message: ‘PUSH_REPLY,route-gateway 192.168.250.1,topology subnet,ping 10,ping-restart 120,socket-flags TCP_NODELAY,ifconfig 192.168.250.2 255.255.255.0,peer-id 0,cipher AES-256-GCM’
Mon Mar 30 22:40:11 2020 OPTIONS IMPORT: timers and/or timeouts modified
Mon Mar 30 22:40:11 2020 OPTIONS IMPORT: –socket-flags option modified
Mon Mar 30 22:40:11 2020 Socket flags: TCP_NODELAY=1 succeeded
Mon Mar 30 22:40:11 2020 OPTIONS IMPORT: –ifconfig/up options modified
Mon Mar 30 22:40:11 2020 OPTIONS IMPORT: route-related options modified
Mon Mar 30 22:40:11 2020 OPTIONS IMPORT: peer-id set
Mon Mar 30 22:40:11 2020 OPTIONS IMPORT: adjusting link_mtu to 1627
Mon Mar 30 22:40:11 2020 OPTIONS IMPORT: data channel crypto options modified
Mon Mar 30 22:40:11 2020 Data Channel: using negotiated cipher ‘AES-256-GCM’
Mon Mar 30 22:40:11 2020 Outgoing Data Channel: Cipher ‘AES-256-GCM’ initialized with 256 bit key
Mon Mar 30 22:40:11 2020 Incoming Data Channel: Cipher ‘AES-256-GCM’ initialized with 256 bit key
Mon Mar 30 22:40:11 2020 ROUTE_GATEWAY 192.168.1.1/255.255.255.0 IFACE=enp0s25 HWADDR=d8:9d:67:c7:b5:47
Mon Mar 30 22:40:11 2020 TUN/TAP device tun0 opened
Mon Mar 30 22:40:11 2020 TUN/TAP TX queue length set to 100
Mon Mar 30 22:40:11 2020 do_ifconfig, tt->did_ifconfig_ipv6_setup=0
Mon Mar 30 22:40:11 2020 /sbin/ip link set dev tun0 up mtu 1500
Mon Mar 30 22:40:12 2020 /sbin/ip addr add dev tun0 192.168.250.2/24 broadcast 192.168.250.255
Mon Mar 30 22:40:12 2020 /sbin/ip route add 192.168.1.1/32 dev enp0s25
Mon Mar 30 22:40:12 2020 /sbin/ip route add 0.0.0.0/1 via 192.168.250.1
Mon Mar 30 22:40:12 2020 /sbin/ip route add 128.0.0.0/1 via 192.168.250.1
Mon Mar 30 22:40:12 2020 WARNING: this configuration may cache passwords in memory — use the auth-nocache option to prevent this
Mon Mar 30 22:40:12 2020 Initialization Sequence Completed

At this point we can breathe a sigh of relief, because it’s all worked and we can test the connection.

Testing the VPN connection

17: Our before connections look like the below
We have one interface (apart from the loopback) The default Gateway is via the enp0s25 interface (192.168.1.1) and the first-hop traceroute is via that IP address as expected.

ifconfig
enp0s25: flags=4163 mtu 1500
inet 192.168.1.111 netmask 255.255.255.0 broadcast 192.168.1.255

netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 enp0s25
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s25

traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 64 hops max
1 192.168.1.1 0.375ms 0.236ms 0.202ms
2 192.168.43.1 122.537ms 2.970ms 3.965ms
3 * * *

18: Once connected to the VPN we have an extra tunnel interface 192.168.250.2. There are a couple of other routes that effectively redirect the default Gateway via the tun0 interface (192.168.250.1) and the first-hop traceroute is via that IP address as expected.

ifconfig
enp0s25: flags=4163 mtu 1500
inet 192.168.1.111 netmask 255.255.255.0 broadcast 192.168.1.255

tun0: flags=4305 mtu 1500
inet 192.168.250.2 netmask 255.255.255.0 broadcast 192.168.250.255

netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.250.1 128.0.0.0 UG 0 0 0 tun0
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 enp0s25
128.0.0.0 192.168.250.1 128.0.0.0 UG 0 0 0 tun0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s25
192.168.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 enp0s25
192.168.250.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0

traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 64 hops max
1 192.168.250.1 1.540ms 1.283ms 1.112ms

Creating a VPN connection in Ubuntu with the GUI

Of course, nobody wants to have to go through the trouble of opening the terminal, typing in sudo openvpn –script-security 2 –config ~/TestCA/dd-wrt-server.ovpn, then typing a password every time to connect to the VPN, and fortunately, there is an easier way.

19: To create a VPN connection in the GUI need to open the network settings menu.
1) Click on the network icon near the top right of the screen ( or if there isn’t a network icon, any of the icons in the top right will do.
2) Click the settings icon, (other options would have been to click any of the network drop-down icons and then settings).
3) Click Network, if it isn’t already selected.
4) Click the “+” plus sign to add a VPN.

Opening the dialogue to add a VPN connection in Ubuntu
Opening the dialogue to add a VPN connection in Ubuntu

20: From the following dialogue choose to Import from file.

Choosing to import VPN settings from a file in Ubuntu
Choosing to import VPN settings from a file in Ubuntu

21: Browse to the file and click open to be presented with the following dialogue. Check that all the certificates are included in the GUI and the settings look to as expected. You’ll have to open the advanced dialogue to check the TLS.key and you can also look for cipher and auth strength in there. If all looks ok click to add the VPN. You can click the certificate boxes to choose the certs if required.

The Add a VPN screen from the GUI in Ubuntu showing selected certificates
The Add a VPN screen from the GUI in Ubuntu showing selected certificates

22: To connect to the VPN now just requires clicking on the VPN switch either in the settings window (1), or (2), in the settings drop down from the top right, which is three clicks of the mouse at most. A successful connection is indicated if the switch changes to green (or blue in the drop-down) and remains so. To disconnect, just click the switch again.

Connecting to the DD-WRT router with the newly created VPN in Ubuntu.
Connecting to the DD-WRT router with the newly created VPN in Ubuntu.

If you want to be really secure you can include password authentication with a certificate which is explained on the dd-wrt wiki page here.

Setting up a profile for remote clients

Our profile .ovpn file contained pointers to the certificates by using absolute path descriptions, which is fine for some hosts, but what if your client doesn’t want the hassle of creating a folder for the certs, adjusting the profile to suit, etc can’t we just include all that in the file?

Well, you can do that. The file below is the one I created for my Android phone. I also created the client2.crt, and client2.key following the steps in the blog post above. I’ve hashed out the lines that I didn’t need, (I’m directly connected to the VPN router for testing so I didn’t want to tunnel al traffic, and I wanted to leave the commented lines in for the certs so you know which ones I’m using in the config below).

client
dev tun
proto tcp-client
remote 192.168.43.179 1194
resolv-retry infinite
nobind
persist-key
persist-tun
# ca /home/username/TestCA/rootCA.crt
# cert /home/username/TestCA/client2.crt
# key /home/username/TestCA/client2.key
# tls-auth /home/username/TestCA/TLS.key
–remote-cert-tls server
comp-lzo
verb 3
cipher AES-128-CBC
auth SHA256
key-direction 1
# redirect-gateway def1
<ca>
—–BEGIN CERTIFICATE—–
4c2BCPNqwG4E4xyuHrN8tl9Lth1SMi7TB8S+h1ulPKd4oDNSePQVjoob
—–END CERTIFICATE—–
</ca>
<cert>
—–BEGIN CERTIFICATE—–
ZkpVz1RPNBZXBVVssGhzDLLQS8v5c3+1LN5Vw2k/eqtq47HIWmSF6pA
—–END CERTIFICATE—–
</cert>
<key>
—–BEGIN RSA PRIVATE KEY—–
wIwKwYDVR0RBCQwIoIOKi55b3VyRlFETi5jb22CECoueW91ckZRRE4ubG
—–END RSA PRIVATE KEY—–
</key>
<tls-auth>
—–BEGIN OpenVPN Static key V1—–
LunFdc15TIQ1BRRqZaU1GtjTXzHqesdIoZiCK4UbastcDk0/cEZSRBSvfrvb
—–END OpenVPN Static key V1—–
</tls-auth>

Connecting to the DD-WRT router and beyond.

I tried a couple of OpenVPN clients before settling on OpenVPN for Android.
It was fairly straight forward to set up and it reconnects automatically if you make changes on the server end. I’ll be covering the import of the profile for that in another blog I’ve included a couple of screenshots below.

The image below shows an Android phone connected via FTP from the WAN side to the DD-WRT NAS using the tunnel address 192.168.250.1

Android phone connected to a DD-WRT router using FTP to access NAS storage
Android phone connected to a DD-WRT router using FTP to access NAS storage

The screenshot below is of the same phone connected to a laptop via SSH but this could just as easily be a VNC remote desktop session to a terminal server or jump server. In this case, both the server and client are VPN connected so the traffic is protected end to end

Android phone connected to a laptop with both clients connected via OpenVPN to the same DD-WRT OpenVPN server.
Android phone connected to a laptop with both clients connected via OpenVPN to the same DD-WRT OpenVPN server.

You should have access to LAN resources at this point. I didn’t have full access during testing but I was doing a few things out of the ordinary. I was using the WiFi as the WAN (connected to through the phone) and both the laptop and the phone were directly connected to the router. I was able to see ping packets reach the laptop when it wasn’t connected to the VPN and it was replying but the packets didn’t get back to the phone, so there were problems afoot.

Some Troubleshooting

After some investigation, I found that the packets were being dropped in the raw table of the router. If you are having problems such as with the tunnel not coming up, or with connectivity after the tunnel is up, then you can inspect the routers iptables.

If the tunnel doesn’t come up you should look at the filter INPUT table, and if you can’t access from the tunnel to the LAN or vice versa, you should look at the filter FORWARD table. If you can’t find issues in either then look at the raw PREROUTING and nat PREROUTING table.

For the openvpn tunnel to come up, since we chose TCP as the protocol, the INPUT table should be allowing TCP port 1194 (the default OpenVPN port) or whatever port number is chosen in the VPN setup GUI.

Checking the INPUT and FORWARD tables

23: To check the filter INPUT and filter FORWARD tables type in iptables -t filter -L -n -v either in the GUI or in the CLI. In the GUI type it in to the commands box and click on the “Run Commands” box and you should get the filter tables returned as in the image below.
In the Chain INPUT, we can see a line with a target of ACCEPT for prot (protocol) TCP on any interface from any source to any destination as long as it’s to tcp dpt:1194. There’s also been one packet and 60 bytes seen so we know it’s received packets.
Scrolling down to the Chain FORWARD, highlighted in grey, we can see ACCEPT for traffic from tun2 to any and to tun2 from any. We can also see packets from tun2 in, but nothing in the other direction, so there could be a problem there.

Checking the filter iptables in a DD-WRT router for allowed OpenVPN traffic
Checking the filter iptables in a DD-WRT router for allowed OpenVPN traffic

Checking the raw PREROUTING table

24: Repeat the above to check the raw PREROUTING table but type in iptables -t raw -L -n -v either in the GUI or in the CLI and you should get the filter tables returned as below. The raw table is the first checkpoint past the physical interface in the router stack, so if the packet isn’t seen there, you’re looking at a physical problem, maybe a one-way circuit, but if you can ping the tunnel address of the router from the client end, that won’t be it.

Checking the raw iptables in a DD-WRT router for allowed traffic
Checking the raw iptables in a DD-WRT router for allowed traffic

25: And there’s our problem, a DROP rule from any interface that isn’t tun2 (the preceding exclamation mark ! ahead of the tun2 means NOT), so this rule drops anything, not from tun2 destined for the address range 192.168.250.0/24. I could ping the LAN address of the router and get a reply, but the router reply never hits the raw PREROUTING table, the first hit for router sourced traffic is the raw OUTPUT chain which allowed everything in this case.
There’s a pretty good figure showing the path of traffic through the iptables chains here, with an in depth guide on iptables here.

26: You can add rules to the iptables by typing into the Commands window, we need to Insert a rule in the raw table at the top that allows our LAN traffic to the tunnel. Not only that but the rules have to survive a reboot. I had varying degrees of success by using the Save Firewall button and ended up inserting the fllowing code in the command window and clicking on Save Startup.
sleep 180; iptables -t raw -F
sleep 10; iptables -t raw -I PREROUTING -i br0 -s 0.0.0.0/0 -d 192.168.250.0/24 -j ACCEPT
sleep 10; iptables -t raw -A PREROUTING -i ! tun2 -s 0.0.0.0/0 -d 192.168.250.0/24 -j DROP
sleep 10; iptables -t raw -A PREROUTING -i ! oet1 -s 0.0.0.0/0 -d 192.168.251.0/24 -m addrtype –src-type ! LOCAL -j DROP
Reboot the router to see if it all sticks. The first line waits for 3 minutes before flushing the raw table, then puts an ACCEPT rule at the top followed by the other DROP rules (that were existing) in turn. Your rules and IP addresses will be different but you get the idea.

The options used in the above rule are -t (table), -I (insert, the default, if you don’t add a number after “PREROUTING” is to insert the rule at the top of the table), -s (source IP or subnet), -d (destination IP or subnet) and -j (jump, to action or another chain).

Other VPN options

There’s also another option to connect with end to end encryption that doesn’t need to connect through your home router and that’s to use Tailscale which is based on Wireguard and it’ll work through firewalls or NATs. It’s free for personal use and you can connect up to a hundred devices. You do need to register, but you can log in with a Gmail or Microsoft account.

One last thing before I wrap up. If you don’t want to redirect the default gateway with the “redirect-gateway def1” line in the OpenVPN profile, you can push routes (to the LAN for instance) from the DD-WRT server end by typing in push “route 192.168.1.0 255.255.255.0 192.168.250.1” in the additional config dialogue box or add a line like “route 172.16.10.2 255.255.255.255” to the profile and the routes will be added when the tunnel is up.

How to push a route to OpenVPN clients from the GUI of a DD-WRT router.
How to push a route to OpenVPN clients from the GUI of a DD-WRT router.

To cut a long story short, a summary.

This blog post covered the configuration of OpenVPN on a DD-WRT router.

It started by going over the steps to prepare the router, then covered setting up a root certificate authority and creating all of the certificates required in the correct formats for the completion of the connection.

It then described the steps required to create a VPN profile for the clients which included the required client-side certificates. It also showed how to import a profile into the current Ubuntu VPN client as well as testing from the CLI, which provided some useful troubleshooting information.

The article continued with some screenshots of connected VPN clients, followed by some suggested alternatives, and gave a couple of routing hints.

While connecting with a VPN client allowed us to reach Network Attached Storage on the router, and other connected VPN clients we needed to make changes to the iptables filters to get two-way communications between the VPN client and the LAN, and the article covered that too.

If you’re a network engineer and you could use an IPv4 subnet calculator (or if you just want the calculator) check out the free Techiedoodah IPv4 excel subnet calculator spreadsheet and if you get a lot of time hands-on rack side and need a tray to put your laptop on, let us know what you think of the Portable Rack Mount Laptop Tray and sign up if you want one. Type with two hands instead of one, be more comfortable, improve your productivity and get out of the server room sooner, (or wherever the rack happens to be).

Techiedoodah blogs are created in the hope that they can help others by giving real-life examples. If this has been useful to you please feel free to leave a comment. If you’re reading this post on the home page, you won’t be able to post comments here, so follow this link to the blog, and then scroll to the comments section at the bottom of the page.

Leave a Reply

Your email address will not be published. Required fields are marked *