DD-WRT Routed OpenVPN Server Configuration with Split Tunneling Support

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

See below:

ovpn config

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:

ovpn-addl-config

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.

For me:

routintable

Take that piece of information and navigate to “Services” > “Services.”  Scroll down to “Additional DNSMasq Options” and enter

interface=tun#

where # is the number you pulled from  routing table.

This is how it looks for me:

dnsmasq config

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:

Firewall config

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
client
dev tun
proto udp
resolv-retry infinite
nobind
persist-key
persist-tun
cipher aes-256-cbc
float
tun-mtu 1500
ca ca.crt
cert client0.crt
key client0.key

ns-cert-type server
comp-lzo
verb 3

You’ll need to add your own target after remote.

If you want all traffic to go over the VPN just add:

redirect-gateway def1

As you can see things are basically default and matching my server settings.

That’s it!

Hopefully this helps somebody!

15 thoughts on “DD-WRT Routed OpenVPN Server Configuration with Split Tunneling Support”

  1. You’ve got a couple of notes up there saying “Paste yours in” but perhaps you could be more specific about it? The field asks for “Public Server Cert”, and the files I’ve got generates from the OpenVPN instructions, that start with server* are: server.crt, server.csr, and server.key.

    Thank god someone finally wrote an updated VPN server howto. Thanks!

  2. Under “Additional Config” I put in what you’ve got there. As soon as I hit Save, then Apply Settings, it changes!

    from what you’ve got:
    push “dhcp-option DNS 192.168.88.1”
    push “dhcp-option DOMAIN HOME”
    push “route 192.168.166.0 255.255.255.0”

    Save, Apply Changes: into this:
    push “dhcp-option DNS 192.168.88.1”
    push “dhcp-option DOMAIN HOME”
    push “route 192.168.11.0 255.255.255.0”

    re-typed in Notepad, without smart quotes
    push “dhcp-option DNS 192.168.88.1”
    push “dhcp-option DOMAIN HOME”
    push “route 192.168.11.0 255.255.255.0”

    and that seems to stick without getting defaulted into it’s ASCII hex code.

  3. This is nice that it is up to date. It _almost_ works for me.
    My ASUS RT-N66U router, using build r29048, just as you did, plus trying several others, I have the following problem:
    The value for “server” is not saved and therefore, not in the resulting openvpn.conf file.
    The config line ends up:
    server 255.255.255.0
    missing the IP address of the VPN server.
    If I put the IP address in the mask box, the result becomes:
    server 192.168.3.0 with no mask value.
    I tried 192.168.3.0/24 but it rejected that.
    Any ideas how to work around this bug?

    1. Hi, were are you putting this info exactly? Client side?
      It sounds like you are either in the DD-WRT OpenVPN client settings or somehow generating a client .conf file with a tool.

  4. Hi,
    I followed your instructions and I am stuck where the ROUTING TABLE does not show me the “tun2” interface for the 192.168.88.0
    Also I am trying to understand who is handling the DHCP requests for your 192.168.88.0 VPN network?

    1. You should have a corresponding tun interface. Just replace the “tun2” I have with whatever your tun virtual interface is called.
      DHCP is provided by the router by DNSMasq.

  5. Hi,

    I can’t browse internet trough openvpn, unless i push some external dns server, and add these firewall rules:

    iptables -I FORWARD -i br0 -o tun+ -j ACCEPT
    iptables -I FORWARD -i tun+ -o br0 -j ACCEPT
    iptables -I FORWARD 1 –source 10.8.0.0/24 -j ACCEPT
    iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE

    What I’m missing? i want dnsmasq to be the dns.

    Thanks

    1. Can’t quite say, a few things could be wrong.
      Is DNSMasq set up to either recursively resolve or forward external DNS requests?
      If you are able to resolve local DNS names we’re definitely outside the scope of this tutorial — not saying I can’t help if you respond, just that I might be tardy in doing so.

  6. Thanks a lot! this works perfectly. The only thing I can’t figure out is how to re-direct dns requests for public sites back to my locally set DNS servers. For instance, if i do nslookup on google.com, my ww-drt router resolves the entry instead of my local DNS. I don’t want to route all DNS requests over VPN cause its way too slow. Any suggestions? (using windows 10)

    1. I’ve run into this too.
      Since this is a client side thing I can think of two options:
      1 — use your client’s “run script on connection” function to modify local DNS resolution behavior.
      2 — run a DNS server on your client machine and use that for all DNS resolution — this will probably give you the most granular control over DNS resolution but does incur the overhead of running a local DNS server.
      Not super helpful, sorry 🙁

    2. Hey Dominic, update:
      I’ve successfully used a tiny DNS resolver called “Deadwood” to intelligently route DNS requests on client machines. I’ve so far only tested it out on Windows in a point-to-point VPN environment but it should work in the article’s context as well.
      In this context steps should be:
      1. Install Deadwood to run as a service (according to best practice on your OS — I know Deadwood can install itself as a service on Windows)
      2. Configure Deadwood to forward requests for your remote domain to your router
      3. Configure Deadwood to forward all other requests to something like Google
      4. Either push “127.0.0.1” as your DNS server from the VPN server or run a client side script that does the same — latter option here may be preferable if you still want things to basically work on devices without a local DNS resolver installed

  7. Hi Marty,
    Thanks for the guide, but I’m stuck at the routing table. My vpn server LAN (192.168.88.0 in your example) is not showing in my routing table. Did you have to set this up in the static routing configuration above the “show routing table” link? That’s the only way I can get it to show up, but I don’t have an option for the tun interface. I appreciate any help you can provide.

    1. My routing entry set itself up with the input from the GUI. I didn’t have to manually enter any routing details.
      Do you see anything equivalent if you SSH to your DD-WRT box and run ifconfig?
      Any luck if you add the route yourself?
      Marty

Leave a Reply to Drew Cancel reply

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