We begin by picking a machine (or container) we will be using as a 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.
We begin by downloading easyrsa3
easy-rsa is a set of shell scripts that simplify managing a public-key infrastructure of certificates and keys. It calls the
# If you don't have git # wget https://github.com/OpenVPN/easy-rsa/archive/master.zip $ git clone https://github.com/OpenVPN/easy-rsa
Generate our PKI folder
$ cd easy-rsa/easyrsa3 && ./easyrsa init-pki
By default, our client certificates are set to have an expiration date of 10 years. This is waay too long.
We set our CA to expire in two years and our client cert to expire in one year by setting the following variables
set_var EASYRSA_CA_EXPIRE 768
set_var EASYRSA_CERT_EXPIRE 365
$ cp vars.example vars $ nano vars
Generate our CA
Make sure you pick a secure password when prompted
$ ./easyrsa build-ca
Generate Certificate Revocation List
A certificate revocation list is a digitally signed list of certificates that have been revoked. In a secure, production environment, we store the key for the crl on a separate machine than the CA. This way, if the CA is compromised, we can still issue out the revocation so our browsers and web servers know the key should not be trusted. For our purposes, we can just keep it in our easy-rsa/pki working directory.
$ ./easyrsa gen-crl
Generate our 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 relatively trivial. For both firefox and chrome you go into
settings -> advanced -> manage certificates -> your certificates -> import
Setting the server to require 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. If paranoid (or sensible), you may want to keep a hash of these files
$ scp pki/ca.crt root@webserver:/etc/ssl/nginx_ca.crt $ scp pki/crl.pem root@webserver:/etc/ssl/nginx_ca.crl
First, make a backup of the nginx config file. Then edit it, for simplicity sake, we'll not assume virtual hosts as that can potentially complicate things (you can do ssl/tls with vhosts with a feature known as SNI, but I'm not completely certain it works fine for client side tls)
In the nginx settings, we have two sections for client and server certificates
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Certificate for standard HTTPS ssl_certificate /etc/ssl/fakedomain.etherarp.net/fakedomain.etherarp.net.crt; ssl_certificate_key /etc/ssl/fakedomain.etherarp.net/fakedomain.etherarp.net.key; # CA for verifying client cert ssl_client_certificate /etc/ssl/nginx_ca.crt; ssl_crl /etc/ssl/nginx_ca.crl; # 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.
Final note, you cant use https client authentication on a per-location basis because the TLS handshake occurs before any dialogue with the webserver (GET, POST etc) takes place.
That's all. Hope this was helpful