Difference between revisions of "Easy-RSA"

From ArchWiki
Jump to navigation Jump to search
(Add steps to create client certificates on the client)
(Undo revision 599295 by Chabad360 (talk) - it is already linked from the first sentence)
Tag: Undo
 
(120 intermediate revisions by 19 users not shown)
Line 1: Line 1:
 
[[Category:Virtual Private Network]]
 
[[Category:Virtual Private Network]]
The first step when setting up [[OpenVPN]] is to create a [[Wikipedia:Public key infrastructure|Public Key Infrastructure (PKI)]].  The PKI consists of:
+
[[ja:Easy-RSA]]
 +
The first step when setting up [[OpenVPN]] is to create a [[Wikipedia:Public key infrastructure|Public Key Infrastructure (PKI)]].  In summary, this consists of:
 +
* A public master [[Wikipedia:Certificate Authority|Certificate Authority (CA)]] certificate and a private key.
 +
* A separate public certificate and private key pair for each server.
 +
* A separate public certificate and private key pair for each client.
 +
 
 +
One can think of the key-based authentication in terms similar to that of how [[SSH keys]] work with the added layer of a signing authority (the CA).  OpenVPN relies on a bidirectional authentication strategy, so the client must authenticate the server's certificate and in parallel, the server must authenticate the client's certificate.  This is accomplished by the 3rd party's signature (the CA) on both the client and server certificates.  Once this is established, further checks are performed before the authentication is complete.  For more details, see [https://www.secure-computing.net/openvpn/howto.php#pki secure-computing's guide].
 +
 
 +
{{Note|
 +
* The process outlined below requires users to securely transfer private key files to/from machines. For the purposes of this guide, using scp is shown, but readers may employ alternative methods as well.  Since the Arch default is to deny the root user over ssh, using scp requires transferring ownership of the files to be exported to a non-root user called ''foo'' throughout the guide.
 +
* Avoid generating keys on devices without a good entropy source. See [https://community.openvpn.net/openvpn/wiki/GettingStartedwithOVPN#Configuringencryption]. Sometimes, [[Random_number_generation#Alternatives|cryptographically secure pseudorandom number generators]] can be used.
 +
}}
 +
 
 +
== Certificate Authority (CA) ==
 +
For security purposes, it is recommended that the CA machine be separate from the machine running OpenVPN.
 +
 
 +
On the '''CA machine''', install {{pkg|easy-rsa}}, initialize a new PKI and generate a CA keypair that will be used to sign certificates:
 +
 
 +
# cd /etc/easy-rsa
 +
# export EASYRSA=$(pwd)
 +
# easyrsa init-pki
 +
# easyrsa build-ca
 +
 
 +
Starting from OpenVPN 2.4, one can also use elliptic curves for TLS connections (e.g. tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384). Elliptic curve cryptography provides more security and eliminates the need for a Diffie-Hellman parameters file. See [https://forums.openvpn.net/viewtopic.php?f=4&t=23227] and [https://www.maths.tcd.ie/~fionn/misc/ec_vpn.php].
 +
 
 +
Append the following lines to {{ic|/etc/easy-rsa/vars}} to make Easy-RSA use elliptic curves:
 +
 
 +
{{hc|/etc/easy-rsa/vars|
 +
set_var EASYRSA_ALGO    ec
 +
set_var EASYRSA_CURVE    secp521r1
 +
set_var EASYRSA_DIGEST  "sha512"
 +
}}
 +
 
 +
Now set up PKI and generate a CA certificate:
 +
 
 +
# cd /etc/easy-rsa
 +
# export EASYRSA=$(pwd)
 +
# export EASYRSA_VARS_FILE=/etc/easy-rsa/vars
 +
# easyrsa init-pki
 +
# easyrsa build-ca
 +
 
 +
== OpenVPN server files ==
 +
 
 +
A functional OpenVPN server requires the following:
 +
 
 +
# The CA's public certificate
 +
# The Diffie-Hellman (DH) parameters file (required by TLS mode when not using TLS with elliptic curves).
 +
# The server key pair (a public certificate and a private key).
 +
# The Hash-based Message Authentication Code (HMAC) key.
 +
 
 +
Upon completing the steps outlined in this article, users will have generated the following files on the server:
 +
 
 +
# {{ic|/etc/openvpn/server/ca.crt}}
 +
# {{ic|/etc/openvpn/server/dh.pem}} (not when using TLS with elliptic curves)
 +
# {{ic|/etc/openvpn/server/servername.crt}} and {{ic|/etc/openvpn/server/servername.key}}
 +
# {{ic|/etc/openvpn/server/ta.key}}
 +
 
 +
=== CA public certificate ===
 +
 
 +
The CA public certificate {{ic|/etc/easy-rsa/pki/ca.crt}} generated in the previous step needs to be copied over to the machine that will be running OpenVPN.
 +
 
 +
On the '''CA machine''':
 +
 
 +
# scp /etc/easy-rsa/pki/ca.crt foo@hostname-of-openvpn-server:/tmp/ca.crt
 +
On the '''OpenVPN server machine''':
 +
 
 +
# mv /tmp/ca.crt /etc/openvpn/server/
 +
# chown root:root /etc/openvpn/server/ca.crt
  
* A public master [[Wikipedia:Certificate Authority|Certificate Authority (CA)]] certificate and a private key.
+
=== Server certificate and private key ===
* A separate public certificate and private key pair (hereafter referred to as a certificate) for each server and each client.
 
  
To facilitate the certificate creation process, OpenVPN comes with a collection of [[Wikipedia:RSA (algorithm)|RSA]] key manangement scripts (based on the openssl command line tool) known as easy-rsa.
+
On the '''OpenVPN server machine''', install {{pkg|easy-rsa}} and generate a key pair for the server:
  
{{Note| Only .key files need to be kept secret, .crt and .csr files can be sent over insecure channels such as plaintext email.}}
+
# cd /etc/easy-rsa
 +
# easyrsa init-pki
 +
# easyrsa gen-req servername nopass
 +
# cp /etc/easy-rsa/pki/private/servername.key /etc/openvpn/server/
  
In this article the needed certificates are created by root in root's home directory. This ensures that the generated files have the right ownership and permissions, and are safe from other users.
+
This will create two files:
  
{{Note|The certificates can be created on any machine. For the highest security, generate the certificates on a physically secure machine disconnected from any network, and make sure that the generated ca.key private key is backed up and never accessible to anyone.}}
+
{{ic|/etc/easy-rsa/pki/reqs/servername.req}}
 +
{{ic|/etc/easy-rsa/pki/private/servername.key}}
  
{{Warning|Make sure that the generated files are backed up, especially the ca.key and ca.crt files, since if lost you will not be able to create any new, nor revoke any compromised certificates, thus requiring the generation of a new [[Wikipedia:Certificate Authority|Certificate Authority (CA)]] certificate, invalidating the entire PKI infrastructure.}}
+
=== Diffie-Hellman (DH) parameters file ===
  
===Installing the easy-rsa scripts===
+
{{Note|If you are using TLS with elliptic curves, skip this step.}}
  
Install the scripts by doing the following:
+
On the '''OpenVPN server machine''', create the initial dh.pem file:
  
{{bc|# pacman -S easy-rsa}}
+
# openssl dhparam -out /etc/openvpn/server/dh.pem 2048
{{bc|# cp -r /usr/share/easy-rsa /root}}
 
  
===Creating certificates on the server===
+
{{Note|Although values higher than 2048 (4096 for example) may be used, they take considerably more time to generate and offer little benefit in security but advisable to have the DH prime number length to match the length of the RSA key. See [https://community.openvpn.net/openvpn/wiki/GettingStartedwithOVPN#Configuringencryption]}}
  
Change to the directory where you installed the scripts.
+
=== Hash-based Message Authentication Code (HMAC) key ===
  
{{bc|# cd /root/easy-rsa}}
+
On the '''OpenVPN server machine''', create the HMAC key:
  
To ensure the consistent use of values when generating the PKI, set default values to be used by the PKI generating scripts. Edit /root/easy-rsa/vars and at a minimum set the KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, and KEY_EMAIL parameters (do not leave any of these parameters blank).  Change the KEY_SIZE parameter to 2048 for the SSL/TLS to use 2048bit RSA keys for authentication.
+
  # openvpn --genkey --secret /etc/openvpn/server/ta.key
  
{{hc|/root/easy-rsa/vars|<nowiki>
+
This will be used to add an additional HMAC signature to all SSL/TLS handshake packets.  In addition any UDP packet not having the correct HMAC signature will be immediately dropped, protecting against:
# easy-rsa parameter settings
 
  
# NOTE: If you installed from an RPM,
+
* Portscanning.
# do not edit this file in place in
+
* DOS attacks on the OpenVPN UDP port.
# /usr/share/openvpn/easy-rsa --
+
* SSL/TLS handshake initiations from unauthorized machines.
# instead, you should copy the whole
+
* Any eventual buffer overflow vulnerabilities in the SSL/TLS implementation.
# easy-rsa directory to another location
 
# (such as /etc/openvpn) so that your
 
# edits will not be wiped out by a future
 
# OpenVPN package upgrade.
 
  
# This variable should point to
+
== OpenVPN client files ==
# the top level of the easy-rsa
 
# tree.
 
export EASY_RSA="`pwd`"
 
  
#
+
=== Client certificate and private key ===
# This variable should point to
 
# the requested executables
 
#
 
export OPENSSL="openssl"
 
export PKCS11TOOL="pkcs11-tool"
 
export GREP="grep"
 
  
# This variable should point to
+
Any machine can generate client files provided that {{pkg|easy-rsa}} is installed.
# the openssl.cnf file included
 
# with easy-rsa.
 
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
 
  
# Edit this variable to point to
+
If the pki is not initialized, do so via:
# your soon-to-be-created key
 
# directory.
 
#
 
# WARNING: clean-all will do
 
# a rm -rf on this directory
 
# so make sure you define
 
# it correctly!
 
export KEY_DIR="$EASY_RSA/keys"
 
  
# Issue rm -rf warning
+
# cd /etc/easy-rsa
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR
+
# easyrsa init-pki
  
# PKCS11 fixes
+
Generate the client key and certificate:
export PKCS11_MODULE_PATH="dummy"
 
export PKCS11_PIN="dummy"
 
  
# Increase this to 2048 if you
+
# cd /etc/easy-rsa
# are paranoid. This will slow
+
  # easyrsa gen-req client1 nopass
# down TLS negotiation performance
 
# as well as the one-time DH parms
 
# generation process.
 
</nowiki>'''export KEY_SIZE&#61;2048'''<nowiki>
 
  
# In how many days should the root CA key expire?
+
This will create two files:
export CA_EXPIRE=3650
 
  
# In how many days should certificates expire?
+
{{ic|/etc/easy-rsa/pki/reqs/client1.req}}
export KEY_EXPIRE=3650
+
{{ic|/etc/easy-rsa/pki/private/client1.key}}
  
# These are the default values for fields
+
The gen-req set can be repeated as many times as needed for additional clients.
# which will be placed in the certificate.
 
# Do not leave any of these fields blank.
 
  
</nowiki>
+
== Sign the certificates and pass them back to the server and clients ==
'''export KEY_COUNTRY&#61;"US"'''
 
'''export KEY_PROVINCE&#61;"CA"'''
 
'''export KEY_CITY&#61;"Acme Acres"'''
 
'''export KEY_ORG&#61;"Acme"'''
 
'''export KEY_EMAIL&#61;"roadrunner@acmecorp.org"'''
 
'''#export KEY_EMAIL&#61;mail@host.domain'''
 
'''export KEY_CN&#61;Acme-CA'''
 
'''export KEY_NAME&#61;Acme-CA'''
 
'''export KEY_OU&#61;""'''<nowiki>
 
export PKCS11_MODULE_PATH=changeme
 
export PKCS11_PIN=1234
 
</nowiki>}}
 
  
Export the environment variables.
+
=== Obtain and sign the certificates on the CA ===
  
{{bc|# source ./vars}}
+
The server and client(s) certificates need to be signed by the CA then transferred back to the OpenVPN server/client(s).
  
Delete any previously created certificates.
+
On the '''OpenVPN server''' (or the box used to generate the certificate/key pairs):
  
{{bc|# ./clean-all}}
+
# cp /etc/easy-rsa/pki/reqs/*.req /tmp
 +
# chown foo /tmp/*.req
  
{{Note| Entering a . (dot) when prompted for a value, blanks out the parameter.}}
+
Securely transfer the files to the CA machine for signing:
  
The build-ca script generates the [[Wikipedia:Certificate Authority|Certificate Authority (CA)]] certificate.
+
$ scp /tmp/*.req foo@hostname-of-CA:/tmp
  
{{hc|# ./build-ca|<nowiki>
+
On the '''CA machine''', import and sign the certificate requests:
Generating a 2048 bit RSA private key
 
..............++++++
 
...++++++
 
writing new private key to 'ca.key'
 
-----
 
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.
 
-----
 
Country Name (2 letter code) [US]:
 
State or Province Name (full name) [CA]:
 
Locality Name (eg, city) [Acme Acres]:
 
Organization Name (eg, company) [Acme]:
 
Organizational Unit Name (eg, section) []:
 
Common Name (eg, your name or your server's hostname) [Acme-CA]:
 
Name [Acme-CA]:
 
Email Address [roadrunner@acmecorp.org]:
 
</nowiki>}}
 
  
The build-key-server script {{ic|# ./build-key-server <server name>}} generates a server certificate. Make sure that the server name (Common Name when running the script) is unique.
+
# cd /etc/easy-rsa
 +
# easyrsa import-req /tmp/servername.req servername
 +
# easyrsa import-req /tmp/client1.req client1
 +
# easyrsa sign-req server servername
 +
# easyrsa sign-req client client1
  
{{Note|Do not enter a challenge password or company name when the script prompts you for one.}}
+
This will create the following signed certificates which can be transferred back to their respective machines:
  
{{hc|# ./build-key-server elmer|<nowiki>
+
{{ic|/etc/easy-rsa/pki/issued/servername.crt}}
Generating a 2048 bit RSA private key
+
{{ic|/etc/easy-rsa/pki/issued/client1.crt}}
.....................++++++
 
.......................................................++++++
 
writing new private key to 'elmer.key'
 
-----
 
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.
 
-----
 
Country Name (2 letter code) [US]:
 
State or Province Name (full name) [CA]:
 
Locality Name (eg, city) [Acme Acres]:
 
Organization Name (eg, company) [Acme]:
 
Organizational Unit Name (eg, section) []:
 
Common Name (eg, your name or your server's hostname) [elmer]:
 
Name [Acme-CA]:
 
Email Address [roadrunner@acmecorp.org]:
 
  
Please enter the following 'extra' attributes
+
The leftover .req files can be safely deleted:
to be sent with your certificate request
 
A challenge password []:
 
An optional company name []:
 
Using configuration from /root/easy-rsa/openssl-1.0.0.cnf
 
Check that the request matches the signature
 
Signature ok
 
The Subject's Distinguished Name is as follows
 
countryName          :PRINTABLE:'US'
 
stateOrProvinceName  :PRINTABLE:'CA'
 
localityName          :PRINTABLE:'Acme Acres'
 
organizationName      :PRINTABLE:'Acme'
 
commonName            :PRINTABLE:'elmer'
 
name                  :PRINTABLE:'Acme-CA'
 
emailAddress          :IA5STRING:'roadrunner@acmecorp.org'
 
Certificate is to be certified until Dec 27 19:11:59 2021 GMT (3650 days)
 
Sign the certificate? [y/n]:y
 
  
1 out of 1 certificate requests certified, commit? [y/n]y
+
# rm -f /tmp/*.req
Write out database with 1 new entries
 
Data Base Updated
 
</nowiki>}}
 
  
The build-dh script generates the [https://web.archive.org/web/20130701090246/https://www.rsa.com/rsalabs/node.asp?id=2248 Diffie-Hellman parameters] .pem file needed by the server. This command will take some time, possibly around a minute or two.
+
=== Pass the signed certificates back to the server and client(s) ===
  
{{Note|It would be better to generate a new one for each server, but you can use the same one if you want to.}}
+
On the '''CA machine''', copy the signed certificates and transfer them to the server/client(s):
  
{{hc|# ./build-dh|
+
# cp /etc/easy-rsa/pki/issued/*.crt /tmp
Generating DH parameters, 2048 bit long safe prime, generator 2
+
# chown foo /tmp/*.crt
This is going to take a long time
+
$ scp /tmp/*.crt foo@hostname-of-openvpn_server:/tmp
..+.............................................................................
+
 
.
+
On the '''OpenVPN server''', move the certificates in place and reassign ownership.
.
+
For the server:
.
+
# mv /tmp/servername.crt /etc/openvpn/server/
............+...............+...................................................
+
# chown root:root /etc/openvpn/server/servername.crt
..................................................................++*++*}}
+
For the client:
 +
# mkdir /etc/easy-rsa/pki/signed
 +
# mv /tmp/client1.crt /etc/easy-rsa/pki/signed
 +
 
 +
That is it. To generate the client profile. See: [[OpenVPN#ovpngen]].
 +
 
 +
== Revoking certificates and alerting the OpenVPN server ==
  
To generate the client(s) key(s), one can either do so on the server side directly using the {{ic|./build-key}} script, or generate the key entirely on the client side and then ask the CA authority to sign it. The first method is simpler and quicker, but the second method doesn't require the client private key to leave its machine and is therefore slightly more secure. (see [[#Creating certificates on the client]] for an outline of the second method)
+
=== Revoke a certificate ===
  
The build-key script {{ic|# ./build-key <client name>}} generates a client certificate. Make sure that the client name (Common Name when running the script) is unique.
+
Over time, it may become necessary to revoke a certificate thus denying access to the affected user(s).  This example revokes the "client1" certificate.
  
{{Note|Do not enter a challenge password or company name when the script prompts you for one.}}
+
On the '''CA machine''':
  
{{hc|# ./build-key bugs|<nowiki>
+
# cd /etc/easy-rsa
Generating a 2048 bit RSA private key
+
# easyrsa revoke client1
....++++++
+
# easyrsa gen-crl
.............................................................++++++
 
writing new private key to 'bugs.key'
 
-----
 
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.
 
-----
 
Country Name (2 letter code) [US]:
 
State or Province Name (full name) [CA]:
 
Locality Name (eg, city) [Acme Acres]:
 
Organization Name (eg, company) [Acme]:
 
Organizational Unit Name (eg, section) []:
 
Common Name (eg, your name or your server's hostname) [bugs]:
 
Name [Acme-CA]:
 
Email Address [roadrunner@acmecorp.org]:
 
  
Please enter the following 'extra' attributes
+
This will produce the CRL file {{ic|/etc/easy-rsa/pki/crl.pem}} that needs to be transferred to the OpenVPN server and made active there.
to be sent with your certificate request
 
A challenge password []:
 
An optional company name []:
 
Using configuration from /root/easy-rsa/openssl-1.0.0.cnf
 
Check that the request matches the signature
 
Signature ok
 
The Subject's Distinguished Name is as follows
 
countryName          :PRINTABLE:'US'
 
stateOrProvinceName  :PRINTABLE:'CA'
 
localityName          :PRINTABLE:'Acme Acres'
 
organizationName      :PRINTABLE:'Acme'
 
commonName            :PRINTABLE:'bugs'
 
name                  :PRINTABLE:'Acme-CA'
 
emailAddress          :IA5STRING:'roadrunner@acmecorp.org'
 
Certificate is to be certified until Dec 27 19:18:27 2021 GMT (3650 days)
 
Sign the certificate? [y/n]:y
 
  
1 out of 1 certificate requests certified, commit? [y/n]y
+
=== Alert the OpenVPN server ===
Write out database with 1 new entries
 
Data Base Updated
 
</nowiki>}}
 
This generates a client certificate ({{ic|bugs.crt}}) and a client private key ({{ic|bugs.key}}) which need to be transferred to the client through a secure channel.
 
 
Generate a secret [[Wikipedia:HMAC|Hash-based Message Authentication Code (HMAC)]] by running:
 
{{ic|# openvpn --genkey --secret /root/easy-rsa/keys/ta.key}} (This is no typo -- the command generates a ta.key file)
 
  
This will be used to add an additional HMAC signature to all SSL/TLS handshake packets.  In addition any UDP packet not having the correct HMAC signature will be immediately dropped, protecting against:
+
On the '''CA machine''':
  
* Portscanning.
+
# cp /etc/easy-rsa/pki/crl.pem /tmp
* DOS attacks on the OpenVPN UDP port.
+
# chown foo /tmp/crl.pem
* SSL/TLS handshake initiations from unauthorized machines.
 
* Any eventual buffer overflow vulnerabilities in the SSL/TLS implementation.
 
  
All the created keys and certificates have been stored in /root/easy-rsa/keys.  If you make a mistake, you can start over by running the clean-all script again.
+
On the '''OpenVPN machine''', copy {{ic|crl.pem}} and inform the server to read it:
 +
# mv /tmp/crl.pem /etc/openvpn/server/
 +
# chown root:root /etc/openvpn/server/crl.pem
  
{{Warning|This will delete any previously generated certificates stored in /root/easy-rsa/keys, including the [[Wikipedia:Certificate Authority|Certificate Authority (CA)]] certificate.}}
+
Edit {{ic|/etc/openvpn/server/server.conf}} uncommenting the crl-verify directive, then [[restart]] openvpn-server@server.service to re-read it:
 +
 +
{{hc|/etc/openvpn/server/server.conf|
 +
.
 +
crl-verify /etc/openvpn/server/crl.pem
 +
.
 +
}}
  
===Creating certificates on the client===
+
== Abbreviated example specifically for containerized Openvpn ==
It might be desirable for the clients to generate their private keys on their own machine, removing the need to trust that the CA operator not keep the client's private key stored remotely (or other nefarious intentions). To do so, the client needs to create the private key locally, and create a [https://en.wikipedia.org/wiki/Certificate_signing_request|Certificate Signing Request] (which is a {{ic|.csr}} file) to the key-signing machine, run by the CA. The operator will then sign the request and return a signed certificate (a {{ic|.crt}} file) which is then transferred back to the client.
+
This section is specifically for users wanting to run Openvpn in a Linux container ([[LXC]]). The code below is designed to be  pasted into a root shell; the standard hash has been omitted to allow for easy copy/paste operations. It is recommended to have two different shell windows open, one for the host and one for the container.
  
====Creating a certificate signing request====
+
{{Note|
 +
* It is assumed that the CA machine is the host and the server machine is the container.
 +
* Both the host and container need to have both {{pkg|openvpn}} and {{pkg|easy-rsa}} installed.
 +
* The container needs to be running.
 +
* Define the name of the container in the CONTAINERNAME variable below.
 +
}}
  
An outline of the required steps follows, assuming "bugs" is the client name:
+
On the host:
# Transfer the {{ic|ca.crt}} file from the CA to the client. The {{ic|ca.crt}} file is public information, and thus this transfer can be done over an insecure channel. The file should be stored in {{ic|/root/easy-rsa/keys/ca.crt}}
+
CONTAINERNAME=foo
# Check that the {{ic|ca.crt}} file has not been tampered with by either:
+
/etc/easy-rsa
## Having the file be signed by the CA and verified by the client using the CA's public key. Note that this is referring to standard [[GnuPG#Signatures|GnuPG]]-style signature verification: {{ic|gpg --verify doc.sig}}
+
easyrsa init-pki && easyrsa build-ca
## Checking the hash of the file (e.g. using {{ic|sha1sum ca.crt}}) and verifying that it matches the expected hash, provided you trust the "expected hash".
+
cp /etc/easy-rsa/pki/ca.crt /var/lib/lxc/$CONTAINERNAME/rootfs/etc/openvpn/server/
## Simply transferring ca.crt over a trusted channel.
 
## Some other mechanism that the reader sees fit.
 
# Run {{ic|./build-req bugs}} which is analogous to running  {{ic|./build-key bugs}} in the server section above. The same warning, that the Common Name should be unique, still stands.
 
# Leave all password field blank. If you'd like to protect your private key with a password, use {{ic|./build-req-pass}} instead. Note that this will require you to input the password whenever the key needs to be unlocked.
 
# You now have the {{ic|bugs.csr}} and {{ic|bugs.key}} files. Send your certificate signing request to the CA, e.g. by emailing your {{ic|bugs.csr}} file. Keep your {{ic|bugs.key}} file secret, this is your private key.
 
# Wait until you receive your signed certificate from the CA, which will be a file named {{ic|bugs.crt}}.
 
  
====Signing a certificate signing request====
+
{{Note|One may substitute other names in the 2nd line of this code (the for loop).  At a minimum, one needs to generate a key for the server and for at least 1 client.  The generic words "server" and "client" are shown, but in reality, these can by any words such as the hostname of the container or the name of the intended user.  As well, one can add additional words to the for loop if more than 2 keys are needed.  If that is the case, just be sure to add corresponding lines to the subsequent steps for each of them.}}
  
To sign a certificate signing request, the CA simply needs to run {{ic|./sign-req bugs}} after placing {{ic|bugs.csr}} into {{ic|/root/easy-rsa/keys/bugs.csr}}. The CA can then transfer the resulting {{ic|bugs.crt}} file back the client using an insecure channel (e.g. via email)
+
In the container:
{{Note| When running the command, the error {{ic|chmod: cannot access `bugs.key': No such file or directory}} will show up. This is expected, and is safe to ignore [https://forums.openvpn.net/topic13418.html]}}
+
cd /etc/easy-rsa && easyrsa init-pki
 +
for i in server client; do easyrsa gen-req $i nopass; done
 +
cp /etc/easy-rsa/pki/private/server.key /etc/openvpn/server/
 +
openssl dhparam -out /etc/openvpn/server/dh.pem 2048
 +
openvpn --genkey --secret /etc/openvpn/server/ta.key
  
===Converting certificates to encrypted .p12 format===
+
Back on the host:
 +
easyrsa import-req /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/reqs/junk.req junk
 +
easyrsa import-req /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/reqs/client.req client
 +
easyrsa sign-req client client
 +
easyrsa sign-req server server
 +
mkdir /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/issued/
 +
mkdir /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/signed/
 +
cp /etc/easy-rsa/pki/issued/*.crt /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/issued/
  
Some software (such as Android) will only read VPN certificates that are stored in a password-encrypted .p12 file. These can be generated with the following command:
+
That will provide the needed files to make an OpenVPN compatible tunnel profile for the client, and the needed server key files for the server. To generate a client profile, refer to  [[OpenVPN#ovpngen]].
{{bc|# openssl pkcs12 -export -inkey keys/bugs.key -in keys/bugs.crt -certfile keys/ca.crt -out keys/bugs.p12}}
 
  
 +
== See also ==
  
== See Also ==
+
* [https://github.com/OpenVPN/easy-rsa/blob/master/README.quickstart.md README.quickstart].
* [https://openvpn.net/index.php/open-source/documentation/miscellaneous/rsa-key-management.html Official EasyRSA instructions]
+
* [https://github.com/OpenVPN/easy-rsa/blob/master/doc/EasyRSA-Advanced.md EASYRSA-Advanced].

Latest revision as of 07:33, 27 February 2020

The first step when setting up OpenVPN is to create a Public Key Infrastructure (PKI). In summary, this consists of:

  • A public master Certificate Authority (CA) certificate and a private key.
  • A separate public certificate and private key pair for each server.
  • A separate public certificate and private key pair for each client.

One can think of the key-based authentication in terms similar to that of how SSH keys work with the added layer of a signing authority (the CA). OpenVPN relies on a bidirectional authentication strategy, so the client must authenticate the server's certificate and in parallel, the server must authenticate the client's certificate. This is accomplished by the 3rd party's signature (the CA) on both the client and server certificates. Once this is established, further checks are performed before the authentication is complete. For more details, see secure-computing's guide.

Note:
  • The process outlined below requires users to securely transfer private key files to/from machines. For the purposes of this guide, using scp is shown, but readers may employ alternative methods as well. Since the Arch default is to deny the root user over ssh, using scp requires transferring ownership of the files to be exported to a non-root user called foo throughout the guide.
  • Avoid generating keys on devices without a good entropy source. See [1]. Sometimes, cryptographically secure pseudorandom number generators can be used.

Certificate Authority (CA)

For security purposes, it is recommended that the CA machine be separate from the machine running OpenVPN.

On the CA machine, install easy-rsa, initialize a new PKI and generate a CA keypair that will be used to sign certificates:

# cd /etc/easy-rsa
# export EASYRSA=$(pwd)
# easyrsa init-pki
# easyrsa build-ca

Starting from OpenVPN 2.4, one can also use elliptic curves for TLS connections (e.g. tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384). Elliptic curve cryptography provides more security and eliminates the need for a Diffie-Hellman parameters file. See [2] and [3].

Append the following lines to /etc/easy-rsa/vars to make Easy-RSA use elliptic curves:

/etc/easy-rsa/vars
set_var EASYRSA_ALGO     ec
set_var EASYRSA_CURVE    secp521r1
set_var EASYRSA_DIGEST   "sha512"

Now set up PKI and generate a CA certificate:

# cd /etc/easy-rsa
# export EASYRSA=$(pwd)
# export EASYRSA_VARS_FILE=/etc/easy-rsa/vars
# easyrsa init-pki
# easyrsa build-ca

OpenVPN server files

A functional OpenVPN server requires the following:

  1. The CA's public certificate
  2. The Diffie-Hellman (DH) parameters file (required by TLS mode when not using TLS with elliptic curves).
  3. The server key pair (a public certificate and a private key).
  4. The Hash-based Message Authentication Code (HMAC) key.

Upon completing the steps outlined in this article, users will have generated the following files on the server:

  1. /etc/openvpn/server/ca.crt
  2. /etc/openvpn/server/dh.pem (not when using TLS with elliptic curves)
  3. /etc/openvpn/server/servername.crt and /etc/openvpn/server/servername.key
  4. /etc/openvpn/server/ta.key

CA public certificate

The CA public certificate /etc/easy-rsa/pki/ca.crt generated in the previous step needs to be copied over to the machine that will be running OpenVPN.

On the CA machine:

# scp /etc/easy-rsa/pki/ca.crt foo@hostname-of-openvpn-server:/tmp/ca.crt

On the OpenVPN server machine:

# mv /tmp/ca.crt /etc/openvpn/server/
# chown root:root /etc/openvpn/server/ca.crt

Server certificate and private key

On the OpenVPN server machine, install easy-rsa and generate a key pair for the server:

# cd /etc/easy-rsa
# easyrsa init-pki
# easyrsa gen-req servername nopass
# cp /etc/easy-rsa/pki/private/servername.key /etc/openvpn/server/

This will create two files:

/etc/easy-rsa/pki/reqs/servername.req /etc/easy-rsa/pki/private/servername.key

Diffie-Hellman (DH) parameters file

Note: If you are using TLS with elliptic curves, skip this step.

On the OpenVPN server machine, create the initial dh.pem file:

# openssl dhparam -out /etc/openvpn/server/dh.pem 2048
Note: Although values higher than 2048 (4096 for example) may be used, they take considerably more time to generate and offer little benefit in security but advisable to have the DH prime number length to match the length of the RSA key. See [4]

Hash-based Message Authentication Code (HMAC) key

On the OpenVPN server machine, create the HMAC key:

# openvpn --genkey --secret /etc/openvpn/server/ta.key

This will be used to add an additional HMAC signature to all SSL/TLS handshake packets. In addition any UDP packet not having the correct HMAC signature will be immediately dropped, protecting against:

  • Portscanning.
  • DOS attacks on the OpenVPN UDP port.
  • SSL/TLS handshake initiations from unauthorized machines.
  • Any eventual buffer overflow vulnerabilities in the SSL/TLS implementation.

OpenVPN client files

Client certificate and private key

Any machine can generate client files provided that easy-rsa is installed.

If the pki is not initialized, do so via:

# cd /etc/easy-rsa
# easyrsa init-pki

Generate the client key and certificate:

# cd /etc/easy-rsa
# easyrsa gen-req client1 nopass

This will create two files:

/etc/easy-rsa/pki/reqs/client1.req /etc/easy-rsa/pki/private/client1.key

The gen-req set can be repeated as many times as needed for additional clients.

Sign the certificates and pass them back to the server and clients

Obtain and sign the certificates on the CA

The server and client(s) certificates need to be signed by the CA then transferred back to the OpenVPN server/client(s).

On the OpenVPN server (or the box used to generate the certificate/key pairs):

# cp /etc/easy-rsa/pki/reqs/*.req /tmp
# chown foo /tmp/*.req

Securely transfer the files to the CA machine for signing:

$ scp /tmp/*.req foo@hostname-of-CA:/tmp

On the CA machine, import and sign the certificate requests:

# cd /etc/easy-rsa
# easyrsa import-req /tmp/servername.req servername
# easyrsa import-req /tmp/client1.req client1
# easyrsa sign-req server servername
# easyrsa sign-req client client1

This will create the following signed certificates which can be transferred back to their respective machines:

/etc/easy-rsa/pki/issued/servername.crt /etc/easy-rsa/pki/issued/client1.crt

The leftover .req files can be safely deleted:

# rm -f /tmp/*.req

Pass the signed certificates back to the server and client(s)

On the CA machine, copy the signed certificates and transfer them to the server/client(s):

# cp /etc/easy-rsa/pki/issued/*.crt /tmp
# chown foo /tmp/*.crt
$ scp /tmp/*.crt foo@hostname-of-openvpn_server:/tmp

On the OpenVPN server, move the certificates in place and reassign ownership. For the server:

# mv /tmp/servername.crt /etc/openvpn/server/
# chown root:root /etc/openvpn/server/servername.crt

For the client:

# mkdir /etc/easy-rsa/pki/signed
# mv /tmp/client1.crt /etc/easy-rsa/pki/signed

That is it. To generate the client profile. See: OpenVPN#ovpngen.

Revoking certificates and alerting the OpenVPN server

Revoke a certificate

Over time, it may become necessary to revoke a certificate thus denying access to the affected user(s). This example revokes the "client1" certificate.

On the CA machine:

# cd /etc/easy-rsa
# easyrsa revoke client1
# easyrsa gen-crl

This will produce the CRL file /etc/easy-rsa/pki/crl.pem that needs to be transferred to the OpenVPN server and made active there.

Alert the OpenVPN server

On the CA machine:

# cp /etc/easy-rsa/pki/crl.pem /tmp
# chown foo /tmp/crl.pem

On the OpenVPN machine, copy crl.pem and inform the server to read it:

# mv /tmp/crl.pem /etc/openvpn/server/
# chown root:root /etc/openvpn/server/crl.pem

Edit /etc/openvpn/server/server.conf uncommenting the crl-verify directive, then restart openvpn-server@server.service to re-read it:

/etc/openvpn/server/server.conf
.
crl-verify /etc/openvpn/server/crl.pem
.

Abbreviated example specifically for containerized Openvpn

This section is specifically for users wanting to run Openvpn in a Linux container (LXC). The code below is designed to be pasted into a root shell; the standard hash has been omitted to allow for easy copy/paste operations. It is recommended to have two different shell windows open, one for the host and one for the container.

Note:
  • It is assumed that the CA machine is the host and the server machine is the container.
  • Both the host and container need to have both openvpn and easy-rsa installed.
  • The container needs to be running.
  • Define the name of the container in the CONTAINERNAME variable below.

On the host:

CONTAINERNAME=foo
/etc/easy-rsa
easyrsa init-pki && easyrsa build-ca
cp /etc/easy-rsa/pki/ca.crt /var/lib/lxc/$CONTAINERNAME/rootfs/etc/openvpn/server/
Note: One may substitute other names in the 2nd line of this code (the for loop). At a minimum, one needs to generate a key for the server and for at least 1 client. The generic words "server" and "client" are shown, but in reality, these can by any words such as the hostname of the container or the name of the intended user. As well, one can add additional words to the for loop if more than 2 keys are needed. If that is the case, just be sure to add corresponding lines to the subsequent steps for each of them.

In the container:

cd /etc/easy-rsa && easyrsa init-pki
for i in server client; do easyrsa gen-req $i nopass; done
cp /etc/easy-rsa/pki/private/server.key /etc/openvpn/server/
openssl dhparam -out /etc/openvpn/server/dh.pem 2048
openvpn --genkey --secret /etc/openvpn/server/ta.key

Back on the host:

easyrsa import-req /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/reqs/junk.req junk
easyrsa import-req /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/reqs/client.req client
easyrsa sign-req client client
easyrsa sign-req server server
mkdir /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/issued/
mkdir /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/signed/
cp /etc/easy-rsa/pki/issued/*.crt /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/issued/

That will provide the needed files to make an OpenVPN compatible tunnel profile for the client, and the needed server key files for the server. To generate a client profile, refer to OpenVPN#ovpngen.

See also