Configure ProtonVPN tunnel on a EdgeMAX EdgeRouter X (ERX) router

I use this configuration to send some traffic from my local network through a ProtonVPN tunnel to Canada.

   LAN (192.168.1.0/24, 192.168.10.0/24)  --  ERX  -- WAN (normal)
                                               |
                                           ProtonVPN (Canada)
                                               |
                                              WAN (via Canada)

192.168.1.0/24 is routed through the normal gateway. 192.168.10.0/24 is routed through ProtonVPN and all its traffic appears to come from Canada.

I explain how to replicate this setup below.

First, configure openvpn to connect to the ProtonVPN service.

We need to download the OpenVPN configuration file, and credentials from the ProtonVPN website.

1. Download the OpenVPN configuration file

Visit account.protonvpn.com/downloads and download the configuration file that you want, and save it to /config/auth/proton/ca.protonvpn.com.udp.ovpn (or similar).

In that file, replace auth-user-pass like this:

-   auth-user-pass
+   auth-user-pass "/config/auth/proton/auth"
+   pull-filter ignore "redirect-gateway"
+   pull-filter ignore "dhcp-option"
+   pull-filter accept "route-gateway"
+   pull-filter ignore "route"

Download OpenVPN Config

2. Save the ProtonVPN credentials

Visit account.protonvpn.com/account.

Username/Password

Copy the OpenVPN / IKEv2 username and OpenVPN / IKEv2 password to /config/auth/proton/auth on 2 lines, first the username, then the password.

Then, update the router configuration.

Now that we have everything we need to run OpenVPN, we can update the router configuration.

Before we start, it's a good idea to backup the existing configuration.

Login as admin, and run configure.

configure

Set some variables for convenience. Make sure to adjust as needed.

CFGFILE="/config/auth/proton/ca.protonvpn.com.udp.ovpn"
PROTONIF="vtun0"
LOCALNET="192.168.1.0/24"
LOCAL2TUN="192.168.10.0/24"
LOCAL2TUNADDR="192.168.10.1/24"

Turn up the openvpn interface. This is what actually runs openvpn.

set interfaces openvpn $PROTONIF config-file $CFGFILE
set interfaces openvpn $PROTONIF description "ProtonVPN to Canada"
set interfaces openvpn $PROTONIF mode client

Configure the firewall rules.

set firewall name PROTONVPN_IN default-action drop
set firewall name PROTONVPN_IN description "ProtonVPN to internal"
set firewall name PROTONVPN_IN rule 10 action accept
set firewall name PROTONVPN_IN rule 10 description "Accept established/related"
set firewall name PROTONVPN_IN rule 10 state established enable
set firewall name PROTONVPN_IN rule 10 state related enable
set firewall name PROTONVPN_IN rule 20 action drop
set firewall name PROTONVPN_IN rule 20 description "Drop invalid"
set firewall name PROTONVPN_IN rule 20 state invalid enable

set firewall name PROTONVPN_LOCAL default-action drop
set firewall name PROTONVPN_LOCAL description "ProtonVPN to router"
set firewall name PROTONVPN_LOCAL rule 10 action accept
set firewall name PROTONVPN_LOCAL rule 10 description "Allow established/related"
set firewall name PROTONVPN_LOCAL rule 10 state established enable
set firewall name PROTONVPN_LOCAL rule 10 state related enable
set firewall name PROTONVPN_LOCAL rule 20 action drop
set firewall name PROTONVPN_LOCAL rule 20 description "Drop invalid state"
set firewall name PROTONVPN_LOCAL rule 20 state invalid enable

set interfaces openvpn $PROTONIF firewall in name PROTONVPN_IN
set interfaces openvpn $PROTONIF firewall local name PROTONVPN_LOCAL

Enable masquerading for ProtonVPN WAN.

set service nat rule 100 description "masquerade for ProtonVPN"
set service nat rule 100 outbound-interface $PROTONIF
set service nat rule 100 protocol all
set service nat rule 100 type masquerade

Add the $LOCAL2TUNADDR address to switch0 if needed.

set interfaces switch switch0 address $LOCAL2TUNADDR

Define a Policy-Based Rule to route traffic from $LOCAL2TUN to the ProtonVPN tunnel.

set firewall group address-group RouteProtonVPN description "This group gets a default route to ProtonVPN"
set firewall group address-group RouteProtonVPN address $LOCAL2TUN

set protocols static table 100 interface-route 0.0.0.0/0 next-hop-interface $PROTONIF
set protocols static table 100 interface-route $LOCALNET next-hop-interface switch0 description LAN

set firewall modify PBR rule 100 description "Route to ProtonVPN"
set firewall modify PBR rule 100 modify table 100
set firewall modify PBR rule 100 source group address-group RouteProtonVPN

set interfaces switch switch0 firewall in modify PBR

In case the ProtonVPN service is down, prevent traffic from $LOCAL2TUN to go to the default gateway.

set firewall name WAN_OUT default-action accept
set firewall name WAN_OUT rule 100 action reject
set firewall name WAN_OUT rule 100 description "Block group routed to ProtonVPN"
set firewall name WAN_OUT rule 100 protocol all
set firewall name WAN_OUT rule 100 source group address-group RouteProtonVPN

Commit the changes.

commit; save

Optionally, route only some destinations through ProtonVPN.

We can also send only some destinations through ProtonVPN, but keep the default WAN gateway. The cherrypicked routes are added to table 110, and the local IP addresses that get them need to be added to the GetSomeRoutesToProtonVPN firewall group.

Run configure again, and use the same $PROTONIF as earlier.

configure

PROTONIF="vtun0"

The addresses in GetSomeRoutesToProtonVPN get cherrypicked routes to the ProtonVPN tunnel.

set firewall group address-group GetSomeRoutesToProtonVPN description "This group gets cherrypicked routes to ProtonVPN from table 110"

Add some local address(es) that will get the cherrypicked routes, e.g. 192.168.1.120:

set firewall group address-group GetSomeRoutesToProtonVPN address 192.168.1.120

Add routes to the ProtonVPN tunnel, e.g. polymtl.ca (132.207.0.0/16):

set protocols static table 110 interface-route 132.207.0.0/16 next-hop-interface $PROTONIF description polymtl.ca

Add the Policy-Based Routing rule.

set firewall modify PBR rule 110 description "Cherrypicked Routes to ProtonVPN"
set firewall modify PBR rule 110 modify table 110
set firewall modify PBR rule 110 source group address-group GetSomeRoutesToProtonVPN

Commit the changes.

commit; save