OpenVPN Server on the EdgeRouter Lite
Preface
In this guide I’ll describe setting up OpenVPN server on a Ubiquiti EdgeRouter Lite. We’ll be using x.509 certificates for authentication of the server and client.
EdgeMax OS Version: 1.7 (Updated for 1.8)
I also have a guide for IPSec server, here.
If you’re undecided between OpenVPN and IPSec, I outline my preference here.
SSL Key and Cert Setup
These steps are nearly identical to the IPSec guide. Just note there’s a difference regarding the private key format.
First, generate a Certificate Authority certificate. This will be used to sign both the server certs AND the client certs. This is how the VPN server and client authenticate each other.
# Switch to root. You’ll need the permissions for writing to certain directories.sudo su
cd /usr/lib/ssl/misc/
./CA.sh -newca
You’ll have created a new directory called /usr/lib/ssl/misc/demoCA.
Now we’ll generate the keys and cert for the server (our ERL in this case) and critically, sign the server cert with our new CA.
# Create server keys and certificate.
./CA.sh -newreq# Sign the server cert with our new CA cert.
./CA.sh -sign
Let’s save our work onto the config partition.
# Save the CA key and cert.
cp demoCA/cacert.pem demoCA/private/cakey.pem /config/auth/# Save our server cert.
mv newcert.pem /config/auth/server.pem
Now we’ll decrypt the server key and leave it in PEM format. The ERL doesn’t provide a way to decrypt the key before starting OpenVPN. (Note that if you want to test IPSec as well, it’ll require the key to be in DER format, which is covered in the IPSec guide.)
# Strip the password and save to the config partition.
openssl pkcs8 -in newkey.pem -out /config/auth/server-pem.key
Generating the Diffie-Hellman parameters can take 10 minutes on the ERL. Might I suggest a coffee break?
# Generate dhp params.
openssl dhparam -out /config/auth/dhp.pem -2 1024
cp dhp.pem /config/auth
Now we can generate the client certs. We do this on the ERL directly because we’ll need to sign them with the CA cert. Alternatively you could generate this on the client and copy the cert around for signing.
I would recommend setting the CN (Common Name) to something unique for each client. The CN is used by the VPN software to uniquely identify clients. This will help you see who is connected to the ERL. Also, by default, OpenVPN won’t allow a single CN to connect twice.
# Generate client key and cert.
./CA.sh -newreq
./CA.sh -sign
mv newcert.pem client1-cert.pem
mv newkey.pem client1-key.pem
We’ll need a PKCS12 formatted file for some clients. This format combines the client’s cert, key and the CA cert into one file.
# Combine the clients creds with the CA cert into a single p12 file.
openssl pkcs12 -export \
-out client1.p12 \
-inkey client1-key.pem \
-in client1-cert.pem \
-certfile demoCA/cacert.pem
Now we’ll need to copy those client credentials onto our client. More on this in the Client section.
OpenVPN Server Setup
Note, I’ll be using port 1194/UDP for this tutorial as it’s the easiest to document. If you’d prefer something less likely to be filtered by other firewalls, I describe the usage of 443/TCP in a later section.
First configure the OpenVPN server within the ERL. Firewall steps to follow.
configure
edit interfaces openvpn vtun0
set mode server
set local-port 1194# This subnet must be unique within your network!
# Do not use a previously configured subnet.
set server subnet 172.30.255.0/24# Configure the SSL/TLS params.
set tls ca-cert-file /config/auth/cacert.pem
set tls cert-file /config/auth/server.pem
set tls key-file /config/auth/server-pem.key
set tls dh-file /config/auth/dhp.pem
I chose 172.30.255.0/24 because it seemed (based on my experience) to be a rarely used IP range. This is important because if your client is every on a network which overlaps with this range, you’ll have routing trouble.
Update for 1.8. EdgeMax 1.8’s OpenVPN configuration supports IPv6, so I recommend running the dual stack “protocol udp6”. IPv6 addresses tend to be static, so this may obviate the need for you to use dynamic DNS.
set protocol udp6
Routes. There are two options.
Option #1. Route all traffic across your VPN. This causes the client to set a new default route.
set openvpn-option “--push redirect-gateway”
Option #2. Only route your local VLANs. In the event you simply want to access your local VLANs remotely.
# Replace the below with the networks you want to access remotely.
set server push-route 192.168.0.0/24
set server push-route 192.168.1.0/24
DNS. By default your clients will retain their original DNS servers which could break things horribly. Eg, your ERL may not have access to query the DNS servers assigned by the coffee shop you’re sitting in.
# Instruct clients to use Google's Public DNS servers.
openvpn-option “--push dhcp-option DNS 8.8.8.8”
openvpn-option "--push dhcp-option DNS 8.8.4.4"
A better option might even be to tell your VPN clients to use the ERL’s DNS forwarding capability. I leave this as an exercise for the reader.
Compression. I recommend enabling compression. Your ERL has the CPU to support it and if you’re bouncing traffic between multiple networks, you’ll want to save as much bandwidth as possible.
set openvpn-option "--comp-lzo"
Firewall. Note that WAN_LOCAL corresponds to packets destined for the ERL itself.
top
# Edit rules for packets destined for the ERL.
edit firewall name WAN_LOCAL # Be sure to NOT overwrite any existing rules.
set rule 4 action accept
set rule 4 description “OpenVPN”
set rule 4 destination port 1194# OpenVPN can run on UDP and TCP. The former is faster,
# the latter is more likely to work in hostile environs.
set rule 4 protocol tcp_udp
set rule 4 log disable
1.8 Update. EdgeMax OS v1.8 supports IPv6 (dual-stack) OpenVPN configuration. So if you enable it (as suggested above) you’ll need to add the same firewall rule for IPv6. Your rule may be named WAN6_LOCAL like mine.
Commit your work. If there are any problems, the ERL will complain about failing to restart the openvpn process.
commit
save
In case of problems, here are some basic troubleshooting commands to get you started.
### Server process running? Also, check the cmd-line args.
$ ps -ef | grep openvpn### openvpn logs via syslog
$ tail /var/log/messages### ERL specific command
$ show openvpn server status
Using port 443 (instead of 1194)
If you’d like to make your VPN available for cases where the remote network is blocking non HTTP(S) ports, you can make the following changes.
Note that OpenVPN recommends UDP instead of TCP. A more detailed discussion can be found here.
This will also require you to move the ERL’s web admin GUI to a different port. If you do this, I also recommend listening on specific local address, rather than ALL IP addresses. This provides some additional security via Defense in Depth.
# Move the admin web interface to 192.168.1.1:4433.
set service gui https-port 4433
set service gui listen-address 192.168.1.1set openvpn vtun0 local-port 443# update the firewall rules as well!
Client Setup
Here’s a simple Linux or MacOS config which should work. Another good source of information is the OpenVPN site’s example configs.
dev tun
proto udp
remote foo.bar.com 443
resolv-retry infinite
nobind
persist-key
persist-tun
pkcs12 client.p12
comp-lzo
link-mtu 1542
Note that I set a specific link-mtu value. My client and the ERL server did not match. You can verify if this is the case for you by watching /var/log/messages on the ERL during a connection attempt and noting any MTU mismatches.
Closing Thoughts
That worked for me and I hope it works for you. I’ll add another short post about OpenVPN IPv6 support when I get a chance.
Update: IPv6+OpenVPN works with EdgeMax OS v1.8, which was released at the end of Feb, 2016.