Presented to CP-LUG 13 May 2008 by Matthew Rinehart
OpenVPN is an open source (GPLv2) application for establishing secure connections over insecure networks.
Public Key Infrastructure
Everyone who has ever connected via SSH or HTTPS has used part of PKI. A pair of keys (big numbers) is generated for each entity needing an identity (like a server). One of these keys is considered public; anyone can view this key in its entirety, and in fact, should. The other key is private; only the entity to whom the key pair belongs should have access to this key.
By using an asymmetric key pair, encryption can be established between two entities who have previously never communicated. Here's how it might work connecting to an SSL webserver.
Virtual Private Network
On your home's private network, you can communicate between the hosts on the network without worrying about anyone on the Internet seeing that traffic because you're on a private subnet that doesn't get routed to the Internet.
A VPN provides that same security via encryption. Once a VPN connection is established, the traffic to the hosts on your home network is encrypted before being sent across the Internet, then decrypted at the VPN server and sent the rest of the way just as traffic on the local network would be. The response is then sent back to the VPN server, encrypted, and forwarded back across the Internet to your VPN client, which decrypts it and presents it to the application.
Once setup and running, a VPN can and should be completely transparent.
There are several installation options available.
emerge openvpn
Install it from your (other) distribution's software repository.
Build it yourself. Sources can be obtained from http://openvpn.net/index.php/downloads.html
For building it from source manually, you will need to have installed OpenSSL, LZO, and PAM, if you want the same functionality that the binary packages provide. It is a standard ./configure; make; make install procedure; just pass in the proper options to the configure script to get it built the way you like it.
OpenVPN will run on Mac and Windows. A Windows installer is provided at the OpenVPN download page: http://openvpn.net/index.php/downloads.html
Third parties have provided other versions, as well as GUIs. The general OpenVPN howto at http://openvpn.net/index.php/documentation/howto.html has some information on those.
There are several choices to be made when configuring OpenVPN.
OpenVPN ships a set of tools called "easy-rsa" for establishing your site's PKI. It consists of a series of scripts which invoke OpenSSL with various parameters to generate keys, certificates, and other essential files.
| Step | Host | Action | Affected/Generated Files |
|---|---|---|---|
| 1 | All | Edit vars to reflect the settings for your site. |
(none) |
| 2 | All | . ./vars |
(none) |
| 3 | All | ./clean-all |
index.txt, serial |
| 4 | CA | ./build-ca (take defaults) |
ca.key, ca.crt |
| 5 | Server | ./build-req --server servername (take defaults) |
servername.key, servername.csr |
| 6 | Server -> CA | Transfer servername.csr to keys directory | servername.csr |
| 7 | CA | ./sign-req server (answer 'y' to both prompts) |
servername.crt, 01.pem, index.txt, index.txt.attr, serial |
| 8 | CA -> Server | Transfer servername.crt to keys directory | servername.crt |
| 9 | Server | ./build-dh |
dh1024.pem |
| 10 | Client | ./build-req clientname (take defaults) |
clientname.key, clientname.csr |
| 11 | Client -> CA | Transfer clientname.csr to keys directory | clientname.csr |
| 12 | CA | ./sign-req clientname (answer 'y' to both prompts) |
clientname.crt, 02.pem, index.txt, index.txt.attr, serial |
| 13 | CA -> Client | Transfer clientname.crt to keys directory | clientname.crt |
| 14 | CA -> All | Transfer ca.crt to keys directory | ca.crt |
At completion, the following should represent the files present on each type of machine:
| Host | File | Purpose |
|---|---|---|
| CA | ca.key | CA private key; signs certificate signing requests from server and clients |
| CA | *.crt | Public certificates; key revocation |
| Server | ca.crt | CA certificate; certificate validation |
| Server | dh1024.pem | Diffie-Hellman parameters |
| Server | servername.crt | Server certificate (public key) |
| Server | servername.key | Server private key |
| Client | ca.crt | CA certificate; certificate validation |
| Client | clientname.crt | Client certificate (public key) |
| Client | clientname.key | Client private key |
/etc/openvpn/openvpn.conf:
port 1194 proto udp dev tun ca /etc/openvpn/easy-rsa/keys/ca.crt cert /etc/openvpn/easy-rsa/keys/server.crt key /etc/openvpn/easy-rsa/keys/server.key dh dh1024.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist /etc/openvpn/ipp.txt ;client-to-client ;duplicate-cn comp-lzo user nobody group nobody persist-key persist-tun status /etc/openvpn/openvpn-status.log verb 3
/etc/openvpn/openvpn.conf:
client dev tun proto udp remote server 1194 resolv-retry infinite nobind user nobody group nobody persist-key persist-tun ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/client.crt key /etc/openvpn/keys/client.key ns-cert-type server comp-lzo verb 3
remote entries can be provided for load-balancing.So far, OpenVPN installed and configured this way will allow a single client to connect to a single server and communicate only with it. Depending on your environment, you may want to implement one or more of the following additional configurations.
It is a good idea to make use of a CRL (certificate revocation list) for your PKI. OpenVPN can be configured to look for a CRL and read it on each client connection to verify that the client's certificate is still valid. The crl-verify directive will enable this. The file specified as the argument to that directive is re-read on each new connection and can therefore be updated/replaced while the server is running.
NOTE: A valid CRL file must already be in place to use crl-verify. You cannot specify the name of a file that does not yet exist, or a 0-length file. The server will fail to start.
Revoking a certificate is done at the CA/key-signing server with the script revoke-full, e.g., ./revoke-full clientname. This creates or updates a crl.pem file, which can be copied to your OpenVPN server and referenced with the crl-verify directive.
The directive client-config-dir specifies a directory holding client-specific configuration files. They are named identical to the CN attribute of the client certificate. This file can be used to push specific settings to the client, such as a static IP, additional routes, etc.
A common use for this might be adding your site's DNS server to the client configuration so that local hostnames resolve as expected once connected. It can also be used to push a new default gateway to the client, such that ALL traffic originating from the host defaults to the VPN.
It's likely you want to be able to use the VPN to connect to more than one machine on your local network. This is a fairly simple process. If you are using a tunneled connection, do the following:
push "route VPN_subnet VPN_subnet_mask" to the server configuration fileFor TAP connections, do nothing. The server-side network is automatically fully accessible under this configuration, since the VPN clients receive addresses on the same network segment.
Although less likely than expanding the access on the server side, OpenVPN supports the scenario in which you would want a single machine on the client side to connect to the VPN and allow all other machines on its network to speak to the VPN as well.
In order to do this, the client's subnet must be unique; it cannot be used by the server's network, the virtual network, or any other connecting client's network. The client must also be identified by a specific certificate that is not allowed to be used by any other client.
To start, the client must be configured for IP forwarding. Next, the server must be setup with client-config-dir, such that a configuration file can be specified for this specific client alone. That configuration file must contain the following directive:
iroute <client's subnet ID> <client's subnet mask>
This informs the OpenVPN process to forward traffic received intended for that network to this client. Then, in the main server configuration file, the following directive should be specified:
route <client's subnet ID> <client's subnet mask>
This instructs the daemon to add that route to the kernel's routing table on startup, so that traffic intended for that subnet gets to OpenVPN.
If other clients should be able to see the subnet behind this particular client, add the following:
client-to-client push "route <client's subnet ID> <client's subnet mask>
Note that this will allow clients to see all other clients as well, which may not be ideal.
Finally, if the VPN server is not the local network gateway, add a static route to the gateway to send traffic intended for the client's subnet to the VPN server.
If the client involved in this configuration isn't the gateway for its network, a similar setup will be required on its end to route traffic properly.
A management interface can be enabled with the directive management address port. A telnet client can connect to this address and port to issue commands, or a GUI can be configured to send the commands to that address and port in response to manipulation of its interface.
Some of the things you can do with the management interface is forcibly disconnect existing connections (e.g., if you've just revoked their certificate or if you want them to pull new commands from the client-config-dir) and adjust daemon verbosity on the fly.
The possibilities are seemingly endless. Here are some advanced configurations that I haven't needed to implement yet and therefore have not looked into closely:
dhcp-optiontls-auth