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:
- create a CA
- create a secret server/client key and csr (certificate signing request)
- sign the csr (with the CA)
- 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:
- I use the option
nopass
through some of the commands - omit this parameter if you want to use a password. - Names which have to be unique for each certificate are written in UPPER LETTERS.
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
- needs (uses) more options to type, but some are optional and can be omitted
- asks some questions w/o an
openssl.cnf
file - wants the options '-days 3650' and '-serial' if required (default by easy-rsa)
easyrsa
- uses different locations/folders, thus could led into confusion by copying back and forth
- could be dangerous by usage of the 'init-pki' command
- needs to revoke a certificate ('') before a new one can be created (by use as designed)
- makes it easy to view CSR's or certs ('show-req', 'show-cert')
- could be critical by 'sign-req' by carefully usage of parameters 'client' or 'server'
- doesn't have a documentation base like openssl
- has some drawback with error handling, even if this not happens quite often
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.