Preface[edit]

There's a plethora of good guides on the Internet into getting the OpenVPN working. This guide will primarily concentrate on using the X.509 certificates with the supplied hierarchy generated by the X.509 infrastructure, and using the PKCS#11 OpenSC crypto provider.

It will also emphasize the important bits of information related to the OpenVPN's functioning when using the certificates.

Software Requirements[edit]

For the purpose of this chapter it is assumed that a server and client machines have been supplied with pre-installed Debian Squeeze GNU/Linux distribution. During the (network) installation it is assumed that the standard task has been selected. It is also recommended to install the SSH server task for ease of administration.

The OpenVPN package which is used by both the server and client can be installed with:

? root
$ apt-get install openvpn

If you intend to use the smart cards for authentication purposes, also make sure you've installed the necessary PKCS#11 provider:

? root
$ apt-get install pcscd opensc

Setting-up the Server[edit]

Issuing the Certificate[edit]

For the server side it's necessary to issue the following certificate:

End Entity Profile: Server
E-mail address: vpn@example.com
CN, Common name: Example OpenVPN Server
O, Organization: Example Inc.
C, Country (ISO 3166): RS
DNS Name: vpn.example.com
Certificate Profile: Example Server
CA: Example Server CA
Token: PEM file

Create the directory which will hold the certificates and keys on the destination server:

? root
$ mkdir /etc/openvpn/tls/

The private key should be placed into the following location:

# /etc/openvpn/tls/vpn.example.com.key

Prepare the accompanying certificate file so that you have the server's certificate followed by the Example Server CA and Example Root CA certificates one after the another in the same file. Place the resulting file into location:

# /etc/openvpn/tls/vpn.example.com.crt

Place the Example Root CA and Example Person CA certificates in PEM format into location:

# /etc/openvpn/tls/trust_chain.crt

Set-up the file permissions:

? root
----BEGIN----$
chmod 755 /etc/openvpn/tls/
chown -R root.root /etc/openvpn/tls/
chmod 600 /etc/openvpn/tls/vpn.example.com.key
chmod 644 /etc/openvpn/tls/vpn.example.com.crt
chmod 644 /etc/openvpn/tls/trust_anchor.crt
-----END-----

Configuring the Server[edit]

It's possible to run the OpenVPN both as a regular user and as a root user. The OpenVPN supports dropping of privileges in case of running as regular user after all the necessary resources have been allocated beforehand. Create the system user/group which will be used for running the OpenVPN:

? root
$ adduser --group --system openvpn

It's also necessary to create a file which will contain the Diffie Hellman parameters for use with the TLS server:

? root
$ openssl dhparam -out /etc/openvpn/tls/dh2048.pem 2048
$ chmod 600 /etc/openvpn/tls/dh2048.pem

Now create the configuration file which will be used by the OpenVPN server:

# /etc/openvpn/vpn.example.com.conf
----BEGIN----
# Specify the mode we'll be using for running this OpenVPN instance.
mode server
# Specify the device type we'll be using for the VPN connections.
dev tun
# Specify the topology in which we'll be running.
topology subnet
# Since the OpenVPN will be running as non-root user, it is important
# to allow the daemon to persist the tun device once it drops the
# privileges.
persist-tun
# Since the OpenVPN will be running as non-root user, it is important
# to allow the daemon to persist the private key once it drops the
# privileges.
persist-key
# Specify the user and group under which the daemon will be running.
user openvpn
group openvpn
# Automatically configure a number of different server-related
# parameters, and assign the specified network.
server 10.64.66.0 255.255.255.0
# Make sure the server acts as a TLS server.
tls-server
# Provide the trust anchor (the root CA) which will determine which
# clients may or may not connect.
ca /etc/openvpn/tls/example_rootca.crt
# The Diffie Hellman parameters must be provided in a PEM-encoded
# file.
dh /etc/openvpn/tls/dh2048.pem
# Specify the certificate which will be presented to the clients when
# the connect.
cert /etc/openvpn/tls/vpn.example.com.crt
# Specify the private key which accompanies the specified server
# certificate.
key /etc/openvpn/tls/vpn.example.com.key

-----END-----

Running the Server[edit]

Once the configuration has been finished, you can start-up the server by executing the following command:

? root
$ service openvpn start vpn.example.com

Setting-up the Client[edit]

Issuing the Certificates[edit]

In case of client configuration, any valid person signing certificate should do. If a static configuration is used, the private key and the certificate need to be in a PEM format.

Create the directory which will hold the certificates and keys on the destination client machine:

? root
$ mkdir /etc/openvpn/tls/

The private key should be placed into the following location:

# /etc/openvpn/tls/vpn.example.com.key

Prepare the accompanying certificate file so that you have the client's certificate followed by the Example Person CA and Example Root CA certificates one after another in the same file. Place the resulting file into location:

# /etc/openvpn/tls/vpn.example.com.crt

Place the Example Root CA and Example Server CA certificates in PEM format into location:

# /etc/openvpn/tls/trust_chain.crt

Set-up the file permissions:

? root
----BEGIN----$
chmod 755 /etc/openvpn/tls/
chown -R root.root /etc/openvpn/tls/
chmod 600 /etc/openvpn/tls/vpn.example.com.key
chmod 644 /etc/openvpn/tls/vpn.example.com.crt
chmod 644 /etc/openvpn/tls/example_rootca.crt
-----END-----

Configuring the Client[edit]

It's possible to run the OpenVPN both as a regular user and as a root user. The OpenVPN supports dropping of privileges in case of running as regular user after all the necessary resources have been allocated beforehand. Create the system user/group which will be used for running the OpenVPN:

? root
$ adduser --group --system openvpn

It's also necessary to create a file which will contain the Diffie Hellman parameters for use with the TLS server:

? root
$ openssl dhparam -out /etc/openvpn/tls/dh2048.pem 2048
$ chmod 600 /etc/openvpn/tls/dh2048.pem

Now create the configuration file which will be used by the OpenVPN client:

# /etc/openvpn/vpn.example.com.conf
----BEGIN----
# Specify the remote server to which the client should connect.
remote vpn.example.com
# Specify the device type we'll be using for the VPN connections.
dev tun
# Specify the topology in which we'll be running.
topology subnet
# Since the OpenVPN will be running as non-root user, it is important
# to allow the daemon to persist the tun device once it drops the
# privileges.
persist-tun
# Since the OpenVPN will be running as non-root user, it is important
# to allow the daemon to persist the private key once it drops the
# privileges.
persist-key
# Specify the user and group under which the daemon will be running.
user openvpn
group openvpn
# Automatically configure a number of different client-related
# parameters.
client
# Make sure the client acts as a TLS client.
tls-client
# Provide the trust anchor (the root CA) which will determine to which
# server we may connect.
ca /etc/openvpn/tls/trust_chain.crt
# Specify the certificate which will be presented to the server when
# trying the connect.
cert /etc/openvpn/tls/vpn.example.com.crt
# Specify the private key which accompanies the specified client
# certificate.
key /etc/openvpn/tls/vpn.example.com.key
# Require that the remote server's certificate has proper key usage
# and extended key usage attributes set.
remote-cert-tls server
-----END-----

Running the Client[edit]

Once the configuration has been finished, you can start-up the client by executing the following command:

? root
$ service openvpn start vpn.example.com

Using Smart card for Authentication[edit]

With OpenVPN it's possible to use smart card for both server and client operation. The only obstacle when using the smart card is the ability to identify the appropriate certificate which should be used for the connection (in case a smart card comes with multiple certificates), and presenting the PIN code in the process.

The consequence of the former is that the OpenVPN daemon has to be started manually from the shell so that user can provide the PIN code for smart card.

The identifier of a certificate can be obtained with:

$ openvpn --show-pkcs11-ids /usr/lib/opensc-pkcs11.so

The information you need from this command's output is the serialized id parameter. Once you have obtained this, you can comment-out the cert and key lines from the configuration file, and add the following lines instead:

# /etc/openvpn/vpn.example.com.conf
----BEGIN----
# Specify the identifier for the certificate.
pkcs11-providers /usr/lib/opensc-pkcs11.so
# Specify the certificate identifier.
pkcs11-id '{{serialized_id}}'
-----END-----

The parameter serialized_id should be copied by the previously obtained value. It is important to note that the single quotes around this ID are necessary.

Another issue with this kind of configuration is that if you've set-up the configuration files in the above locations, you could have the boot process hanging on you indefinitely. To prevent this, you may want to move the configuration files outside of their current location.

As mentioned previously, you'll need to start the OpenVPN daemon in a slightly different manner, by executing the following command:

? root
$ openvpn --config {{config_file}}

Parameter config_file should be replaced by the path to the desired configuration file. If the appropriate smart card is present, you will be prompted for a user PIN code. Once the PIN code has been obtained, the daemon will proceed with the usual steps for authenticating and establishing the VPN.

Enabling CRL Checks[edit]

When connecting to the OpenVPN sever, by default both client and server will perform a number of basic checks (like key usages, verification of the trust chain etc). One thing that's not turned on explicitly, but is very useful, is CRL verification.

OpenVPN's implementation of CRL check verification leaves a little bit to be desired, but it's still usable to a point. It's possible to use two types of (mutually exclusive) CRL verification. One relies on providing a single CRL which should contain the entries of relevant entities (in our case Example Person CA CRL on server side, and Example Server CA CRL on client side). This type of configuration is aware of new CRL being downloaded in the place of the old one, though.

The other is to use the capath option which basically requires both trust chain certificates and CRL's to be placed into a single directory, and having them set-up with the c_rehash utility. Unfortunately, under this mode of operation it's not possible just to replace the existing CRL's with news ones - a restart of the OpenVPN server is required so that new CRL would get reloaded.

For start create the directory which will contain the CRL we download from the web server:

? root
$ mkdir /etc/openvpn/crl/

If you're setting-up the server, create the following script that will download the CRL:

# /usr/local/bin/getcrls_openvpn.sh
----BEGIN----
#!/bin/bash

# Download the CRL.
/usr/bin/wget http://crl.example.com/personca.crl -O /etc/openvpn/crl/personca.crl

# Convert the CRL from the default DER format to PEM format.
/usr/bin/openssl crl -inform DER -in /etc/openvpn/crl/personca.crl -out /etc/openvpn/crl/personca.pem

-----END-----

If you're setting-up the client, create the following script that will download the CRL:

# /usr/local/bin/getcrls_openvpn.sh
----BEGIN----
#!/bin/bash

# Download the CRL.
/usr/bin/wget http://crl.example.com/personca.crl -O /etc/openvpn/crl/serverca.crl

# Convert the CRL from the default DER format to PEM format.
/usr/bin/openssl crl -inform DER -in /etc/openvpn/crl/serverca.crl -out /etc/openvpn/crl/serverca.pem

-----END-----

Set-up the file permissions:

? root
$ chown root.root /usr/local/bin/getcrls_openvpn.sh
$ chmod 700 /usr/local/bin/getcrls_openvpn.sh

Set-up the cron job to execute the script periodically (we'll have it download the CRL's every hour):

? root
$ echo "0 * * * * /usr/local/bin/getcrls_openvpn.sh" | crontab

You can manually execute the script the first time if you want to get started:

? root
$ getcrls_openvpn.sh

Now add the following line to the OpenVPN configuration (for server):

# /etc/openvpn/vpn.example.com.conf
----BEGIN----
# Verify the certificates using the designated CRL list.
crl-verify /etc/openvpn/crl/personca.pem
-----END-----

If you're setting-up a client, the configuration should instead contain:

# /etc/openvpn/vpn.example.com.conf
----BEGIN----
# Verify the certificates using the designated CRL list.
crl-verify /etc/openvpn/crl/serverca.pem
-----END-----

Restart the OpenVPN daemon after the change has been made:

? root
$ service openvpn vpn.example.com restart