Ubuntu Server 14.04 – Certificate Authority mit OpenSSL einrichten

Um Anwendungen mit SSL („Secure Sockets Layer“) bzw. TLS („Transport Layer Security“) zu verschlüsseln, werden digitale Zertifikate benötigt. Diese werden von einer Zertifizierungsstelle („Certificate Authority“, „CA“) ausgegeben, die die Korrektheit der Zertifikatsdaten durch eine Signierung mit ihrem eigenen privaten Schlüssel sicherstellt. Client-Anwendungen wie Webbrowser oder Mail-Programme können die Gültigkeit der ihnen von Server-Anwendungen wie Webservern oder Mailservern vorgelegten Zertifikate mit dem zugehörigen öffentlichen Schlüssel der Certificate Authority prüfen. Die Zertifikate sind hierbei ausgehend von einem sog. „Root“-Zertifikat in einer Zertifikatskette hierarchisch aufgebaut. Falls eine Anwendung das Root-Zertifikat als vertrauenswürdig einstuft, akzeptiert sie auch alle anderen von der Certificate Authority signierten Zertifikate.
Digitale Zertifikate kommerzieller Anbieter sind in der Regel kostenpflichtig und z. B. für den Einsatz in einem lokalen Netzwerk oft nicht erforderlich. Hier können wir stattdessen mit dem Programmpaket OpenSSL eine eigene kostenlose Certificate Authority einrichten und selbst signierte Zertikate („Self-signed Certificates“) erstellen. Zur sicheren Kommunikation müssen wir in den Anwendungen dann nur noch unser Root-Zertifikat integrieren.
Üblicherweise besteht eine Zertifikatskette aus einem Root-Zertifikat, einem Zwischenzertifikat und einem Serverzertifikat für die eigentliche Anwendung. Da mit einer eigenen Certificate Authority in der Regel nur eine überschaubare Anzahl von Serverzertifikaten ausgestellt wird, werden wir nachfolgend auf das Erzeugen eines Zwischenzertifikats verzichten.

Voraussetzungen

Wir haben unseren Server z. B. gemäß der Anleitung zur Basisinstallation für Ubuntu Server 14.04 installiert und durch Updates / Upgrades auf den neuesten Stand gebracht. Der Server hat den Rechnernamen server und gehört zur Domain test.local. Es existiert ein Benutzer theo, der Mitglied der Gruppe sudo ist und somit über Administratorrechte verfügt. Die Befehle führen wir mit Root-Rechten aus, z. B. nach Öffnen einer Rootshell mit sudo -i.
OpenSSL gehört zum Installationsumfang von Ubuntu Server 14.04 und sollte daher bereits auf unserem Server vorhanden sein. Falls nicht, können wir es wie folgt nachinstallieren:

root@server:~# apt install openssl

Root-Zertifikat für eigene Certification Authority anlegen

Privaten Schlüssel generieren

Für unser Root-Zertifikat und auch die Serverzertifikate benötigen wir einen privaten Schlüssel, den wir mit der Anweisung openssl genrsa erzeugen:

root@server:~# openssl genrsa -aes256 -out /etc/ssl/private/ca_test.local.key 4096
Enter pass phrase for /etc/ssl/private/ca_test.local.key: ***
Verifying - Enter pass phrase for /etc/ssl/private/ca_test.local.key: ***

Hiermit erhalten wir einen RSA(„Rivest, Shamir, Adleman“)-Schlüssel ca_test.local.key mit einer Länge von 4096 bit. Die Schlüssellänge liegt damit über dem in den technischen Richtlinien TR-02102 des BSI empfohlenen Wert von 2000 bzw. 3000 bit.
Der private Schlüssel ist durch eine Passphrase mit dem AES(„Advanced Encryption Standard“)-Verfahren mit 256 bit verschlüsselt. Zur Speicherung nutzen wir das Schlüsselverzeichnis /etc/ssl/private, das bereits bei der Installation von OpenSSL angelegt wurde. Bei erhöhten Sicherheitsanforderungen kann man die Schlüsseldatei stattdessen auch auf einem externen Datenträger wie einem USB-Stick ablegen, den man gut verschlossen lagert und nur bei Bedarf an den Server anschließt.

Root-Zertifikat erzeugen

Mit dem privaten Schlüssel können wir nun mit dem Befehl openssl req ein neues Root-Zertifikat / CA-Zertifikat ca_test.local.crt mit einer Gültigkeitsdauer von 3650 Tagen, also ca. 10 Jahren erstellen:

root@server:~# openssl req -days 3650 -extensions v3_ca -key /etc/ssl/private/ca_test.local.key -new -out /usr/share/ca-certificates/ca_test.local.crt -sha512 -subj "/CN=Test CA/O=Theo Test" -x509
Enter pass phrase for /etc/ssl/private/ca_test.local.key: ***

Als Speicherort wählen wir das Verzeichnis /usr/share/ca-certificates, in dem sich auch die zusammen mit OpenSSL installierten offiziellen CA-Zertifikate befinden.
Zur Gewährleistung der Integrität unserer Zertifikats nutzen wir als Hashfunktion SHA(„Secure Hash Algorithm“)-2 mit 512 bit. Die unsicherere Funktion SHA-1 sollte man nach den Empfehlungen des NIST („National Institute of Standards and Technology“) nicht mehr verwenden. Der aktuell sicherste Algorithmus SHA-3 wird von OpenSSL derzeit noch nicht unterstützt.
Um die normalerweise zu beantwortenden Detailfragen zum Zertifikatsinhaber zu umgehen, werden die einzelnen Antworten durch / getrennt als sogenannter „Distinguished Name“ (DN) der Option -subj übergeben. Der Distinguished Name wird zur eindeutigen Identifizierung eines Zertifikats genutzt. Wir geben hier nur den einzigen Pflichteintrag „Common Name“ (CN) für den Zertifikatsnamen und den „Organization Name“ (O) für den Namen des Zertifikatausstellers an. Weitere optionale Angaben sind:

  • /C=: Country Name
  • /ST=: State or Province Name
  • /L=: Locality Name
  • /OU=: Organizational Unit Name

In diversen Anleitungen wird beim obigen Aufruf von openssl req als weitere Option -nodes („no DES“) angegeben. Gemäß dem OpenSSL-Handbuch ist dies aber wohl nicht notwendig, da wir keinen privaten Schlüssel erzeugen:

-nodes
if this option is specified then if a private key is created it will not be encrypted.

Zertifikatsliste ergänzen

Mit dem folgenden Befehl aktualisieren wir die Liste aller CA-Zertifikate, die im Verzeichnis /usr/share/ca-certificates enthalten sind:

root@server:~# dpkg-reconfigure ca-certificates

Die Nachfrage, ob wir neuen Zertifikaten von Zertifizierungsstellen vertrauen möchten, beantworten wir mit Fragen. In der nun erscheinenden Auflistung wählen wir unser Root-Zertifikat ca_test.local.crt aus und bestätigen die Auswahl mit Ok. Hiermit wird das Zertifikat an die Datei ca-certificates.crt im Zertifikatsverzeichnis /etc/ssl/certs angehängt, die Konfiguration in /etc/ca-certificates.conf aktualisiert und in /etc/ssl/certs ein symbolischer Link ca_test.local.pem erzeugt.

Root-Zertifikat überprüfen

Zum Testen lassen wir uns das Root-Zertifikat abschließend mit openssl x509 ausgeben:

root@server:~# openssl x509 -in /etc/ssl/certs/ca_test.local.pem -noout -text

Client-Installation vorbereiten

Als Vorbereitung für die Installation auf den Client-Rechnern kopieren wir das Zertifikat in ein Heimat-Verzeichnis eines Serverbenutzers, auf das wir extern zugreifen können, in unserem Beispiel theo:

root@server:~# cp /usr/share/ca-certificates/ca_test.local.crt /home/theo

Nun können wir per FTP oder Fernzugriff mit SCP („Secure Copy“) die Datei ca_test.local.crt auf den Client übertragen.

Root-Zertifikat auf Client hinterlegen

Damit Anwendungen auf den Client-Rechnern die von unserer Certificate Authority erstellten Serverzertifikate akzeptieren, müssen wir das Root-Zertifikat im jeweiligen Programm hinterlegen. Wir werden im Folgenden die Vorgehensweise exemplarisch für Windows beschreiben.
Vorausgesetzt, wir haben den Fernzugriff entprechend Ubuntu Server 14.04 – Fernzugriff einrichten konfiguriert, können wir als Benutzer hans die Zertifikatsdatei mit dem SCP-Programm PSCP herunterladen:

C:\Windows\System32>c:\users\hans\pscp -i c:\users\hans\id_rsa.ppk -P 42022 theo@server.test.local:ca_test.local.crt c:\users\hans\ca_test.local.crt

Unter Windows (ab Version 98) werden Informationen über Zertifikate in der Zertifikatsverwaltung gespeichert, die wir in der Eingabeaufforderung wie folgt starten:

C:\Windows\system32>certmgr.msc

Im Ordner Vertrauenswürdige Stammzertifizierungsstellen erreichen wir nach einem Rechtsklick auf den Unterordner Zertifikate unter Alle AufgabenImportieren… den Zertifikatimport-Assistenten und können die einzelnen Importschritte ausführen. Unser hinterlegtes Root-Zertifikat wird nun u. a. in den Webbrowsern Chrome und Internet Explorer sowie in Outlook berücksichtigt.
Andere Anwendungen wie der Webbrowser Firefox oder der E-Mail-Client Thunderbird verwalten die Zertifikate eigenständig. Bei der Version 41 von Firefox installieren wir das Root-Zertifikat beispielsweise unter EinstellungenErweitertZertifikate anzeigenZertifizierungsstellenImportieren….

Serverzertifikat erstellen

Ein selbst signiertes Serverzertifikat erzeugen wir in drei Schritten. Die einzelnen Schritte beschreiben wir nachfolgend am Beispiel eine Zertikats für www.test.local.

Privaten Schlüssel anlegen

Zuerst generieren wir analog zum Vorgehen beim Root-Zertifikat einen privaten Schlüssel www.test.local.key:

root@server:~# openssl genrsa -out /etc/ssl/private/www.test.local.key 4096

Wir verzichten hierbei auf die Verschlüsselung mit einer Passphrase, da wir ansonsten bei jedem Start der Server-Anwendung ein Passwort eingeben müssten.

Zertifikatsanfrage generieren

Im zweiten Schritt erzeugen wir eine Zertifikatsanfrage („Certificate Signing Request“, „CSR“) www.test.local.csr. Die Anweisung hierfür sieht ähnlich wie der Befehl zum Anlegen des Root-Zertifikats aus. Die Optionen -days, -extensions und -x509 geben wir allerdings nicht mit an:

root@server:~# openssl req -key /etc/ssl/private/www.test.local.key -new -out /etc/ssl/private/www.test.local.csr -sha512 -subj "/CN=www.test.local/O=Theo Test"

Bei einem Serverzertifikat muss der Common Name CN exakt mit dem vollqualifizierten Domainnamen FQDN („Fully Qualified Domain Name“) des Servers übereinstimmen. Eine Client-Anwendung würde das Zertifikat z. B. für den Server ftp.test.local nicht akzeptieren, selbst wenn er unter derselben IP-Adresse wie www.test.local erreichbar wäre. Die Angabe mehrerer Domains ist mit SAN(„Subject Alternative Name“)-Zertifikaten möglich, auf die wir in dem gesonderten Beitrag Ubuntu Server 14.04 – SAN-Zertifikate erstellen näher eingehen.

Serverzertifikat erzeugen

Mit der Zertifikatsanfrage erhalten wir schließlich mittels openssl x509 das Serverzertifikat www.test.local.pem im Zertifikatsverzeichnis /etc/ssl/certs:

root@server:~# openssl x509 -CA /etc/ssl/certs/ca_test.local.pem -CAcreateserial -CAkey /etc/ssl/private/ca_test.local.key -days 3650 -in /etc/ssl/private/www.test.local.csr -out /etc/ssl/certs/www.test.local.pem -req -sha512
...
Enter pass phrase for /etc/ssl/private/ca_test.local.key: ***

Beim Ausstellen eines Zertifikats durch unsere Certificate Authority wird eine Seriennummer verwendet, die bei jeder Nutzung um 1 erhöht wird und in einer Datei gespeichert wird. Mit der Option -CAcreateserial legen wir fest, dass die Seriennummern-Datei mit einer Zufallszahl angelegt wird, falls sie noch nicht existiert. Der Dateiname wird dabei aus dem Namen der Root-Zertifikats-Datei ohne Dateiendung und der Endung .srl gebildet. In unserem Fall lautet er mit vollständiger Pfadangabe also /etc/ssl/certs/ca_test.local.srl.
Die Zertifikatsanfrage wird nun nicht mehr benötigt und kann gelöscht werden:

root@server:~# rm /etc/ssl/private/www.test.local.csr

Abschließend kontrollieren wir noch unser Serverzertifikat:

root@server:~# openssl x509 -in /etc/ssl/certs/www.test.local.pem -noout -text

Serverzertifikats-Skript

Muss man mehr als ein oder zwei Serverzertifikate erzeugen, lohnt sich die Anlage eines Shellskripts, hier genservcert.sh:

root@server:~# touch /root/genservcert.sh
root@server:~# chmod 0700 /root/genservcert.sh

Ein einfaches Skript, das die oben beschriebenen Schritte zusammenfasst, kann wie folgt aussehen:

#!/bin/bash
# genservcert.sh
private="/etc/ssl/private"
certs="/etc/ssl/certs"
openssl genrsa -out $private/$1.key 4096
openssl req -key $private/$1.key -new -out $private/$1.csr -sha512 -subj "/CN=$1/O=$2"
openssl x509 -CA $certs/$3.pem -CAcreateserial -CAkey $private/$3.key -days 3650 -in $private/$1.csr -out $certs/$1.pem -req -sha512
rm $private/$1.csr
openssl x509 -in $certs/$1.pem -noout -text

Ein Aufruf für den Server mail.test.local lautet dann beispielsweise:

root@server:~# /root/genservcert.sh mail.test.local "Theo Test" ca_test.local
...
Enter pass phrase for /etc/ssl/private/ca_test.local.key: ***