Switching to OpenWrt: OpenVPN client setup differences

As an avid DD-WRT user for a long time, I recently made the switch to OpenWrt for my next router upgrade, the Linksys WRT3200ACM. While both firmware’s are Linux based they are fundamentally different. Join me on my adventure with OpenVPN configuration comparing the two setups.

This is something that caught me out initially. A lot of users of DD-WRT/OpenWrt users often setup a OpenVPN client on the router to route traffic through a VPN gateway for privacy. This is often in conjunction with providers like Private Internet Access, ExpressVPN, NordVPN etc. (not an endorsement, although I do use Private Internet Access).

One key difference that DD-WRT does by default which OpenWrt does not is prevent your gateway being redirected when connected.

Most OpenVPN servers will use the configuration of redirecting the client’s gateway, this is achieved like so:

push "redirect-gateway def1"

This will essentially redirect all your traffic through the VPN gateway when active. DD-WRT prevents this server side configuration, by automatically adding pull-filter ignore "redirect-gateway" to your client config, this is visible in the source code. In older DD-WRT builds this would have been route-noexec. The former is better to use (if supported) because it allows you to still use the route command. This will stop the default gateway being modified. OpenWrt on the other hand doesn’t do anything to prevent this by default and hence your router gateway and any client that connects will be sent through the VPN by default. Arguably, you might say isn’t this the whole point? Well yes, but actually no.

DD-WRT routers actually break if you try and send the router itself through an OpenVPN tunnel or include it in any VPN routing policy, due to the custom routing setup it has. OpenWrt being more vanilla, doesn’t break and will work fine, but in a lot of cases, it’s not ideal and arguably, does your router itself really need to go through a VPN?

If your router itself does go through a VPN, without additional handling you’ll essentially lose external access to your WAN. As soon as your router and it’s traffic goes through the VPN, pinging your WAN IP will be met with request timeouts (if ICMP is allowed in your firewall), port forwarding for LAN clients will not work as the traffic won’t go through the right interface, if you use a 6in4 tunnel i.e. Hurricane Electric, you’ll break your IPv6 tunnel, because your IPv4 endpoint won’t be your WAN IPv4 but the VPN and many other issues you might not have even had to think about as a DD-WRT does this by default.

You can fix some of these issues with IPv4 static routes with OpenWrt, but these aren’t ideal especially when you have a dynamic IP address from your ISP. Instead, you should consider preventing the gateway from being modified and then using policy based routing to route your traffic through the VPN conditionally. To prevent your default gateway being modified, you can by apply one of the following lines to your OpenVPN client config, depending on the version of OpenVPN installed:

# OpenVPN 2.4 client config
list pull_filter 'ignore "redirect-gateway"'
# OpenVPN 2.3 client config
option route_nopull '1'

This prevents the OpenVPN client modifying your default gateway. When the OpenVPN connection is established, you will have an active connection to your VPN, but your router won’t be directing any traffic through it by default. The next step is implementing something called policy based routing (PBR).

Unlike DD-WRT, OpenWrt doesn’t include any policy based routing functionality by default. You can of course build this yourself with CLI wizardry. However, there is an excellent VPN Policy-based Routing package by stangri which will do the heavy lifting of building out the required routing, traffic marking, iptables (firewall) and main configuration work needed for it. You’ll need to add a custom repo to have access to this package through opkg, but it’s fairly easy to get setup and installed using the comprehensive README.md.

It’s a very well documented package and integrates with LuCI (OpenWrt router web interface), however it’s config file /etc/config/vpn-policy-routing can be much easier to work with for larger configurations and changes. It offers a variety of routing options to conditionally target including:

  • IP source/destination address(es) src_addr dest_addr
  • Specific source/destination ports src_port dest_port
  • DNS based rules with domains dest_addr
  • IPv6 support and more!

Domain based policies require ipset, which itself requiresdnsmasq-full.

The dnsmasq + ipset combo has become a popular split tunnel VPN approach for when targeting raw IP addresses becomes too challenging or cumbersome. Particularly for services like Netflix which has vast amounts of IP addresses through many CDNs that rotate regularly.

For larger rulesets, you can even use the Custom User Files option, allowing you to add large amount of IP addresses to a chain.

ipset has the advantage of being able to use domain based policies but also automatically matching any sub domain underneath the root domain. As an example, if you had bbc.co.uk as a policy, this would also match sub.bbc.co.uk or sub.sub.bbc.co.uk .

Examples of policies with VPR:

Depending on your interface naming scheme the option interface value may differ, these examples are using the most common naming conventions likely to be used.

Single LAN client (All traffic through WAN):

config policy
option name 'Local IP'
option interface 'wan'
option src_addr '192.168.1.70'

LAN clients within a specific CIDR range (All traffic through VPN):

config policy
option name 'Local Subnet'
option interface 'vpn'
option src_addr '192.168.1.100/30'

Domain based policy (All traffic through the WAN):

config policy
option name 'Bypass Test'
option interface 'wan'
option dest_addr 'ifconfig.me'

Source port policy (All traffic through the WAN):

config policy
option name 'Plex Media Server'
option interface 'wan'
option src_port '32400'

These are just basic examples, there are many other policies and combinations.

The key point about policy based routing is it gives you flexibility and control of what traffic will go through the VPN and what doesn’t.

The policy priority is the same as its order as listed in Web UI and /etc/config/vpn-policy-routing. The higher the policy is in the Web UI and configuration file, the higher its priority is. The exception with ipset rules is they take priority over any ordering in the config file.

The general concept uses a combination of various tools and routing techniques to achieve the result. Mostly the concept is based around fwmark (traffic control filter), iptables and setting up custom routing tables to support both the WAN and VPN routes. In the case of the VPR package:

  • Traffic for the WAN has the fwmark value of: 0x010000
  • Traffic for the VPN has the fwmark value of: 0xff0000

The mark values are deliberately set to a high value to avoid conflicting with other mark values that may be in use.

Essentially, all of the policy examples are a friendlier way to wrap around raw CLI commands to mark traffic to either the WAN or VPN. This package is doing the heavy lifting for you, so you have a consistent interface to create rules which get translated into the required CLI config to work with OpenWrt. You can peak at what the package is doing from the source code:

https://github.com/stangri/openwrt_packages/tree/master/vpn-policy-routing/files

Many VPN guides will talk about VPN killswitches. In the case of Linux routers, this is usually specific iptables rules that stops any traffic using your WAN gateway if the VPN interface goes down to avoid leaks. It’s worth noting the VPR package is not compatible with such rules due to it’s own routing setup, so avoid using them here.

Instead, you should define an explicit policy for the VPN and make sure you have strict enforcement enabled. This is an equivalent approach. By specifying a explicit policy and the VPN going down, a client will not have access to the WAN. This does potentially mean however during start-up or if the VPN Policy Routing services goes down, you could get traffic leaks, because these rules will not be enforced by this package.

As an additional measure, you could add an additional custom firewall rule, to always make sure a client or a number of clients cannot use the WAN, regardless of any VPR policy. An example of this could be:

iptables -I FORWARD -s "$LAN_CLIENT" -o "$WAN_IF" -m state --state NEW -j REJECT --reject-with icmp-host-prohibited

As I mentioned in the beginning I had been a long time DD-WRT user and only recently made the switch to OpenWrt. From the point of view of setting up a split tunnel VPN approach on both firmware’s using the same concepts, I would have to say that it is easier on OpenWrt than DD-WRT. Despite the difference in configuration and learning a slightly different OS, OpenWrt has far simpler extendability capabilities.

At this time of writing, the dnsmasq version DD-WRT ships does not have ipset support enabled which while isn’t mandatory for a lot of policies, it’s pretty much a must for domain based policies for this approach. In addition, DD-WRT does not have the ipset binary available and is missing the critical xt_set module for iptables. On top of all that the iptables DD-WRT uses is a custom compiled version that is older and doesn’t have support for the critical — match-set directive. In order to have these on DD-WRT you would need to do a combination of compiling these userland tools yourself and/or use Entware.

DD-WRT also requires you to make additional modifications to the routing table, to workaround a few bugs/issues with the policy based routing setup.

OpenWrt on the other hand, it’s a case of a couple of opkg install commands and your done.

DD-WRT is still an excellent firmware choice and supports a wider set routers, including Broadcom SOC based routers (which OpenWrt will struggle with because of it’s FOSS philosophy). However for extending the default software set, OpenWrt wins in this regard.

This is really just a general overview about the VPR package with OpenWrt and what the possibilities are, for further help and support you can go to the OpenWrt forums where the developer, stangri actively responds:

Thanks Stangri, for creating this great package and making VPN policy based routing much simpler on OpenWrt!

I'm a web developer, but also like writing about technical networking and security related topics, because I'm a massive nerd!