March 16, 2017

Build a Real VPN with OpenVPN


Learn how to build a proper virtual private network with OpenVPN in this tutorial.

A real, genuine, honest-to-gosh virtual private network (VPN) is an encrypted network-to-network virtual tunnel that connects trusted endpoints. It is not a HTTPS web portal that trusts all clients. Let us build a proper strong VPN with OpenVPN.

The definition of VPN has been stretched beyond recognition with the proliferation of HTTPS VPNs, which trust all clients. These work for shopping sites, which permit only limited client access. Many are sold to businesses as "Easy client-less configuration!" to provide remote employee access. But I do not trust them as extensions of my networks. A VPN connects two networks, such as branch offices, or a remote worker to an office server. A real VPN requires that both the server and clients authenticate to each other.

Setting up a VPN where both servers and clients authenticate to each other is a bit of work, and that is why "Easy client-less configuration!" sells. But it's really not that hard to set up a proper strong OpenVPN server. You need two hosts on different networks to set up a nice OpenVPN test lab, such as a couple of virtual machines, or two hosts on different networks, like a wireless and a wired machine. All hosts need OpenVPN and Easy-RSA installed.

Set up PKI

First. we'll create a proper public key infrastructure (PKI) on the server. Your OpenVPN server is the machine that external users will connect to. As with all Linux servers, "server" refers to function, and a computer can be both a server and a client. A PKI offers several advantages: you have a Certificate Authority (CA) which simplifies key distribution and management, and you can revoke client certificates at the server. When you don't use a CA the server needs a copy of every client certificate. A CA doesn't need all those client certificates; it only needs to know whether the client certificates have been signed by the CA. (OpenVPN also supports static keys, which are fine for one or two users; see How to Set Up Secure Remote Networking with OpenVPN on Linux, Part 1.)

Remember, private keys must always be protected and never shared, while public keys are meant to be shared. In OpenVPN, the public key is called a certificate and has a .crt extension, and the private key is called a key, with a .key extension.

In the olden days, OpenVPN came with nice helper scripts to set this up: the Easy-RSA scripts. These are now maintained as a separate project, so if your Linux distribution doesn't package them you can get them fresh from GitHub. Browse the Releases page to get ready-to-use tarballs. You might want to download them from GitHub anyway, to get the current 3.0.1 release. This release dates back to October 2015, but a lot of Linux distributions are stuck on the old 2.x releases. Let's go ahead and use the new release.

Download and unpack the Easy-RSA tarball into your /etc/openvpn directory. Change to your Easy-RSA directory, then run this command to initialize your new PKI:

$ sudo ./easyrsa init-pki

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/easyrsa/pki

Now go ahead and create your new CA:

$ sudo ./easyrsa build-ca
Generating a 2048 bit RSA private key
writing new private key to '/etc/openvpn/easyrsa/pki/private/ca.key.tJXulR8Ery'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Common Name (eg: your user, host, or server name) [Easy-RSA CA]

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:

You will copy your new ca.crt into /etc/openvpn on all client machines. The next steps takes place on your client machine, creating a PKI environment, the client's private key, and a signing request. Replace "AliceRemote" with whatever name you want to identify the client:

$ sudo ./easyrsa init-pki
$ sudo ./easyrsa gen-req AliceRemote
Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easyrsa/pki/reqs/AliceRemote.req
key: /etc/openvpn/easyrsa/pki/private/AliceRemote.key

Copy the .req file to your server, import it, and then sign it:

$ sudo ./easyrsa import-req /media/carla/4gbstik/AliceRemote.req AliceRemote
$ sudo ./easyrsa sign-req client AliceRemote
Certificate created at: /etc/openvpn/easyrsa/pki/issued/AliceRemote.crt

Copy the signed certificate to the client machine. Now both server and client have all the necessary certificates and key pairs.

If you plan to use TLS, you need to generate Diffie-Hellman parameters on the server. You probably will, so go ahead and do it:

$ sudo ./easyrsa gen-dh

Server Configuration

Look in your openvpn/examples/ directory for configuration file examples. This is a complete example server configuration, and it goes in /etc/openvpn/server.conf. Edit the commented options for your own setup:

port 1194
proto udp
dev tun
keepalive 10 120
status openvpn-status.log
verb 3
ifconfig-pool-persist /etc/openvpn/ipp.txt

# Your server keys
ca /etc/openvpn/easyrsa/pki/ca.crt
key /etc/openvpn/easyrsa/pki/private/ca.key
dh /etc/openvpn/easyrsa/pki/dh.pem

# Set server mode, and define a virtual pool of IP
# addresses for clients to use. Use any subnet
# that does not collide with your existing subnets.

# Set up route(s) to subnet(s) behind
# OpenVPN server
push "route"
push "route"

Client Configuration

Use this on your client. This example is /etc/openvpn/client.conf:

dev tun
proto udp
resolv-retry infinite

# The hostname/IP address and port of the server
remote servername 1194

# Your certificates and keys
cert /etc/openvpn/easyrsa/pki/AliceRemote.crt
ca /etc/openvpn/easyrsa/pki/ca.crt
key /etc/openvpn/easyrsa/pki/private/AliceRemote.key

Connecting to the Server

Start OpenVPN on the server from the command line by referencing the configuration file, for example openvpn /etc/openvpn/server.conf. Start it on the client in the same way, for example openvpn /etc/openvpn/client.conf. You may name your configuration files anything you want, and you may create multiple files for multiple server and client configurations. Once your OpenVPN tunnel is established it's just like having a shielded Ethernet cable to carry your session safely over untrusted networks, and you can log into your usual programs just as though you were sitting next to the server.

This should get you up and running. There are many configuration and command line options for OpenVPN; see the OpenVPN Documentation. Easy-RSA has a lot of good howtos on GitHub, and bundled in the tarball.

Learn more about Linux through the free "Introduction to Linux" course from The Linux Foundation and edX.

Click Here!