I spent too much time trying to get OpenVPN fully working on my DD-WRT router. All the documentation I found was either outdated or seemed overly complicated given the GUI options available in my build. This post is my attempt to document a full and working configuration of an OpenVPN server on a DD-WRT router.
My router is a Linksys WRT1900AC v2 running DD-WRT v3.0-r29048 std.
When looking for documentation this thread on the DD-WRT forums gave me the idea that it should in fact be easier than most documentation states. And it basically is!
These are the catches that added complication to the configuration:
- Bridged TAP mode isn’t supported on iOS necessitating TUN for me
- DNS doesn’t push to clients out of the box
- TUN setups need a NAT rule to access the Internet via VPN
Below are steps to get things working as per my setup. The details really aren’t critical as long as they match within your config and between your server and clients. My LAN is 192.168.166.0/24 (netmask 255.255.255.0) so in theory all you should have to do to get things up is replace that network with yours in the steps below.
1.) Create your certs and keys following the official instructions here. Generating these isn’t specific to DD-WRT so there are plenty of resources available. I’d say generate more than you need so you won’t need to revisit if you need more — generation is a bit of a pain.
2.) Configure settings in “Services” > “VPN” as below.
- OpenVPN: Enable
- Start Type: WAN Up
- Config as: Server
- Server mode: Router (TUN)
- Network: 192.168.88.0
- Netmask: 255.255.255.0
- Port: 1194
- Tunnel Protocol: UDP
- Encryption Cipher: AES-256 CBC
- Hash Algorithm: SHA1
- Advanced options: Yes
- TLSCiphter: No
- LZO Compression: Yes
- Redirect default Gateway: Disable (I have this disabled so I can choose on the client side whether or not to route all traffic over the VPN).
- Allow Client to Client: Enable
- Allow duplicate cn: Disable
- Tunnel MTU setting: 1500
- Tunnel UDP Fragment:
- Tunnel UDP MSS-Fix: Disable
- CCD-Dir DEFAULT file:
- Client connect script:
- Static Key:
- PKCS12 Key:
- Public Server Cert: Paste yours in
- CA Cert: Paste yours in
- Private Server Key: Paste yours in
- DH PEM: Paste yours in
If you want to resolve DNS names over the VPN you will need to add the below lines to “Additional Config.” If this isn’t the case you need no further configuration on this page.
push “dhcp-option DNS 192.168.88.1”
push “dhcp-option DOMAIN HOME”
push “route 192.168.166.0 255.255.255.0”
Here’s how it looks in the DD-WRT GUI:
Here’s a breakdown of what’s going on:
- A route is pushed to clients so that they will go to DD-WRT for requests on the LAN network (192.168.166.0/24 for me).
- The local DNS server at 192.168.166.1 is pushed to clients so they can make queries on the server’s network.
- The domain is specified so hostnames will resolve without specification.
At this point you can click “Apply Settings”
4.) If you are using DD-WRT as a DNS server you’ll need to tell DNSMasq to listen for requests on the interface your VPN clients will query on. To do this you’ll need to figure out what interface that is. You can find this in the GUI by clicking “Setup” > “Advanced Routing” > “Routing Table.” In there you’ll see a route that specifies the tun adapter you are using.
Take that piece of information and navigate to “Services” > “Services.” Scroll down to “Additional DNSMasq Options” and enter
where # is the number you pulled from routing table.
This is how it looks for me:
5.) At this point VPN clients exclusively have access to the LAN due to the lack of a NAT rule. Navigate to “Administration” > “Commands,” click “Edit” in the “Firewall” commands and add
iptables -t nat -A POSTROUTING -s 192.168.88.0/255.255.255.0 -j MASQUERADE
After clicking “Save Firewall” you should see your rule, see below:
Here’s the breakdown of what’s going on:
- iptables is the program that does packet filtering in Linux.
- The -t nat argument and parameter specifies that we will be working with the NAT table in iptables.
- The -A POSTROUTING argument and parameter appends the rule to the POSTROUTING processing chain.
- The -s argument and parameter filters the rule to apply to packets coming from our VPN network. These need to match the network you specified in step 2 (iptables will accept either a netmask (e.g. 255.255.255.0) bitmask (e.g. /24)).
- -j MASQUERADE tells iptables to masquerade the packet as coming from the router itself — this is the part that makes the NATing happen.
Finally you’ll need your client side config. I’m using this:
remote private.veryprivate.superprivate;) 1194
You’ll need to add your own target after remote.
If you want all traffic to go over the VPN just add:
As you can see things are basically default and matching my server settings.
Hopefully this helps somebody!