Manual CA with easyrsa
If you need help creating one, you might find the easyrsa package helpful. Use the following to manage an easyrsa-based PKI for OpenVPN…
Initial Setup
First download the easyrsa
package.
$ mkdir easyrsa
$ wget -qO- "https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.0-rc1/EasyRSA-3.0.0-rc1.tgz" \
| tar -xzC easyrsa --strip-components 1
Customize a .envrc
file to store some reusable config values (try direnv…
$ cat > .env << EOF
export OPENVPN_HOST="vpn.example.com"
export OPENVPN_PORT=1194
export EASYRSA_VARS_FILE="vars"
export EASYRSA_REQ_COUNTRY="US"
export EASYRSA_REQ_PROVINCE="California"
export EASYRSA_REQ_CITY="San Francisco"
export EASYRSA_REQ_ORG="Copyleft Certificate Co"
export EASYRSA_REQ_OU="My Organizational Unit"
export EASYRSA_REQ_EMAIL="me@example.net"
EOF
$ direnv allow
direnv: loading .envrc
Initialize your PKI and create the authority…
$ ( cd easyrsa/ && EASYRSA_PKI=../pki ./easyrsa init-pki )
$ cd pki
$ cat ../easyrsa/vars.example \
| sed -E "s/^#?set_var[[:space:]]+EASYRSA[[:space:]]+.*\$/set_var EASYRSA \"\$PWD\/..\/easyrsa\"/" \
| sed -E "s/^#?set_var[[:space:]]+EASYRSA_PKI[[:space:]]+.*\$/set_var EASYRSA_PKI \"\$PWD\"/" \
> vars
$ ../easyrsa/easyrsa build-ca
# password will be used whenever you need to sign new certificates
# common name = openvpn
$ ../easyrsa/easyrsa gen-crl
$ ../easyrsa/easyrsa gen-dh
$ cd ../
Creating a New Key
When a server or client needs to generate a certificate, you can use a temporary directory and openssl
to create one.
First create a temporary directory, named after the unique server or client profile name…
mkdir main-server
cd main-server
Then create a key and certificate request…
$ openssl req -new -nodes -days 3650 -newkey rsa:2048 \
-subj "/C=$EASYRSA_REQ_COUNTRY/ST=$EASYRSA_REQ_PROVINCE/L=$EASYRSA_REQ_CITY/O=$EASYRSA_REQ_ORG/OU=$EASYRSA_REQ_OU/CN=$( basename $PWD )/emailAddress=$EASYRSA_REQ_EMAIL" \
-out "$( dirname $PWD ).req" \
-keyout "$( dirname $PWD ).key"
Sign the certificate. In the case of a server certificate, you may want to retain the private key in your pki
directory…
cp "$( dirname $PWD ).key" "$PKI_DIR/private/$( dirname $PWD ).key"
Once signed and delivered for the connection profile, you should delete the temporary directory with the *.req
and *.key
files.
Signing a Certificate Request
The easyrsa
package can create two types of certificates (client and server) which can only be used for their specific purpose. Assuming you received a certificate signing request file of certificate.req
, first import it into your pki
directory…
$ CN=$( openssl req -in certificate.req -noout -subject | sed -E 's#^.+/CN=([^/]+).*#\1#' )
$ mv certificate.req "pki/reqs/$CN.req"
$ cd pki
Server Certificate
$ ../easyrsa/easyrsa sign server "$CN"
Client Certificate
$ ../easyrsa/easyrsa sign client "$CN"
Once a certificate is signed, you can provide it back to the requester.
$ cat "pki/issued/$CN.crt"
Server Configuration
Once you have a PKI setup and a server key-pair configured, you can use the file data for the openvpn
job properties.
tls_key_pair.ca
is./pki/ca.crt
tls_key_pair.certificate
is./pki/issued/main-server.crt
tls_key_pair.private_key
is./pki/private/main-server.key
tls_crl
is./pki/crl.pem
dh_pem
is./pki/dh.pem
Client Configuration
Once a client has had their key-pair signed, they will want to include it in the base OpenVPN profile configuration:
<key>
is the client private key<cert>
is the signed certificate
Typically, the base OpenVPN profile configuration should be provided by the OpenVPN server operator. It will look something like the following.
client
dev tun
proto tcp
remote $OPENVPN_HOST $OPENVPN_PORT
comp-lzo
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
remote-cert-tls server
verb 3
mute 20
tls-client
<ca>
# OpenVPN server CA
</ca>
Once the user appends their private key to the profile, they can use file with their OpenVPN client.
$ openvpn –config client.ovpn