Your own SSL Certificate Authority on Linux

Your own SSL Certificate Authority on Linux

With your own Certificate Authority you can get rid of browser security warnings and you don't need to import single site certificates, only the CA root certificate once.

Creating your own Certificate Authority is useful when you run multiple intranet web servers or software with an web interface (Like Routers, PFSense, OPNSense, ESXI etc.).

In this How-To we focus on Https and Browsers, but you can also use your CA for mail servers, databases and other applications.

Certificate Authority Workflow

Like on the internet, instead of generating a self-signed certificate, you generate an private key and a Certificate Signing Request (CSR) from your webserver. With your Certificate Authority keys you generate the public certificate (CRT) for the CSR, which you install on your webserver.

Once your clients trust your CA, they are going to also trust the signed certificate.

Prerequisites

An DNS server in your network makes things easier, especially since Chrome 65, else you could also use the hosts file (/etc/hosts on Linux) in order to set up FQDNs.

Openssl needs to be installed too and your web server needs support for SSL (mod_ssl etc.).

Most software with an web interface, like PFSense or ESXI, allow you to generate a Certificate Signing Request directly from it.

Creating your own Certificate Authority

On your Linux computer (not on the server!) use openssl to generate the CA's private key and root certificate.

$ openssl genrsa -aes256 -out ca.key 4096
Generating RSA private key, 4096 bit long modulus
..........................................................................................................................................................................++++
............++++
e is 65537 (0x010001)

Make sure you put in a secure passphrase, this prevents anyone with the private key file to generate root certificates without it.

Next we generate the root certificate for the clients of our CA with 3 years validity. For compatibility reasons we generate an PEM and CRT file.

$ openssl req -x509 -new -nodes -key ca.key -sha256 -days 1095 -out ca.pem
Enter pass phrase for 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) [AU]:US
State or Province Name (full name) [Some-State]:Texas
Locality Name (eg, city) []:Austin
Organization Name (eg, company) [Internet Widgits Pty Ltd]:bytee.net
Organizational Unit Name (eg, section) []:security
Common Name (e.g. server FQDN or YOUR name) []:bytee.local
Email Address []:contact@bytee.net

Converting the PEM file to a CRT file:

$ openssl x509 -in ca.pem -inform PEM -out ca.crt

You now have three files, your private key (ca.key) and your root certificate (ca.pem and ca.crt).

Congratulations your CA is ready to be deployed!

Importing your root certificate on Linux

Installing the CA root certificate is quite forward on most Linux distributions. First create a directory for extra certificates in /usr/share/ca-certificates, if you want want you could also use /usr/local/share/ca-certificates:

# mkdir /usr/share/ca-certificates/extra

Next copy the CA .crt file to this directory:

# cp ca.crt /usr/share/ca-certificates/extra

Finally run update-ca-certificates to generate a new concatenated Linux ca-certificates.crt file, which Linux uses system-wide for validating certificates.

Please note that Firefox and Chrome don't use the system-wide certificates on Linux. You need to import the certificate in your browser manually. For Chromium / Chrome just navigate to chrome://settings/certificates, choose Authorities and click on Import.

Generate a CSR for Apache

As example, we are going to generate a certificate request for an Apache Web Server and the domain web.bytee.local. For most other web servers, like NGINX it's similar.

First you need to generate the private key for the Apache vhost:

$ openssl genrsa -out web.bytee.local.key 4096 

Next generate the certificate signing request (CSR):

$ openssl req -new -key web.bytee.local.key -out web.bytee.local.csr

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) [AU]:US
State or Province Name (full name) [Some-State]:Texas
Locality Name (eg, city) []:Austin
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bytee.net
Organizational Unit Name (eg, section) []:web
Common Name (e.g. server FQDN or YOUR name) []:web.bytee.local
Email Address []:info@bytee.net

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

With your CA key you can now generate the public certificate (CRT) for the web server.

Starting with Chrome 65 we need to supply subject alternative names (DNS names) to the certificate though, else Chrome is going to show an error message. To prevent this, you need to include an external file in the generation, call it web.bytee.local.ssl.conf with this content:

subjectAltName = @alt_names

[alt_names]
DNS.1   = web.bytee.local
DNS.2   = web

Now you are ready to sign it:

$ openssl x509 -req -in web.bytee.local.csr -CA ca.pem -CAkey ca.key -out web.bytee.local.crt -days 1095 -sha256 -extfile web.bytee.local.ssl.conf
Signature ok
subject=C = US, ST = Texas, L = Austin, O = Bytee.net, OU = web, CN = web.bytee.local, emailAddress = info@bytee.net
Getting CA Private Key
Enter pass phrase for ca.key:

Now configure Apache to use the newly generated certificate (private key + crt file) and reload the service.

For any other server (or vhost) just repeat the last steps of generating the CSR and creating the CRT.