TLS Client Authentication with Certificates (nginx + easyrsa)

Begin by picking a seperate machine (or container) to store the certificate authority. Because this machine is charged with generating certificates we will be using as trusted authentication factors, it is important that this machine is well secured. It's considered bad practice to store the ceritficate authority on the web server.

Download easyrsa3

easy-rsa is a set of shell scripts that simplify managing a public-key infrastructure of certificates and keys. It calls the openssl binary.

$ wget https://github.com/OpenVPN/easy-rsa/archive/master.zip
$ unzip master.zip
$ sudo cp -r easy-rsa-master/easyrsa3 /root/easyrsa3

Generate PKI folder

The PKI folder is where your keys and certificates will be stored.

$ sudo -i
# cd /root/easyrsa3
# easyrsa ./init-pki

A variable files (/root/easyrsa3/vars) customizes options such as expiry time. By default, the client certificates are set to have an expiration date of 10 years. In my opinion, this is far too long. The default values are shown in vars.example.

# cat > /root/easyrsa3/vars << $EOF
set_var EASYRSA_CA_EXPIRE 768
set_var EASYRSA_CERT_EXPIRE 30
$EOF

Generate the CA

Make sure you pick a secure password when prompted

# ./easyrsa build-ca

Generate the first certificate

We will later install this on our browser.
This certificate will be required to access our protected https server.

$ ./easyrsa build-client-full rohan-laptop nopass
$ ./easyrsa export-p12 rohan-laptop

We then install the PKCS12 bundle to our browser. The PKCS12 bundle contains both our certificate and key. Importing into the browser is quite easy. For both firefox and chrome you go into

settings -> advanced -> manage certificates -> your certificates -> import

Setting nginx to require certificate authentication

From our CA box, we scp our CA certificate and our CRL to our webserver. Also, it's worth mentioning, that unlike keys, these files are not strictly confidential.

# scp pki/ca.crt  root@webserver:/etc/ssl/nginx_ca.crt

Then add the following lines to your SSL site configuration

# CA for verifying client cert 
ssl_client_certificate /etc/ssl/nginx_ca.crt;
# Client must possess a certificate verified by the CA
ssl_verify_client on;

Now restart nginx. Now, if your certificate is not properly installed in your browser, you will get an error message of the 400 response. (Use a different browser to be sure of this). Otherwise, with the cert installed, your browser should notify you to say the site has requested a certificate.

That's all. Hope this was helpful