malte70.blog()

mkcert: Vertrauenswürdige SSL-Zerfitikate für Entwickler

Mithilfe von mkcert lassen sich im Handumdrehen vertrauenswürdige SSL-Zertifikate für lokale Hostnamen und sogar IP-Adressen generieren.

Selbst signierte Zertifikate, wie sie in Testumgebungen oft zum Einsatz kommen, sorgen immer für Warnmeldungen, da einem SSL-Zertifikat ohne die Signatur einer vertrauenswürdigen CA niemals vertraut werden kann. Eine eigene lokal verwendete CA muss also her.

Gängige Tools zum Verwalten einer CA wie xca sind für diesen Einsatzzweck absoluter Overkill; außerdem erfordern sie Kenntnisse über SSL-Interna, um z. B. mehr als einen Hostnamen pro Zertifikat zu unterstützen.

mkcert ist das absolute Gegenteil, es gibt nicht einmal eine Konfigurationsdatei. Die CA-Zertifikate können problemlos auf mehreren Computern gleichzeitig zum Erzeugen von SSL-Zertifikaten genutzt werden, sie müssen einfach nur in den Standard-CAROOT-Ordner kopiert werden.

Installation

mkcert kann unter zahlreichen Betriebssystemen über die Paketverwaltung installiert werden, alternativ kann von der GitHub Release-Seite herunter geladen werden.

Um die Zertifikate auch in Browsern mit eigener Liste vertrauenswürdiger CAs zu installieren wird zusätzlich NSS benötigt.

# macOS
brew install mkcert nss

# Debian
sudo apt install mkcert libnss3-tools

# ArchLinux
sudo pacman -S mkcert nss

# Andere Linux-Distributionen:
# Release via GitHub-API abfragen und herunter laden (Python wird zum parsen der Antwort gebraucht)
wget -O mkcert $(wget -q -O- https://api.github.com/repos/FiloSottile/mkcert/releases/latest | python -c 'import json,sys
d = json.load(sys.stdin)
for a in d["assets"]:
  if "linux-amd64" in a["name"]:
    print(a["browser_download_url"])
')
sudo mv mkcert /usr/local/bin

# Windows
winget install FiloSottile.mkcert
Hinweis: Im Folgenden verwende ich nur die Pfade unter unixoiden Systemen, Windows-Nutzer müssen da etwas umdenken 😉

Erste Schritte

mkcert kümmert sich selbstständig um die Generierung der Zertfifikate, ohne dass man openssl-Konfigurationen anlegen muss um irgendwie alternative Hostnamen ins Zertifikat aufzunehmen.

Der Standard-Pfad für die CA kann über die Umgebungsvariable $CAROOT angepasst werden, ansonsten wird ~/.local/share/mkcert verwendet.

# Speicherort für CA anzeigen
mkcert -CAROOT

# SSL-CA erzeugen und direkt im System installieren
mkcert --install

Jetzt kann schon das erste Zertifikat erstellt werden. Dabei ist wie bei certbot der erste genannte Hostname der Name des Zertifikats selbst, und es können beliebig weitere Alternativ-Namen angegeben werden.

Wie zuvor schon erwähnt erlaubt mkcert nicht nur Hostnamen ohne eine Domain, sondern auch IP-Adressen. Server-Zertifikate werden immer im aktuellen Verzeichnis erstellt.

# Ein Verzeichnis für alle Server-Zertifikate
mkdir ~/mkcert-cert
cd ~/mkcert-cert

# Ein generisches Zertifikat für die Entwickler-Workstation erstellen
mkcert deepthought deepthought.local 192.168.1.42 localhost 127.0.0.1 ::1

Das erstellte Zertifikat heißt dann ./deepthought+5.pem, und der private Schlüssel ./deepthought+5-key.pem. („+5“ wegen fünf weiteren alternativen Hostnamen im Zertifikat)

Ein Zertifikat kann aber natürlich auch nur für eine einzelne IP ausgestellt werden, für einen Router zum Beispiel:

mkcert 192.168.1.1

rootCA-Zertifikat verteilen

Die CA auf weiteren Computern einrichten

mkcert kann sich auch darum kümmern, das CA-Zertifikat auf anderen Computern im System zu verankern.

Nach der Installation muss noch vor dem ersten Aufruf von mkcert das CAROOT-Verzeichnis manuell erstellt werden, damit keine zweite CA erstellt wird:

mkdir -p ~/.local/share/mkcert
scp \
	deepthought.local:.local/share/mkcert/rootCA.pem \
	~/.local/share/mkcert/

# Falls mkcert auf diesem Rechner auch Zertifikate erstellen solll,
# muss auch der Private Key kopiert werden:
scp \
	deepthought.local:.local/share/mkcert/rootCA-key.pem \
	~/.local/share/mkcert/

Jetzt kann die rootCA durch mkcert im System bekannt gemacht werden:

mkcert -install

Smartphones/Tablets

Um das Zertifikat auf Smartphones zu installieren, muss es im Browser von einem Webserver geladen werden.

Falls kein lokaler Webserver vorhanden ist, lässt sich mit Python ein einfacher Webserver starten:

mkdir ~/mkcert-web
cd ~/mkcert-web
cp $(mkcert -CAROOT)/rootCA.pem .

python -m http.server
# Nach dem Download mit Ctrl+C beenden

cd -
rm $OLDPWD/rootCA.pem
rmdir $OLDPWD

SSL-Zertifikat für OpenWRT

Um via HTTPS auf die Weboberfläche (LuCi) eines OpenWRT-Routers zugreifen zu können, muss zunächst mit mkcert ein neues Zertifikat für den Hostnamen oder die IP ausgestellt werden:

cd ~/mkcert-cert
mkcert openwrt 192.168.1.1

Jetzt folgt der schwierige Teil: Die Zertifikate auf den Router kopieren. OpenWRT unterstützt von Haus aus nämlich kein SCP oder SFTP.

Entweder greift man wieder zum Webserver, trotzdem diesmal ein privater Schlüssel dabei ist. Aber da die Zertifikate Textdateien sind, reicht ein ein echo mit Ausgabeumleitung; der Key wird einfach mit Copy und Paste in den Befehl eingefügt:

pbcopy < ~/mkcert-cert/openwrt+1.pem

ssh openwrt

echo ' ← jetzt mit Ctrl+Shift+V oder Cmd+V einfügen
-----END CERTIFICATE-----
' > /etc/ssl/mkcert-openwrt.crt

Das Gleiche für den privaten Schlüssel wiederholen, nur stattdessen in /etc/ssl/mkcert-openwrt.key schreiben. Jetzt muss nur noch das uhttpd konfiguriert und neu gestartet werden:

vi /etc/config/uhttpd
# […]
config uhttpd 'main'
	# […]
	option cert '/etc/ssl/mkcert-openwrt.crt'
	option key '/etc/ssl/mkcert-openwrt.key'
	# […]
/etc/init.d/uhttpd restart

Fertig!