OpenVPN: easa-rsa 3

It was more than 3 years ago that I have had to setup and touch an OpenVPN configuration. But than comes the day with the need to touch it. Usually not a big deal, but quickly I realized that on my (Gentoo) system easy-rsa 2 was updated (replaced). And the new version easy-rsa 3 is quite different. As it makes no sense to stick with old stuff I decided to switch to the actual version and started over to create all certificates and keys new. I did skim over the related documentation and created the required multiple certs/keys. Making a long story short - it doesn't work. Even if it was my fault, unfortunately the documentation wasn't easy and clear enough like it happens quite often. As the most pages at the web at the time were for easy-rsa 2, I want to document the technical pitfalls a bit. As a foreshadow:

I question that easy-rsa 3 is as easy as it claims - it hides (replaces) openssl complexity with its own complexity only!

Anyway, lets go forward with it. The general steps to create certs signed by a ca (certificate authority) are:

  1. create a CA
  2. create a secret server/client key and csr (certificate signing request)
  3. sign the csr (with the CA)
  4. distribute the keys and certs to the related systems

I will do all at the same system (host). Thus we have to use separate folders.  easy-rsa  does all relative inside to the folder where the used executable is located. Two more hints:

Certificate Authority

First make a copy the folder  easy-rsa  for the CA. Beware that the location where  easy-rsa  was installed differs from system to system. I assume that it is installed in  /usr/share/easy-rsa  further-in.

 $ cp -r /usr/share/easy-rsa ~/my-ca

All we will do with easyrsa now will be done relative inside this folder.

Now we can create our certificate authority:

$ cd ~/my-ca
$ ./easyrsa init-pki
$ ./easyrsa build-ca nopass

Never run the command  ./easyrsa init-pki  in this folder  (~/my-ca)  again !  This will remove the private key and the certificate of the CA! It is maybe a good idea to make a backup of this folder right now ;-), so let's do it:

$ cd ~
$ cp -r my-ca my-ca~

Keep the private key  ~/my-ca/pki/private/ca.key  absolute secret. The certificate  ~/my-ca/pki/ca.crt  is required by every server and client. Lets us put in a separate folder:

$ mkdir ~/vpn-keys
$ cp ~/my-ca/pki/ca.crt ~/vpn-keys

Create Server Certificate

DO NOT USE the CA's folder  ~/my-ca  from above !  Create a new copy for the server/client certificates:

 $ cp -r /usr/share/easy-rsa ~/my-certs

Change into this folder and create a certificate signing request:

$ cd ~/my-certs
$ ./easyrsa init-pki
$ ./easyrsa gen-req VPNSERVER nopass

The name  VPNSERVER  MUST be unique for each certificate request! It is used as the common name (CN) of the certificate. It is not a bad idea to use the hostname - even the FQDN - of the OpenVPN server.

Now we have to import the request into the ca and to create a certificate for the server.

$ cd ~/my-ca
$ ./easyrsa import-req ~/my-certs/pki/req/VPNSERVER.req VPNSERVER

Now we can use  VPNSERVER  further-in to simplify the processing. Review the request (optional) and create the server certificate:

$ ./easyrsa show-req VPNSERVER
$ ./easyrsa sign-req server VPNSERVER

That's it. Now it is important to save the servers key and certificate:

$ cp ~/my-ca/pki/issued/VPNSERVER.crt ~/vpn-keys
$ cp ~/my-certs/pki/private/VPNSERVER.key ~/vpn-keys

It is important to save the  VPNSERVER.key  now as for the reason how I will do the next steps.

Create Client Certificate(s)

As an alternative you can make another copy of  easy-rsa  in a new folder for each client. But it is fine to use the existing folder  ~/my-certs  for the client(s) too. I recommend to clean the folder  ~/my-certs :

$ cd ~/my-certs
$ ./easyrsa init-pki

Be sure you are inside the correct folder  ~/my-certs ! Anyhow, the  init-pki  is optional here.

The next steps are similar to Create Server Certificate except that we have to replace  VPNSERVER  by another unique name (here:  CLIENT_1 ) and usage of the option  client  when we sign the request.

$ cd ~/my-certs
$ ./easyrsa gen-req VPNSERVER nopass
$ cd ~/my-ca
$ ./easyrsa import-req ~/my-certs/pki/req/CLIENT_1.req CLIENT_1
$ ./easyrsa show-req CLIENT_1
$ ./easyrsa sign-req client CLIENT_1
$ cp ~/my-ca/pki/issued/CLIENT_1.crt ~/vpn-keys
$ cp ~/my-certs/pki/private/CLIENT_1.key ~/vpn-keys

Repeat these steps for each client by replacing  CLIENT_1  by another unique name (e.g.  CLIENT_2 ). Same as with the name  VPNSERVER  above here:

The name of  CLIENT_*  MUST be unique for each certificate request!

Generate DH parameter

Last but not least we need a DH key.  easyrsa  creates a 2048 bit long safe prime - this could take some time. Simply run

$ cd ~/my-ca
$ ./easyrsa gen-dh
$ cp pki/dh.pem ~/vpn-keys/dh2048.pem

Now we (should ;-)) have all required keys and certs.

At this point I want to do a sidestep and show the equivalent steps by using  openssl  commands. You can jump over this paragraph if it's not of interrest.

Using openssl

I will go through the usage of  openssl  quite quickly. Create a new empty folder and change into it. Then do the following steps:

Certificate Authority:
$ openssl genrsa -aes256 -out ca.key 2048                                   # private key (secret)
$ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -set_serial 1   # public key
Create Server Certificate:
$ openssl req -new -newkey rsa:2048 -out server.req -nodes -keyout server.key -days 3650     # private key
$ openssl x509 -req -in server.req -out VPNSERVER.crt \                                      # public key
               -CA ca.crt -CAkey ca.key -CAserial serial \
               -extensions server_cert -days 3650
Create Client Certificate(s):
$ openssl req -new -newkey rsa:2048 -out CLIENT_1.req -nodes -keyout CLIENT_1.key -days 3650        # private key
$ openssl x509 -req -in CLIENT_1.req -out CLIENT_1.crt -CA ca.crt -CAkey ca.key -CAserial serial \  # public key
               -extensions usr_cert -days 3650

Repeat these steps for each client by replacing CLIENT_1 by another unique name (e.g. CLIENT_2) - same as above.

If you don't have a file “serial” replace  -CAserial serial  with  -CAcreateserial .

Generate DH parameter:
 $ openssl dhparam -out dh2048.pem 2048

Comparison

No matter which tool you prefer, you have to know/learn the parameter for it. So lets have a look at the pro and cons.

openssl

easyrsa

I will stop here. Some other things like changing the key size in easyrsa would increase complexity.

Conclusion: Stay with  openssl  - it is not harder to use and at least because there are hundreds of thousands howto's available!

What is What

After we have created the keys and certificates lets have a look what is required for each system:

vpn server ca.crt, dh2048.pem, VPNSERVER.key, VPNSERVER.crt
client 1 ca.crt, CLIENT_1.key, CLIENT_1.crt
client X ca.crt, CLIENT_X.key, CLIENT_X.crt

In other words:  ca.crt  is required by each server and client. Additional the server requires  dh2048.pem . All pairs of  *.key/*.crt  files have to be put on the related system.