WireGuard VPN using an EdgeRouter X

posted on 2018-08-12

The EdgeRouter X has the capability to run WireGuard, a fast VPN protocol that has matured enough in the last years to be ready for home use. My favorite VPN provider, AzireVPN (referral link), already has support for it as well and at the moment has even opened up the WireGuard connections for free to test the load and performance. That means that, for now, you should be able to get this all up and running for free.

To complete this example you will have to be familiar with the EdgeRouter SSH command line interface and know something about the configuration you already have up and running. You should also feel comfortable to install packages.

Installing WireGuard

First we need to get and install the WireGuard package, you can get it from https://github.com/Lochnair/vyatta-wireguard/releases

and for the EdgeRouter X you need the E50 package. Download the latest version and then upload it using, for example, scp to the /tmp folder on your EdgeRouter X.

Next run sudo dpkg -i /tmp/wireguard-e50-..... to install the package.

Getting WireGuard credentials from AzireVPN

To keep it simple, we let AzireVPN generate our private key and configuration.

After creating an account, log in and visit https://www.azirevpn.com/cfg/wireguard

Here you can download a zip file with configuration for the different VPN endpoints that they own.

Choose one location, like azirevpn-es1.conf and take not of your private key, the endpoint and public key of the endpoint.

Configuration

Now it's time to start configuring the interface and the routing.

Log into your EdgeRouter via SSH and start the configuration session with configure.

We start with the WireGuard interface and credentials:

edit interfaces wireguard wg0
set address <the ipv4 address you got>
set route-allowed-ips false

set peer ZcFmXAL9JWCQoS//5w9WRDKTzTcOlhXXNOX/8d/cSF8= endpoint es1.wg.azirevpn.net:51820
set peer ZcFmXAL9JWCQoS//5w9WRDKTzTcOlhXXNOX/8d/cSF8= allowed-ips 0.0.0.0/0

set private-key <the private key from the configuration file>
exit

The route-allowed-ips false will make sure that we have to set up routing by hand, which we are going to use to manually route only insecure traffic we want over the VPN later.

For this we start a new routing table with the default route over the wg0 interface.

set protocols static table 22 interface-route 0.0.0.0/0 next-hop-interface wg0

Next up, we make sure that any traffic that is sent out of the wg0 interface is masqueraded to the ip of the interface.

edit service nat rule 5222
set description "masquerade for wg0"
set outbound-interface wg0
set type masquerade
exit

For this example, we are going to only route some of the traffic over the VPN and leave the rest to run outside of the VPN. I consider traffic to SSH and HTTPS ports to be secure already, so let's create a group for these ports:

edit firewall group port-group secure_tcp
set port ssh
set port https
exit

Then we create a modify firewall rule set that will change the routing behavior of matched traffic to use the wg0 routing table we created earlier.

edit firewall modify lan_in_modify rule 20
set description wireguard
set protocol tcp
set destination group port-group !secure_tcp
set modify table 22
exit

This will match anything that is not considered a secure TCP port and apply the routing table we defined earlier (22) to that traffic.

To apply this rule to traffic on a given interface, we need to hook up the firewall rule. I've bonded together the local ports into a switch0 configuration so for me it's

set interfaces switch switch0 firewall in modify lan_in_modify

but you can choose any port you like to, for example, only have some local ports on VPN and the rest just directly connected to the internet.

That's it for the basic connection, use compare to see what you add and use commit to apply the current configuration. But we are not done yet, we need a firewall on the wg0 interface. These probably fit in with your current wan facing firewall and therefore I'm just giving a bare-minimal example for completeness here

First the firewall rules (don't forget to enter configure mode again)

set firewall name wan_in default-action drop
set firewall name wan_in description 'WAN to internal'
set firewall name wan_in rule 10 action accept
set firewall name wan_in rule 10 description 'Allow established/related'
set firewall name wan_in rule 10 state established enable
set firewall name wan_in rule 10 state related enable
set firewall name wan_in rule 20 action drop
set firewall name wan_in rule 20 description 'Drop invalid state'
set firewall name wan_in rule 20 state invalid enable

and then to apply them to the interface

set interfaces wireguard wg0 firewall in name wan_in

Also the connections from outside to wg0 should be protected, but keep in mind that the connection for WireGuard itself should still be allowed. Here we can use the firewall mark that the WireGuard driver adds. An example is:

set firewall name wan_local default-action drop
set firewall name wan_local description 'WAN to router'
set firewall name wan_local rule 10 description 'Allow established/related'
set firewall name wan_local rule 10 state established enable
set firewall name wan_local rule 10 state related enable
set firewall name wan_local rule 10 action accept

set firewall name wan_local rule 15 description 'accept wireguard'
set firewall name wan_local rule 15 mark 222
set firewall name wan_local rule 15 action accept

set firewall name wan_local rule 20 description 'Drop invalid state'
set firewall name wan_local rule 20 state invalid enable
set firewall name wan_local rule 20 action drop

set interfaces wireguard wg0 firewall in name wan_local

After all the commits (and if everything is working possibly a "save") you should have a simple WireGuard VPN connection for all but HTTPS and SSH.

The VPN connection may still be leaky if the route goes down, so this is by far a complete solution. Also, I still have to figure out the IPv6 support.

Happy hacking!