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 adapters 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.

While this guide should work fine with any Linux computer I’ll be focusing on Debian-based distributions. This guide has
been tested on Debian Jessie on an old T60 Thinkpad and 2017-01-11-raspbian-jessie.zip on a Raspberry Pi.

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.

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).

If you’re using Debian be sure to create an encrypted LVM or partition.

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:

# Prompt for current date during boot.## https://github.com/Robpol86/robpol86.com/blob/master/docs/_static/date-prompt.service## Stops the system from booting up to 2 minutes or until user enters the# current time in the console. Useful for Raspberry Pis and other systems# with no real time clocks.## Save as: /etc/systemd/system/date-prompt.service# Enable with: systemctl enable date-prompt.service[Unit]After=fake-hwclock.serviceAfter=systemd-fsck-root.service [email protected]Before=sysinit.target plymouth-start.serviceDefaultDependencies=noDescription=Prompt for current date during boot[Service]Environment="P=Enter the current date (e.g. Feb 11 5:17 PM): "ExecStartPre=-/bin/plymouth deactivateExecStart=/bin/bash -c 'until read -ep "$P" R; [ ! -z "$R" ] && date -s "$R"; do :; done'ExecStartPost=-/bin/plymouth reactivateExecStopPost=-/bin/plymouth reactivateRemainAfterExit=yesStandardError=inheritStandardInput=ttyStandardOutput=inheritTimeoutSec=120Type=oneshot[Install]WantedBy=sysinit.target

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.

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.

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.

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.pem you’ll be generating is the most sensitive file on this dedicated computer. Keep it as
secure as possible. When opensslgenrsa asks you for a password enter a unique and very secure password. Make
sure setfacl worked and the permissions are: -r--------1rootroot1.8KAug1512:21private/ca.key.pem

Note

The opensslreq 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.

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” (ou 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 sudoupdate-ca-trust.

We can use the airgap script we copied 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.

Note

airgap will 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):

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.

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!

Note

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.1 you’ll instead be using https://router.myhome.net for example. Common Name here
will be router.myhome.net.

On the root CA host run these commands. Substitute router.myhome.net with whatever FQDN your target web server
will use.

If you want to issue a certificate with multiple Subject Alternative Names (e.g. one cert for server.myhome.net
and 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:

exportCN=server.myhome.net
exportSAN=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
certs/router.myhome.net.cert.pem and private/router.myhome.net.key.pem on the web server. Read
Bridging the Air Gap for instructions on how to do this securely.

Java seems to have its own certificate store separate from the Operating System’s. So in the case of IPMI you’ll have a
valid HTTPS connection to the web interface but when trying to open the Console Redirection you’ll get certificate
warnings.

To fix this you’ll need to add the host’s (not root) certificate to Java’s certificate store. On OS X:

Open System Preferences. Click on the Java icon at the bottom.

In the new window click on the Security tab and then the Manage Certificates button at the bottom.

Set certificate type to Secure Site CA.

Click Import, set File Format to All Files, and import router.myhome.net.cert.pem.