Post

Creating your own custom CA

As the constant security warnings displayed by my browser when accessing my local infrastructure annoyed me already for a long time I decided to look into the task of creating my own custom CA (“certificate authority”). There is not a lot of “local infrastructure” to be honest, basically my router and NAS drive. Anyway, I tend to access those via https and thus generating a warning by my browser telling me this site has no valid certificate. Of course, devices like this run with self-signed certificates, unknown to any browser.

So, the overall goal was to create my own CA, import the CA certificate into to my devices/browsers and then sign individual certificates for my router and NAS drive with my CA. Once this would succeed browsers will accept my certificates. I basically managed this by following those two guides:

Big thanks to the respective authors!

Creating a CA

The first step would be to create your own CA. For that part I mostly followed descriptions given in the first link (s. above). Of course you will need openssl installed on your computer. It should come with every Linux distribution and can be installed via its package manager. If your on Windows or MacOSX, I can’t tell for sure. On Windows you can probably find some binaries or simply install WSL. If you’re on MacOSX you can make use of Homebrew.

Let’s generate our CA certificate and its key! First, create a directory which will hold everything. Depending on your security requirements you can execute all steps as root as well. This will create a 4096 bit key called myca-key.pem and a certificate called myca-cert.pem which will be valid for 10 years:

1
2
$ mkdir ~/myca && cd ~/myca
$ openssl req -new -x509 -newkey rsa:4096 -days 3650 -keyout myca-key.pem -out myca-cert.pem

You will be asked a couple of questions, which should be pretty self explaining, s. example here (entering a “.” will leave the field blank):

1
2
3
4
5
6
7
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:<YOUR_NAME>
Email Address []:<YOUR_EMAIL>

You will find the defaults in square brackets. As Common name you can choose something like “My CA” or whatever, but this should not a be domain name. Also, choose a good password for the key (and don’t loose it ;-) )! This password will be required to sign your server certificates. Keep the key in a secure place (again: depending on your security requirements).

The certificate file needs to be imported as new CA into your browser and/or OS. But we’ll get to that later.

Creating a server certificate

As we now have our CA the next step is to generate a server certificate for a NAS drive, local web server, whatever. Again you have to answer the same questions as before when generating the CA certificate, however, this time the Common name should be the hostname of the target system (i.e. your NAS drive).

Something I did not know at first - and which led to some frustration and quite a lot of failed tests - was the fact, that the Common name is not really important anymore and ignored by browsers. What you need is an certificate extension called SAN: Subject Alternative Name. Here you can define all the hostnames the certificate should be valid for. In may case I used the IP address and the hostname, so I can address my SAN drive via both and still have a valid certificate. To create a certificate with SAN extension I mainly followed the second link (s. above).

Server key

Let’s create a 4096 bit key for our server certificate first. It will not have a password:

1
$ openssl genrsa -out myserver_key.pem 4096

Signing request

Next, we’ll create a signing request via:

1
$ openssl req -new -key myserver_key.pem -out myserver_csr.pem

You will have to answer some questions again. Remember, this time the Common Name should be the hostname of your server or device., i.e.:

1
2
3
4
5
6
7
8
9
10
11
12
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:`
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:<SEVERNAME>
Email Address []:<YOUR_EMAIL>

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

This should leave you with the signing request file myserver_csr.pem.

Server certificate

To actually generate the server certificate we need to create a configuration file first, i.e. myserver_san.cnf:

1
2
3
4
5
6
7
8
9
10
11
12
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = <SERVER_IP>
DNS.1 = <SERVER_NAME_1>
DNS.2 = <SERVER_NAME_2>

You can add multiple IPs or hostnames if you want. The certificate will be valid for all of them.

Have your CA key password ready and generate the server certificate:

1
$ openssl x509 -req -in myserver_csr.pem -CA myca-cert.pem -CAkey myca-key.pem -out myserver_cert.pem -CAcreateserial -days 1825 -sha256 -extfile myserver_san.cnf

This will create the server certificate myserver_cert.pem, valid for 5 years (change that by adjusting “-days XXX”).

To check the content of this certificate execute:

1
$ openssl x509 -noout -text -in myserver_cert.pem

Now install the server certificate myserver_cert.pem and the certificate key myserver_key.pem on your device. In case of a Syonolgy NAS drive you can simply upload both files. There might be cases were key and certificate need to be in one file. You can achieve this quite easily by:

1
$ cat myserver_key.pem myserver_cert.pem > myserver_key_and_cert.pem

Importing a CA

The only thing missing now is to make your browser and/or OS aware of the new CA so it will trust the certificate issued for your device(s).

Debian

In case you’re running a Debian based OS execute:

1
2
3
$ sudo mkdir /usr/local/share/ca-certificates/myca
$ sudo cp myca-cert.pem /usr/local/share/ca-certificates/myca/myca-cert.crt
$ sudo update-ca-certificates

Arch Linux

For Arch Linux based distros simply run:

1
$ sudo trust anchor --store /path/to/myca-cert.crt

There is no need to import the CA separately into Firefox or Chrome as described below. It should work right away.

Android

To make use of the new CA in Android, the certificate needs to be converted into DER format:

1
$ openssl x509 -inform PEM -outform DER -in myca-cert.pem -out myca-cert_DER.crt

Copy myca-cert_DER.crt to your Android device, go to Settings -> Security -> Encryption & Credentials -> Install certificate (might differ depending on device/Android version). This should work for Chromium/Chrome browsers and apps.

For Fennec/Firefox go to Settings -> About -> hit the logo at the top a couple of times until debug menu is enabled -> go back -> Secret Settings -> enable “Use third party certificates” (Wow…! s. here)

Desktop Browsers

For Chromium/Chrome got to Settings -> Privacy and Security -> Security -> Manage certificates, go to Authorities tab and click Import. When asked: use this certificate for webpages only. You can list and manage certificates also by certutil (Debian: install libnss3-tools):

1
$ certutil -d sql:${HOME}/.pki/nssdb -L

For Firefox got to Settings -> Privacy and Security -> Certificates -> View Certificates -> Authorities -> Import (again: use this certificate for webpages only)

That should be it. When browsing your devices, like your NAS device, there will be no more security warnings.

This post is licensed under CC BY-SA 4.0 by the author.