OpenWrt with NordVPN: OpenVPN

I own an OpenWrt router which I want connected to a VPN 24/7. Major VPN providers all support this scenario, however I currently have a NordVPN subscription so let's go with that for now.

There are 2 main options to run NordVPN on an OpenWrt router: OpenVPN and Wireguard. OpenVPN is the easiest but also slowest solution in terms of performance. Let's tackle this one first.

Source https://support.nordvpn.com/Connectivity/Router/1047411192/OpenWRT-CI-setup-with-NordVPN.htm

Installation of OpenVPN

Once you have a terminal connected to your OpenWrt server:

opkg update
opkg install openvpn-openssl
opkg install ip-full

To have a LuCI GUI with it

opkg install luci-app-openvpn

Once you have installed the OpenVPN package, you can make it launch automatically whenever the router starts:

/etc/init.d/openvpn enable

Download configuration file and store credentials

Easy as it gets. Next let's get a VPN conf. Head over to https://nordvpn.com/servers/tools/ to download a configuration. Click Show available protocols and then Download config for UDP or TCP. The file contains OpenVPN configuration files with the .ovpn extension. The file name in the archive defines the server’s country, number, and used protocol. For example, in the file name al1.nordvpn.com.ovpn, al stands for Albania, 1 is the server number, and tcp means TCP protocol.

The OpenVPN configuration for NordVPN requires you to input the username and password every time OpenVPN starts. To provide credentials automatically, append the word "secret" with a preceding space to the string auth-user-pass. The resulting string should be auth-user-pass secret.

Create a file with the name "secret" in the same folder and enter the credentials in it. The first line is your NordVPN service username, and the second is your NordVPN service password:

username
password 

You can find your NordVPN service credentials in the Nord Account dashboard at

Configure OpenVPN

Let's use the "al1.nordvpn.com.tcp.ovpn" file example:

1) Specify the file name in /etc/config/openvpn. You can use uci:

uci set openvpn.nordvpn=openvpn
uci set openvpn.nordvpn.enabled='1'
uci set openvpn.nordvpn.config='/etc/openvpn/al1.nordvpn.com.tcp.ovpn'
uci commit openvpn

The file /etc/config/openvpn should contain the following appended strings:

config openvpn 'nordvpn'
        option enabled '1'
        option config '/etc/openvpn/al1.nordvpn.com.tcp.ovpn'

Configure the network

Create a new network interface:

uci set network.nordvpntun=interface
uci set network.nordvpntun.proto='none'
uci set network.nordvpntun.ifname='tun0'
uci commit network

The file /etc/config/network should contain the following appended strings:

config interface 'nordvpntun'
        option proto 'none'
        option ifname 'tun0'

Create a new firewall zone and add a forwarding rule from LAN to VPN:

uci add firewall zone
uci set firewall.@zone[-1].name='vpnfirewall'
uci set firewall.@zone[-1].input='REJECT'
uci set firewall.@zone[-1].output='ACCEPT'
uci set firewall.@zone[-1].forward='REJECT'
uci set firewall.@zone[-1].masq='1'
uci set firewall.@zone[-1].mtu_fix='1'
uci add_list firewall.@zone[-1].network='nordvpntun'
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='lan'
uci set firewall.@forwarding[-1].dest='vpnfirewall'
uci commit firewall

The file /etc/config/firewall should contain the following appended strings:

config zone
        option name 'vpnfirewall'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'nordvpntun'
config forwarding
        option src 'lan'
        option dest 'vpnfirewall'

Now you need to configure the DNS servers. The simplest approach is to use NordVPN DNS for the WAN interface of the router. Here’s how to add NordVPN DNS:

uci set network.wan.peerdns='0'
uci del network.wan.dns
uci add_list network.wan.dns='103.86.96.100'
uci add_list network.wan.dns='103.86.99.100'
uci commit

The file /etc/config/network should contain the section 'wan' with the following strings (the three bottom strings have been appended):

config interface 'wan'
        option ifname 'eth0.2'
        option force_link '1'
        option proto 'dhcp'
        option peerdns '0'
        list dns '103.86.96.100'
        list dns '103.86.99.100' 

Hardening

This step is optional. To prevent traffic leakage in case the VPN tunnel drops, you can edit the file /etc/firewall.user with the following content:

# This file is interpreted as a shell script.
# Put your custom iptables rules here, and they will be executed with each firewall (re-)start
# Internal uci firewall chains are flushed and recreated on reload, so
# put custom rules into the root chains, e.g. INPUT or FORWARD, or into the
# special user chains, e.g. input_wan_rule or postrouting_lan_rule.
 
if (! ip a s tun0 up) && (! iptables -C forwarding_rule -j REJECT); then
       iptables -I forwarding_rule -j REJECT
fi

You should also create the file 99-prevent-leak in the folder /etc/hotplug.d/iface/ with the following content:

#!/bin/sh
if [ "$ACTION" = ifup ] && (ip a s tun0 up) && (iptables -C forwarding_rule -j REJECT); then
       iptables -D forwarding_rule -j REJECT
fi
if [ "$ACTION" = ifdown ] && (! ip a s tun0 up) && (! iptables -C forwarding_rule -j REJECT); then
       iptables -I forwarding_rule -j REJECT
fi

In some cases, OpenVPN hangs with a log message like “couldn't resolve host …”. In this case, the tunnel stays, but the connection is lost. You should reconnect it manually with the following script /etc/openvpn/reconnect.sh, which is added to /etc/rc.local as:

/etc/openvpn/reconnect.sh &

"reconnect.sh" should contain this script:

#!/bin/sh
n=10
while sleep 50; do
t=$(ping -c $n 8.8.8.8 | grep -o -E '[0-9]+ packets r' | grep -o -E '[0-9]+')
if [ "$t" -eq 0 ]; then
/etc/init.d/openvpn restart
fi
done

Page top