A lesson on naming hackathon projects... (among other things)
This guide is based on the excellent guide by robpol86.com. Much of the content has been copied however it shall diverge with my own edits.
This guide is going to involve pulling some template files and scripts from my repository Certificate Authority Jumpstart. I highly recommend cloning it onto your Raspberry Pi before we get started.
This guide will go over setting up an offline root certificate authority for your home network. It is based on what I've learned from jamielinux.com with a few differences:
- We will not be creating an intermediate pair here. Since my intentions are just setting up SSL certs on a handful of internal web interfaces and maybe even WPA2 Enterprise one day, I didn't think it was worth setting this up. It might make revoking certs not as quick, but I don't see myself signing very many certs after my initial run.
- I'll include steps on how to bridge the air gap. For maximum paranoid-tier security we will not be plugging in any USB flash drives (or USB anything excluding keyboards) or network cables. WiFi adaptors are also obviously forbidden. For this we'll be using qrencode.
- I'll be assuming the Linux computer you're using has a GUI (desktop environment). This is to reduce the number of QR codes needed since you'll have more resolution with a GUI than with a frame buffer so you can fit more data in each QR code.
- For additional paranoid-tier security we'll generate a 8192-bit long RSA key for our root CA. 4096-bit keys are fine too but I'm crazy. We'll also be creating 4096-bit SSL keys instead of the usual 2048-bit. While this guide should work fine with any Linux computer I'll be focusing on Debian-based distributions.
The goal here is to setup an offline root CA. It will be online at first to get updates but right before generating the root pair we will remove any network connectivity from the host and never EVER connect it to any networks or USB devices. This will be an offline and air-gapped root CA.
Preparing the Host
This section will go over preparing a newly-installed Debian/Raspbian system. For machines without a real time clock (e.g. Raspberry Pis) we'll setup a script that runs during boot that prompts you for the current time.
- Perform a clean install of Debian (or install the latest Raspbian PIXEL image on the Raspberry Pi) and boot up the host. It's ok to have network access for now. For my Raspberry Pi I followed Raspbian Setup (Raspberry Pi) (you don't need to install any of those packages in that link, just upgrade).
- Upgrade all of your packages since this will be the last time the system will have internet access:
sudo apt update && sudo apt upgrade.
sudo rebootin case a new kernel was installed.
- Finally install these required packages:
sudo apt-get install qrencode acl
Boot Date Prompt on Raspberry Pi
Raspberry Pis don't have real time clocks so they don't keep track of the time when powered off. Usually they handle this by getting the current time from the internet after booting up. However since our root CA will never have internet access again we need to always set the current time every time it boots up.
Since time is very important for signing certificates we'll want to avoid forgetting this. You can install this systemd file to have it prompt you for the current time before the Raspberry Pi finishes booting up, guaranteeing you won't forget:
Copy the OpenSSL Config
Based on a few articles I've found while considering which domain to use at home, I thought I would mention it here even though it's more of a network-related topic rather than an SSL/Certificate topic. I highly encourage you to either purchase a dedicated domain name for your home network or at least use a dedicated subdomain on a domain you already own.
In the table below I'll use
myhome.net as an example.
ORG_NAME is just a name so in this case the value would be "MyHome.net". If you used
home.mycooldomain.com then the
ORG_NAME equivalent may be "Home.MyCoolDomain.com". It can actually be set to anything but this is what I've done for my home network.
The first step is to configure OpenSSL. You'll need to replace some values in the configuration file I'll be providing to you. Refer to the table below for what you'll be replacing.
|To Replace||Replace With||Example|
||Two-letter ISO abbreviation for your country.||US|
||State or province where you live. No abbreviations.||California|
||City where you are located.||San Francisco|
||Name of your organization.||MyHome.net|
||Section of the organization.||Home|
||Your contact email@example.com|
Overwrite all of
/etc/ssl/openssl.cnf with this file (it's still ok to have network access for this part). Be sure to replace
SUB_ strings as otherwise you'll have to enter these values on each certificate request.
OpenSSL Directory Structure
Everything will live in
/root/ca. It will also all be owned by root. Remember this computer is a dedicated CA so it won't be doing anything else at all except hosting your very important root certificate private key and the root certificate itself.
Run the command
sudo bash prepare_root.sh to setup directories and permissions within
setfacl commands set file-system ACLs which enforce default maximum file permissions for new files/directories. A brief description for these directories:
||Certificates are dumped here.|
||Certificate revocation lists.|
||Certificate signing request.|
||Not used in this guide.|
||Private keys. VERY SENSITIVE.|
This is the moment we've all been waiting for! Just one more file and then isolate the host from the world permanently.
Place this file into
chmod +x it. We'll use this script to convert files into QR codes after compressing and encrypting them.
Now remove all USB devices (sans keyboard) and network cables/connections. If this is on a Raspberry Pi either swap it out with a Model A (the one without WiFi or ethernet ports), or fill in the ethernet port with hot glue. Do the same with all but one USB ports. Or just be super duper sure never to plug in things when using this SD card.
Finally Generate the Pair
This is where we actually generate the root key and certificate. The root key is used to sign additional certificate pairs for specific devices/servers, and the root certificate is what you'll export to clients that should trust any of these additional certificates.
Warning: The root key
ca.key.pemyou'll be generating is the most sensitive file on this dedicated computer. Keep it as secure as possible. When
openssl genrsaasks you for a password enter a unique and very secure password. Make sure
setfaclworked and the permissions are:
-r-------- 1 root root 1.8K Aug 15 12:21 private/ca.key.pem
openssl req command will prompt you for some information. The defaults you've specified in
openssl.cnf will be fine. However double check that the Common Name is the fully qualified domain name of this certificate authority.
sudo su - # Become root. cd /root/ca export CN=$(hostname --fqdn) export SAN=DNS:$CN openssl genrsa -aes256 -out private/ca.key.pem 8192 openssl req -key private/ca.key.pem -new -x509 -days 1827 -extensions v3_ca -out certs/ca.cert.pem openssl x509 -noout -text -in certs/ca.cert.pem |more # Confirm everything looks good.
You're done generating your root certificate and private key. You're technically "done". However you'll probably want to do these two steps:
- Install the public root certificate on client computers so they can trust your servers instead of getting SSL errors.
- Creating an SSL certificate to install on your web servers (router admin pages, IPMI interfaces, etc.). For more info see:
Issuing Server Certificates
For the former you'll want to export the
certs/ca.cert.pem file and install it on client computers/devices. For example:
- OS X: The "Keychain Access" app can install that file in the System keychain (not System Roots), an you'll need to manually set the trust to "Always Trust" (you may also have to restart web browsers or just reboot to get rid of SSL errors).
- Fedora/CentOS/RHEL: Copy that file to
/etc/pki/ca-trust/source/anchors/and then run
- Android: In the Wifi settings under "Wifi Preferences" there is button labelled "Install certificates". Pressing this brings up a file explorer from which you can select
ca.cert.pem, you must then give the CA "VPN and apps" credential use. (Note: apps by default do not have to accept user added certificate authorities so some apps may still produce errors e.g. Metamask Mobile)
Instructions for exporting this file is available in the
Bridging the Air Gap section below.
This section will contain additional sub sections with instructions on how to complete some tasks you may repeat for different use cases.
Issuing Server Certificates
This section covers issuing SSL certificates for web servers such as router admin pages. We will generate an SSL certificate and its private key. You'll need to install both files on the web server. Keep in mind the private key is very sensitive and is used to sign SSL sessions to keep it secure as you transfer it to the web server!
When asked for a Common Name you'll need to enter the web server's FQDN. So instead of accessing your router admin page using
http://192.168.0.1you'll instead be using
https://router.myhome.netfor example. Common Name here
On the root CA host place
/root/ca and run these commands. Substitute
router.myhome.net with whatever FQDN your target web server will use.
export CN=server.myhome.net export SAN=DNS:$CN bash sign_cert.sh
If you want to issue a certificate with multiple Subject Alternative Names (e.g. one cert for
sub.server.myhome.net) you can set them in the
SAN environment variable. Below is an example for a certificate valid for the main domain as well as all (single-level) wildcard sub-domains:
export CN=server.myhome.net export SAN=DNS:$CN,DNS:*.$CN
Verify that the Issuer is the root CA and the Subject is the certificate itself. You will need to install both
private/router.myhome.net.key.pem on the web server. Read
Bridging the Air Gap for instructions on how to do this securely.
Bridging the Air Gap
We can use the
airgap script we downloaded earlier to encode files into one or more QR codes to be scanned by your phone and reassembled on another computer. This is a one-way data transfer so your root CA host remains secure and air gapped.
airgapwill print a password at the end of its run. Use this one-time password to decrypt the files on the receiving computer.
For example if you want to just export the
certs/ca.cert.pem file you'll do something like this (you can also specify multiple files for
airgap to encode at once):
pi@raspberrypi:~ $ sudo su - root@raspberrypi:~# cd /root/ca root@raspberrypi:~/ca# airgap certs/ca.cert.pem Compressing, encrypting, and encoding 1 file(s)... certs/ca.cert.pem Done -rw-r--r-- 1 root root 7219 Feb 16 16:28 /tmp/qr-01.png -rw-r--r-- 1 root root 6816 Feb 16 16:28 /tmp/qr-02.png Password: 3SOD8voj8bT root@raspberrypi:~/ca#
Then in the GUI open both of those files and scan them with your phone using a QR scanner app. If you're scanning QR codes with an Android phone using Barcode Scanner you can "Share via email" which gives you the option to share to Dropbox (for some dumb reason) which makes it easy to get encrypted data on your computer.
Once you've scanned the QR codes and saved the large strings of data somewhere on a Linux or OS X computer run these commands to reassemble and decrypt data: