EdgeRouter Guided CLI Configuration

This is a long CLI recipe that I use for configuring EdgeRouter ER-4 for home network use. Of course, you could use the GUI built-in wizard, but what’s the fun in that?

This recipe covers at least:

  1. Setting up basic firewall, NAT, port forwards, static DHCP reservations. Support for PPPoE ISPs like Bell Canada Fibe to bypass the Home Hub 3000.
  2. Updating a dynamic DNS hostname (like at DNS Made Easy).
  3. Enabling an OpenVPN server for remote access.
  4. Failover between two internet connections.

Changelog

Preamble

There are plenty of guides on the internet. I’ve tried to make this one flexible; you can pick and choose what features you want, and you can (generally) copy/paste these commands and assemble a custom router that has the functionality you want.

I’ve been doing a few (remote) home network deployments/upgrades of Ubiquiti EdgeRouter ER-4 units. (The actual physical and logical configuration of the network is discussed separately from this post; I’ve been snagging the Brocade ICX7150-C12P switches that have been on eBay, and either connecting the cable, DSL or Fiber connection into a VLAN on the Brocade, then running a trunk VLAN to the EdgeRouter to handle NAT. Wireless is provided by Ruckus R710 access points running Unleashed firmware.)

Before you get started, I strongly recommend a USB to console cable (example) to ensure you always have direct CLI access to the router.

For an EdgeRouter ER-4, I’ve been following these steps:

Connect to the console, use the terminal client of your choice, 115200 baud, log in, and enter configure mode:

Login: ubnt
Password: ubnt

configure

Factory reset if needed, reboot, before starting from scratch

# factory reset and existing unit via console
sudo cp /opt/vyatta/etc/config.boot.default /config/config.boot
reboot

Next, set up the interfaces for LAN. Here, I’m using 10.116.0.1 as the ER’s IP address:

delete interfaces ethernet eth0 address 192.168.1.1/24
set interfaces ethernet eth0 address 10.116.0.1/24
set interfaces ethernet eth0 description eth0-LAN
set interfaces ethernet eth0 duplex auto
set interfaces ethernet eth0 poe output off
set interfaces ethernet eth0 speed auto

Optional: If you’re using VLANs and have an L3-aware internal switch handling intra-VLAN routing, add static routes to the switch’s virtual interface. Here, I assume the internal switch is at 10.116.0.254. Make sure you set the appropriate mirror static route on your switch so it knows how to access the EdgeRouter!

set protocols static route 10.0.0.0/16 next-hop 10.116.0.254 description locationname-core
set protocols static route 10.0.0.0/16 next-hop 10.116.0.254 distance 1

Next, configure eth2 for WAN.

#WAN: If your ISP just gives you an address via DHCP
set interfaces ethernet eth2 address dhcp
set interfaces ethernet eth2 address dhcpv6
set interfaces ethernet eth2 description eth2-WAN
set interfaces ethernet eth2 duplex auto
set interfaces ethernet eth2 firewall in name WAN_IN
set interfaces ethernet eth2 firewall local name WAN_LOCAL

#WAN PPPoE: If your ISP gives you a PPPoE login/password, we'll set up pppoe0 and attach it to eth2, and allow pppoe0 to get DNS servers from the PPPoE server
set interfaces ethernet eth2 duplex auto
set interfaces ethernet eth2 poe output off
set interfaces ethernet eth2 pppoe 0 default-route auto
set interfaces ethernet eth2 pppoe 0 firewall in name WAN_IN
set interfaces ethernet eth2 pppoe 0 firewall local name WAN_LOCAL
set interfaces ethernet eth2 pppoe 0 mtu 1492
set interfaces ethernet eth2 pppoe 0 name-server auto
set interfaces ethernet eth2 pppoe 0 user-id lorem
set interfaces ethernet eth2 pppoe 0 password ipsum
set interfaces ethernet eth2 speed auto

#WAN PPPoE Bell Canada: Bell Canada requires PPPoE sessions to be established on VLAN 35, and configure MTU/MSS clamping:
set interfaces ethernet eth2 address dhcp
set interfaces ethernet eth2 address dhcpv6
set interfaces ethernet eth2 description eth2-WAN
set interfaces ethernet eth2 duplex auto
set interfaces ethernet eth2 firewall in name WAN_IN
set interfaces ethernet eth2 firewall local name WAN_LOCAL
set interfaces ethernet eth2 speed auto
set interfaces ethernet eth2 vif 35 mtu 1500
set interfaces ethernet eth2 vif 35 pppoe 0 default-route auto
set interfaces ethernet eth2 vif 35 pppoe 0 mtu 1492
set interfaces ethernet eth2 vif 35 pppoe 0 name-server auto
set interfaces ethernet eth2 vif 35 pppoe 0 user-id lorem
set interfaces ethernet eth2 vif 35 pppoe 0 password ipsum
set firewall options mss-clamp interface-type pppoe
set firewall options mss-clamp interface-type all
set firewall options mss-clamp mss 1412

#Finally, if you have Bell IPTV, you'll need to clone your HomeHub's MAC address:
set interfaces ethernet eth2 mac 00:00:00:00:00:00

You may need to configure MTU clamping (as above) if you’re using PPPoE with Bell Canada Fibe and you’re using EdgeRouter to bypass the Bell Home Hub 3000.

If you have mulitple ISPs, you may wish to connect ISPA and ISPB to your switch on dedicated VLANs, then expose tagged traffic to the EdgeRouter, and have the EdgeRouter access both connections, on different VLANs. While this is obviously not ideal for fast links (as both would saturate 1Gbps eth2), this is probably fine if your backup link is relatively slow.

Now, on your machine, you can generate an ed25519 key to secure admin access to the router.

ssh-keygen -t ed25519 -C "user@domain.com"

… and use it to secure access to the router, set the admin password, disable UNMS and discovery, the default DNS/NTP servers, and turn on DPI on the router so you can see what kinds of traffic is flowing through.

set service gui http-port 80
set service gui https-port 443
set service gui older-ciphers disable
set service ssh disable-password-authentication
set service ssh port 22
set service ssh protocol-version v2
set service ubnt-discover disable
set service unms disable
set system host-name ubnt
set system login user ubnt authentication plaintext-password somethingveryLongAndVerySecure@$(T*WRKJHGWRKJGH
set system login user ubnt authentication public-keys ed25519-keyname key <publickey>
set system login user ubnt authentication public-keys ed25519-keyname type ssh-ed25519
set system login user ubnt level admin
set system name-server 8.8.8.8
set system name-server 4.2.2.1
set system ntp server 0.ubnt.pool.ntp.org
set system ntp server 1.ubnt.pool.ntp.org
set system ntp server 2.ubnt.pool.ntp.org
set system ntp server 3.ubnt.pool.ntp.org
set system time-zone UTC
set system traffic-analysis dpi enable
set system traffic-analysis export enable

Now, set up NAT so the LAN/eth0 is able to access the internet via eth2

set service nat rule 5000 description 'masquerade for WAN1'
set service nat rule 5000 log disable
set service nat rule 5000 outbound-interface eth2
set service nat rule 5000 protocol all
set service nat rule 5000 type masquerade

# If PPPoE, replace the relevant line above with:
set service nat rule 5000 outbound-interface pppoe0

And configure basic rules to forward ports:

set port-forward auto-firewall enable
set port-forward hairpin-nat enable
set port-forward lan-interface eth0
set port-forward wan-interface eth2

#Again, if PPPoE replace the relevant line with:
set port-forward wan-interface pppoe0

Configure the firewall next. Allow any established connections, and only permit creating certain kinds of inbound connections. Here, I have some “remote_admin” addresses that will always punch through the firewall, allowing remote administration. If you don’t want this, just don’t include any addresses in the group.

set firewall all-ping enable
set firewall broadcast-ping disable
set firewall group address-group remote_admin address <any static IP>
set firewall group address-group remote_admin address <any other static IP>
set firewall group address-group remote_admin description ''
set firewall group network-group network description ''
set firewall ipv6-name WANv6_IN default-action drop
set firewall ipv6-name WANv6_IN description 'WAN inbound traffic forwarded to LAN'
set firewall ipv6-name WANv6_IN enable-default-log
set firewall ipv6-name WANv6_IN rule 10 action accept
set firewall ipv6-name WANv6_IN rule 10 description 'Allow established/related sessions'
set firewall ipv6-name WANv6_IN rule 10 state established enable
set firewall ipv6-name WANv6_IN rule 10 state related enable
set firewall ipv6-name WANv6_IN rule 20 action drop
set firewall ipv6-name WANv6_IN rule 20 description 'Drop invalid state'
set firewall ipv6-name WANv6_IN rule 20 state invalid enable
set firewall ipv6-name WANv6_LOCAL default-action drop
set firewall ipv6-name WANv6_LOCAL description 'WAN inbound traffic to the router'
set firewall ipv6-name WANv6_LOCAL enable-default-log
set firewall ipv6-name WANv6_LOCAL rule 10 action accept
set firewall ipv6-name WANv6_LOCAL rule 10 description 'Allow established/related sessions'
set firewall ipv6-name WANv6_LOCAL rule 10 state established enable
set firewall ipv6-name WANv6_LOCAL rule 10 state related enable
set firewall ipv6-name WANv6_LOCAL rule 20 action drop
set firewall ipv6-name WANv6_LOCAL rule 20 description 'Drop invalid state'
set firewall ipv6-name WANv6_LOCAL rule 20 state invalid enable
set firewall ipv6-name WANv6_LOCAL rule 30 action accept
set firewall ipv6-name WANv6_LOCAL rule 30 description 'Allow IPv6 icmp'
set firewall ipv6-name WANv6_LOCAL rule 30 protocol ipv6-icmp
set firewall ipv6-name WANv6_LOCAL rule 40 action accept
set firewall ipv6-name WANv6_LOCAL rule 40 description 'allow dhcpv6'
set firewall ipv6-name WANv6_LOCAL rule 40 destination port 546
set firewall ipv6-name WANv6_LOCAL rule 40 protocol udp
set firewall ipv6-name WANv6_LOCAL rule 40 source port 547
set firewall ipv6-receive-redirects disable
set firewall ipv6-src-route disable
set firewall ip-src-route disable
set firewall log-martians enable
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
set firewall name WAN_LOCAL default-action drop
set firewall name WAN_LOCAL description 'WAN to router'
set firewall name WAN_LOCAL rule 10 action accept
set firewall name WAN_LOCAL rule 10 description 'Allow remote admin'
set firewall name WAN_LOCAL rule 10 log disable
set firewall name WAN_LOCAL rule 10 protocol all
set firewall name WAN_LOCAL rule 10 source group address-group remote_admin
set firewall name WAN_LOCAL rule 20 action accept
set firewall name WAN_LOCAL rule 20 description 'Allow established/related'
set firewall name WAN_LOCAL rule 20 state established enable
set firewall name WAN_LOCAL rule 20 state related enable
set firewall name WAN_LOCAL rule 90 action drop
set firewall name WAN_LOCAL rule 90 description 'Drop invalid state'
set firewall name WAN_LOCAL rule 90 state invalid enable
set firewall receive-redirects disable
set firewall send-redirects enable
set firewall source-validation disable
set firewall syn-cookies enable

Now we can commit and make sure the configuration we’ve done so far is sane/valid. And assuming no errors, save it, so a power cycle will reload this configuration.

commit
save

Next, we need DHCP/DNS for internal clients on LAN. The default scope here will issue IPs on the 10.116.0.0/24 subnet, and I’ve included a sample DHCP reservation by MAC address. The DNS forwarder on this router will cache some queries, and rely on 8.8.8.8 and 8.8.4.4 for name resolution.

set service dhcp-server disabled false
set service dhcp-server hostfile-update disable
set service dhcp-server shared-network-name LAN1 authoritative enable
set service dhcp-server shared-network-name LAN1 subnet 10.116.0.0/24 default-router 10.116.0.1
set service dhcp-server shared-network-name LAN1 subnet 10.116.0.0/24 dns-server 10.116.0.1
set service dhcp-server shared-network-name LAN1 subnet 10.116.0.0/24 lease 86400
set service dhcp-server shared-network-name LAN1 subnet 10.116.0.0/24 start 10.116.0.100 stop 10.116.0.250
set service dhcp-server shared-network-name LAN1 subnet 10.116.0.0/24 static-mapping R710-01 ip-address 10.116.0.100
set service dhcp-server shared-network-name LAN1 subnet 10.116.0.0/24 static-mapping R710-01 mac-address 'AA:BB:CC:DD:EE:FF'
set service dhcp-server shared-network-name LAN1 subnet 10.116.0.0/24 unifi-controller 10.116.0.50
set service dhcp-server static-arp disable
set service dhcp-server use-dnsmasq disable
set service dns forwarding cache-size 2048
set service dns forwarding listen-on eth0
set service dns forwarding listen-on switch0
set service dns forwarding listen-on vtun0
set service dns forwarding dhcp eth2
set service dns forwarding name-server 8.8.8.8
set service dns forwarding name-server 8.8.4.4
set service dns forwarding options expand-hosts
set service dns forwarding options bogus-priv
set service dns forwarding options localise-queries
set service dns forwarding options strict-order

You may wish to enable dhcp logging

set service dhcp-server global-parameters 'log-facility local2;'
set system syslog file dhcpd facility local2 level debug
set system syslog file dhcpd archive files 5
set system syslog file dhcpd archive size 5000

And you can view DHCP logs using…

show log file dhcpd

If you have any DNS entries you always want to resolve to specific internal IPs, you can use…

#static device
set system static-host-mapping host-name fqdn.sub.domain.com inet 10.116.0.100
#static domain forward to a specific server
set service dns forwarding options address=/domain.net/10.116.0.100

If you have internal services that you want to be remotely accessible, you can set up port forwards. If you will set up dual WAN, skip this step; we’ll do that with destination NAT below.

#setup port forwards with single WAN configurations (here I'm forwarding my WAN tcp/8022 to 10.116.0.50 tcp/22)
set port-forward auto-firewall enable
set port-forward hairpin-nat enable
set port-forward lan-interface eth0
set port-forward rule 1 description ssh
set port-forward rule 1 forward-to address 10.116.0.50
set port-forward rule 1 forward-to port 22
set port-forward rule 1 original-port 8022
set port-forward rule 1 protocol tcp

Enable smart-queue QoS to manage bufferbloat. Adjust the rate values as ~90% of what your speed test reports. You probably shouldn’t do this on an ER-X or ERLite (since they’re CPU constrained and can probably only handle a 50mbps connection), but ER-4 should handle this fine on (most) internet connections.

set traffic-control smart-queue Default download ecn enable
set traffic-control smart-queue Default download flows 1024
set traffic-control smart-queue Default download fq-quantum 1514
set traffic-control smart-queue Default download limit 10240
set traffic-control smart-queue Default download rate 115mbit
set traffic-control smart-queue Default upload burst 200kb
set traffic-control smart-queue Default upload ecn enable
set traffic-control smart-queue Default upload flows 1024
set traffic-control smart-queue Default upload fq-quantum 1514
set traffic-control smart-queue Default upload limit 10240
set traffic-control smart-queue Default upload rate 10mbit
set traffic-control smart-queue Default wan-interface eth2

Commit and save again.

commit
save

Upgrade to the latest firmware:

# Grab latest links at https://www.ui.com/download/edgemax
add system image https://dl.ui.com/firmwares/edgemax/v2.0.9-hotfix.2/ER-e300.v2.0.9-hotfix.2.5402463.tar
# or use 1.10.x branch (old)
add system image https://dl.ui.com/firmwares/edgemax/v1.10.11/ER-e300.v1.10.11.5274269.tar
# if you need to manipulate/explore, use:
show system image
show system image storage
delete system image

Backup your configuration with commands - so you can diff any changes.

# backup router config to /tmp - you can easily add cronjob to download and backup the configuration
sudo cli-shell-api showConfig --show-commands --show-active-only --show-ignore-edit --show-show-defaults > /tmp/edgerouter-backup-$HOSTNAME.commands.conf
#via https://github.com/tbyehl/edgerouter-backup/blob/master/config/user-data/hooks/03-edgerouter-backup.sh 
#via https://github.com/tbyehl/edgerouter-backup 

Configure IGMP Proxy for Bell Fibe IPTV

set protocols igmp-proxy interface eth0 role downstream
set protocols igmp-proxy interface eth0 threshold 1
set protocols igmp-proxy interface eth2.36 alt-subnet 224.0.0.0/8
set protocols igmp-proxy interface eth2.36 alt-subnet 10.0.0.0/8
set protocols igmp-proxy interface eth2.36 role upstream
set protocols igmp-proxy interface eth2.36 threshold 1

Configure EdgeRouter to update a Dynamic DNS hostname with DNS Made Easy

Create /config/dnsmadeeasy.sh

# https://support.dnsmadeeasy.com/support/solutions/articles/47001119947-the-ddns-shell-script
DMEUSER=yourDNSMadeEasyUserName

# This is your password
DMEPASS=SuperDuperSecretPassword

DDNS=somefqdnhostname.yourdomain.org

# This is the unique number for the record that you are updating.
# This number can be obtained by clicking on the DDNS link for the
# record that you wish to update; the number for the record is listed
# on the next page.
DMEID=12345678

# Obtain current ip address (here are two mechanisms; one uses the IP address on eth2, the other hits the internet and gets your WAN IP - pick one method)
IPADDR=`ip a | grep eth2 | grep inet | awk '{print $2}' | awk -F : '{print $0}' | cut -d '/' -f1`
IPADDR=$(curl --cacert /config/cacert --silent https://ipv4.icanhazip.com)

# Check what the current hostname resolves to; don't update if no update is required.
CURRENTDNS=`getent hosts $DDNS | awk '{ print $1 }'`

if [ "$CURRENTDNS" = "$IPADDR" ]; then
  logger -t DNS-Made-Easy -s "No IP change detected."
else
  if curl --cacert /config/cacert --silent -O /proc/self/fd/1 https://cp.dnsmadeeasy.com/servlet/updateip?username=$DMEUSER\&password=$DMEPASS\&id=$DMEID\&ip=$IPADDR | grep success > /dev/null; then
    logger -t DNS-Made-Easy -s "DNS Record Updated Successfully"
  else
    logger -t DNS-Made-Easy -s "Problem updating DNS record."
  fi
fi

Make it executable.

chmod +x dnsmadeeasy.sh

Ensure cacert exists for curl to validate certificates

sudo -i
cd /config
curl -o cacert -k https://curl.se/ca/cacert.pem

via https://daniel.haxx.se/blog/2018/11/07/get-the-ca-cert-for-curl/

Get the script to run periodically:

set system task-scheduler task ddns executable path /config/dnsmadeeasy.sh
set system task-scheduler task ddns interval 10m

Enable remote OpenVPN access

1. Basic setup first:

Add OpenVPN user, set a password.

configure
set system login user openvpn-user authentication plaintext-password SECR3TsuperlongT0Psecr3tpassword
set system login user openvpn-user level operator
commit
save

Make a folder to store OpenVPN config, and generate DH parameters:

sudo -i
mkdir /config/openvpn
cd /config/openvpn
openssl dhparam -out dh2048.pem -2 2048

Make the certificates good for ~10 years, so you don’t get locked out prematurely:

  1. export SSLEAY_CONFIG="-days 3650"
  2. Edit /usr/lib/ssl/openssl.cnf ; locate default_days, the default is 365, change it to 3650 or something large.
  3. Edit /usr/lib/ssl/misc/CA.pl and change CADAYS to –days 3650 for 10 years.

2. Create a local Certificate Authority (CA)

Remember the CApassword you pick; you’ll need it in subsequent steps!

/usr/lib/ssl/misc/CA.pl -newca

CA certificate filename (or enter to create): <enter>
Enter PEM pass phrase: <CApassword>
Verifying - Enter PEM pass phrase: <CApassword>
Country Name (2 letter code) [AU]: CA
State or Province Name (full name) [Some-State]: Ontario
Locality Name (eg, city) []: Toronto
Organization Name (eg, company) [Internet Widgets Pty Ltd]: Ipsum
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: My CA
Email Address []:
Please enter the following 'extra' attributes to be sent with your certificate request
A challenge password []:
An optional company name []:
Enter pass phrase for ./demoCA/private/./cakey.pem: <CApassword>

3. Generate request for a server certificate

Pick a temporary password for the private key; we’ll decrypt the key at the next step.

/usr/lib/ssl/misc/CA.pl -newreq

Generating a 2048 bit RSA private key
Enter PEM pass phrase: <tempserverkeypassphrase>
Verifying - Enter PEM pass phrase: <tempserverkeypassphrase>
Country Name (2 letter code) [AU]: CA
State or Province Name (full name) [Some-State]: Ontario
Locality Name (eg, city) []: Toronto
Organization Name (eg, company) [Internet Widgets Pty Ltd]: Ipsum
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: my.serverdomainname.org
Email Address []:
A challenge password []:
An optional company name []:

4. Now sign the server certificate:

/usr/lib/ssl/misc/CA.pl -sign

Enter pass phrase for ./demoCA/private/cakey.pem: <CApassword>
Sign the certificate? [y/n]: y
1 out of 1 certificate requests certified, commit? [y/n]: y

5. Rename it as the server certificate, and decrypt the private key now for usage

mv newcert.pem server.pem
mv newkey.pem server.key
rm newreq.pem
openssl rsa -in server.key -out server-decrypted.key
Enter pass phrase for /config/auth/server.key: <tempserverkeypassphrase>

6. Request a user certificate to enable remote access

/usr/lib/ssl/misc/CA.pl -newreq

Enter PEM pass phrase: <tempusercertpass>
Verifying - Enter PEM pass phrase: <tempusercertpass>
Country Name (2 letter code) [AU]: CA
State or Province Name (full name) [Some-State]: Ontario
Locality Name (eg, city) []: Toronto
Organization Name (eg, company) [Internet Widgets Pty Ltd]: Ipsum
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: openvpn-user
Email Address []:
A challenge password []:
An optional company name []:

7. Sign the user certificate

/usr/lib/ssl/misc/CA.pl -sign

Enter pass phrase for ./demoCA/private/cakey.pem: <CApassword>
Sign the certificate? [y/n]: y
1 out of 1 certificate requests certified, commit? [y/n]: y

8. Rename it as the user certificate, and decrypt the private key now for usage.

mv newcert.pem openvpn-user.pem
mv newkey.pem openvpn-user.key
rm newreq.pem
openssl rsa -in openvpn-user.key -out openvpn-user-decrypted.key
Enter pass phrase for /config/auth/openvpn-user.key: <tempusercertpass>

9. Set up the OpenVPN server in EdgeRouter CLI now

Since our internal subnet is 10.116.0.0/24, the VPN subnet will be 10.117.0.0/24 (non-overlapping), and tell remote clients that this VPN link allows them to access the internal subnet using push-route. Additionally, tell remote VPN clients to use the EdgeRouter as a DNS server.

exit #exit out of our previous sudo session so we're back in [configure]

set interfaces openvpn vtun0
set interfaces openvpn vtun0 description "OpenVPN server"
set interfaces openvpn vtun0 mode server
set interfaces openvpn vtun0 encryption aes256
set interfaces openvpn vtun0 hash sha256
set interfaces openvpn vtun0 server subnet 10.117.0.0/24
set interfaces openvpn vtun0 server push-route 10.116.0.0/24
set interfaces openvpn vtun0 server name-server 10.116.0.1
set interfaces openvpn vtun0 tls ca-cert-file /config/openvpn/demoCA/cacert.pem
set interfaces openvpn vtun0 tls cert-file /config/openvpn/server.pem
set interfaces openvpn vtun0 tls key-file /config/openvpn/server-decrypted.key
set interfaces openvpn vtun0 tls dh-file /config/openvpn/dh2048.pem
set interfaces openvpn vtun0 openvpn-option "--port 1194"
set interfaces openvpn vtun0 openvpn-option --tls-server
set interfaces openvpn vtun0 openvpn-option "--comp-lzo yes"
set interfaces openvpn vtun0 openvpn-option --persist-key
set interfaces openvpn vtun0 openvpn-option --persist-tun
set interfaces openvpn vtun0 openvpn-option "--keepalive 10 120"
set interfaces openvpn vtun0 openvpn-option "--user nobody"
set interfaces openvpn vtun0 openvpn-option "--group nogroup"
set interfaces openvpn vtun0 openvpn-option '--plugin /usr/lib/openvpn/openvpn-auth-pam.so openvpn'
commit

10. Allow OpenVPN traffic through the firewall, and listen for DNS requests at the tunnel.

set firewall name WAN_LOCAL rule 30 action accept
set firewall name WAN_LOCAL rule 30 description 'Allow openvpn'
set firewall name WAN_LOCAL rule 30 destination port 1194
set firewall name WAN_LOCAL rule 30 log disable
set firewall name WAN_LOCAL rule 30 protocol udp

set service dns forwarding listen-on vtun0

11. Finally, create your .ovpn profile/config file to use on the client.

client
dev tun
proto udp
remote <FQDN or WANIP of the Edgerouter> 1194
cipher AES-256-CBC
auth SHA256
resolv-retry infinite
redirect-gateway def1
nobind
comp-lzo yes
persist-key
persist-tun
user nobody
group nogroup
verb 3
setenv ALLOW_PASSWORD_SAVE 0 
auth-user-pass

<ca>
-----BEGIN CERTIFICATE-----
(Grab certificate from /config/openvpn/demoCA/cacert.pem and put it here!)
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
(Grab certificate from /config/openvpn/openvpn-user.pem and put it here!)
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN RSA PRIVATE KEY-----
(Grab private key from /config/openvpn/openvpn-user-decrypted.key and put it here!)
-----END RSA PRIVATE KEY-----
</key>

If you have a second WAN connection, and want EdgeRouter to failover between two connections:

# LAN is eth0
# Assume eth2 is Internet1
# Now we configure eth2 as Internet2
# https://ryanclouser.com/2016/10/22/Ubiquiti-EdgeRouter-Multi-WAN-Failover-and-Port-Forwarding/
# https://blog.voina.org/edgerouter-dual-wan-with-hair-pin/
# https://blog.voina.org/edgerouter-dual-wan-hair-pin-multiple-networks-openvpn-site-to-site-vpn/ 
# https://help.ubnt.com/hc/en-us/articles/205145990-EdgeRouter-WAN-Load-Balancing 

# Configure IP and connection on eth2
#WAN2: If your ISP just gives you an address via DHCP
set interfaces ethernet eth2 address dhcp
set interfaces ethernet eth2 address dhcpv6
set interfaces ethernet eth2 description eth2-WAN
set interfaces ethernet eth2 duplex auto
set interfaces ethernet eth2 firewall in name WAN_IN
set interfaces ethernet eth2 firewall local name WAN_LOCAL

#WAN PPPoE: If your ISP gives you a PPPoE login/password, we'll set up pppoe1 and attach it to eth2, and allow pppoe1 to get DNS servers from the PPPoE server
set interfaces ethernet eth2 duplex auto
set interfaces ethernet eth2 poe output off
set interfaces ethernet eth2 pppoe 1 default-route auto
set interfaces ethernet eth2 pppoe 1 firewall in name WAN_IN
set interfaces ethernet eth2 pppoe 1 firewall local name WAN_LOCAL
set interfaces ethernet eth2 pppoe 1 mtu 1492
set interfaces ethernet eth2 pppoe 1 name-server auto
set interfaces ethernet eth2 pppoe 1 user-id ipsum
set interfaces ethernet eth2 pppoe 1 password lorem
set interfaces ethernet eth2 speed auto

Configure NAT on eth2 so address translation will occur:

# if DHCP
set service nat rule 5001 description DSL
set service nat rule 5001 log disable
set service nat rule 5001 outbound-interface eth2
set service nat rule 5001 protocol all
set service nat rule 5001 type masquerade

# if PPPoE
set service nat rule 5001 description DSL
set service nat rule 5001 log disable
set service nat rule 5001 outbound-interface pppoe1
set service nat rule 5001 protocol all
set service nat rule 5001 type masquerade

# Add all your internal IPs to PRIVATE_NETS
set firewall group network-group PRIVATE_NETS network 10.116.0.0/16

set firewall modify balance rule 10 action modify
set firewall modify balance rule 10 destination group network-group PRIVATE_NETS
set firewall modify balance rule 10 modify table main

Prevent local LAN from being balanced across 2 WAN interfaces.

# If eth2 and eth2 are both DHCP:
set firewall modify balance rule 20 action modify
set firewall modify balance rule 20 destination group address-group ADDRv4_eth2
set firewall modify balance rule 20 modify table main

set firewall modify balance rule 30 action modify
set firewall modify balance rule 30 destination group address-group ADDRv4_eth2
set firewall modify balance rule 30 modify table main

# If eth2 is PPPoE and eth2 is DHCP: (for example - if both connections are pppoe, then use pppoe0 and pppoe1)
set firewall modify balance rule 20 action modify
set firewall modify balance rule 20 destination group address-group ADDRv4_pppoe0
set firewall modify balance rule 20 modify table main

set firewall modify balance rule 30 action modify
set firewall modify balance rule 30 destination group address-group ADDRv4_eth2
set firewall modify balance rule 30 modify table main

Send all other traffic to load balancing group

set firewall modify balance rule 110 action modify
set firewall modify balance rule 110 modify lb-group G

Apply firewall to LAN interface in the IN direction

set interfaces ethernet eth0 firewall in modify balance

Create load-balance group that includes eth2 and eth3

# If eth2 and eth2 are DHCP use:
set load-balance group G interface eth2
set load-balance group G interface eth3
# If eth2 is PPPoE, and eth3 is DHCP use:
set load-balance group G interface pppoe0
set load-balance group G interface eth3

If you want to use eth3 only as failover:

set load-balance group G interface eth3 failover-only

Configure how [quickly] a connection is determined to be down, or how quickly it is up again, and what target is used to determine if the connection is up.

set load-balance group G interface eth2 route-test count success 5
set load-balance group G interface eth2 route-test count failure 2

set load-balance group G interface eth2 route-test initial-delay 30
set load-balance group G interface eth2 route-test interval 5

set load-balance group G interface eth2 route-test type ping target ping.ubnt.com
set load-balance group G interface eth2 route-test type default

set load-balance group G lb-local-metric-change enable

Check/verify load balancing status with: (parse this output with scripts for additional monitoring)

show load-balance status
show load-balance watchdog

See what IP addresses are configured on Edgerouter:

run show interfaces

See what IPs have been distributed by DHCP:

show dhcp leases

See what MAC addresses are present:

show arp

See also: