I’ve been setting up a vpn network using OpenVPN. The dog-in-charge demands that I implement Transport Layer Security (TLS). TLS requires creating a series of certifications and keys which can then be referenced from a VPN configuration file.

This post is about the process of implementing TLS. It is not about the tools, i.e. the command-line instructions, that are available for implementing TLS. The tools will be discussed in another post.

The Certificate Authority

Transport Layer Security begins with a Certificate Authority (CA). The CA has two parts: a private key, stored in the file ca.key, and a public certificate, stored in the file ca.crt. Those file names are arbitrary–you can call them anything you want–but those are the names commonly used on the interwebs for talking about them.

ca.key is super-secret. ca.key has the “root” signing authority. The only way to gain access to the network is with a certificate that has been signed by ca.key. It’s secrecy is important enough that it is often kept off the network and stored off-site or on a thumb-drive. I keep mine in my prison wallet.

ca.crt is public. It can (and must) be shared with vpn clients. Its contents include an encrypted code for verifying that a peer-machine’s certificate was signed by ca.key. ca.crt establishes a link to ca.key without disclosing ca.key’s contents or location. ca.crt has no signing authority. It cannot sign new certificates for new clients; it can only verify that a client’s certificate was signed by a legitimate signing authority.

On a small vpn network like mine, the CA is “self-signing”. Large networks and secure internet addresses use certificates signed by a commercial signing authority. For example, when I purchased the domain adogslaboratory.net from Porkbun, it came with a certificate signed by Let’s Encrypt that I can use to publish my website over the https protocol. Websites without an official CA can’t use https.

But for my private purposes a self-signing certificate is sufficient. I create ca.key and I am responsible for keeping it super-secret. No one can join my vpn unless they have a certificate that was signed by my ca.key.

So, if our server, home-cooking, is going to use TLS to secure its vpn network, the first step is to generate ca.key and ca.crt. We will skip over the CLI commands for now and come back to them in a later post.

The private key, the Certificate Signing Request, and the public certificate

Once home-cooking has ca.key and ca.crt in hand it can proceed to the next step: creating a private key (which we will call home-cooking.key) and a Certificate Signing Request (home-cooking.csr).

Like ca.key, home-cooking.key is secret. It may not be super-secret, but it is secret. home-cooking will keep its private key protected with 600 security permissions.

The .csr file is only temporary. It will be presented to ca.key for signing. ca.key will respond to the CSR and sign a new public certificate, home-cooking.crt. Once the public certificate has been signed,home-cooking.csr is no longer needed and it can be deleted.

Our server now has its own private key (home-cooking.key) and public certificate (home-cooking.crt). It also has possession of ca.key and ca.crt.

What about the client?

It’s time to introduce distant-cousin. distant-cousin wants to be a client on home-cooking’s vpn but it lacks the credentials. So, it asks home-cooking to hook a cousin up. home-cooking goes through the same steps as before: create distant-cousin.key and distant-cousin.csr; present the .csr file to ca.key; receive the signed distant-cousin.crt back from ca.key; and delete distant-cousin.csr.

At this point we have signed certificates for both machines. We are done using ca.key for now. It can be safely keistered (keystered?).

Now, if you are keeping track, home-cooking has five files in its possession: ca.crt, home-cooking.key, home-cooking.crt, distant-cousin.key, and distant-cousin.crt. home-cooking sends distant-cousin.key, distant-cousin.crt and a copy of ca.crt to distant-cousin.

Each computer now has in its possession its own private key (the <hostname>.key file), a public certificate (<hostname>.crt) and a copy of the CA’s public certificate, ca.crt. These three files, locally stored on each machine connected to the vpn, combine to produce a TLS-secured network.

Teamwork makes the dream work

So, how do these pieces all fit together?

When distant-cousin wants to connect to the vpn it contacts the server, home-cooking. home-cooking uses home-cooking.key to generate a personal signature. It presents its public certificate, home-cooking.crt, to distant-cousin along with the signature. distant-cousin compares the signature against the contents of the certificate and uses ca.crt to verify that the certificate was issued by ca.key.

distant-cousin does the whole thing in reverse, sending its signature and certificate to home-cooking so that home-cooking can authenticate its credentials using the same process.

Each of the documents performs an essential function. The private key is secret and never leaves its host. Only the private key can produce the signature used by that particular machine. The public certificate is the credential signed by the “root” signing authority, ca.key. And ca.crt is the CA’s public certificate, providing an authoritative link to ca.key.

Wrapping things up

So that is how it all works toge….wait….I feel like I’ve forgotten something…oh crap.

I forgot ta.key. Screw it, I’m done for the night.