Ubuntu Server 14.04 – SAN-Zertifikate erstellen

Stellt man mit einer eigenen Certificate Authority („CA“) mit OpenSSL ein Serverzertifikat aus, so gilt dieses standardmäßig nur für die im Common Name („CN“) des Zertifikats angegebene Domain. Bei einem Server mit mehreren vollqualifizierten Domainnamen („Fully Qualified Domain Name“, „FQDN“) wie www.test.local, mail.test.local usw., muss daher für jeden FQDN eine eigenes Zertifikat erzeugt werden.

Man kann sich die Zertifikatserstellung erleichtern, indem man die Erweiterung Subject Alternative Name („SAN“) des in RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile der Internet Engineering Task Force IETF spezifizierten Standards X.509 nutzt. Damit können in nur einem SAN-Zertifikat alle Domains aufgelistet werden, für die das Zertifikat gültig sein soll. Neben Domainnamen sind hier u. a. auch Einträge für IP-Adressen und E-Mail-Adressen möglich.

Die alternativ einsetzbaren Wildcard-Zertifikate sind nicht so flexibel, da sie nur eine Ebene einer einzigen Domain umfassen. Ein Zertifikat für *.test.local schützt z. B. die FQDN www.test.local und mail.test.local, nicht aber test.local und www.de.test.local oder ftp.dummy.private. Vorteilhaft gegenüber SAN-Zertifikaten ist, dass ein Wildcard-Zertifikat nicht bei jeder Änderung der Domainliste neu ausgestellt werden muss.

Die folgende Anleitung zum Anlegen von SAN-Zertifikaten mit OpenSSL ist eine Ergänzung zum Beitrag Ubuntu Server 14.04 – Certificate Authority mit OpenSSL einrichten.

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

OpenSSL-Konfiguration anpassen

Um mit OpenSSL SAN-Zertifikate ausstellen zu können, ist eine modifizierte Version der Konfigurationsdatei /etc/ssl/openssl.cnf erforderlich. Neben einigen globalen Anweisungen nach dem Schema Name = Wert am Anfang enthält diese Datei im Wesentlichen Konfigurationabschnitte mit Überschriften in der Form [ Abschnitt ], unter denen mehrere Anweisungen zusammengefasst sind.

Als Grundlage erstellen wir zunächst mit

root@server:~# cp /etc/ssl/openssl.cnf /etc/ssl/openssl-san.cnf

eine Kopie der Konfigurationsdatei und ergänzen openssl-san.cnf dann wie folgt:

...
[ req ]
...
# req_extensions = v3_req # The extensions to add to a certificate request
req_extensions = v3_req # The extensions to add to a certificate request
...
[ v3_req ]
...
subjectAltName = @alt_names
...
[ alt_names ]
DNS.1 = test.local
DNS.2 = www.test.local
DNS.3 = mail.test.local

Damit der Inhalt des Abschnitts [ v3_req ] mit Zertifikats-Erweiterungen bei einer Zertifikatsanfrage berücksichtigt wird, entfernen wir das Kommentarzeichen # vor der Anweisung req_extensions = v3_req im Konfigurationabschnitt [ req ]. In [ v3_req ] fügen wir einen zusätzlichen Eintrag subjectAltName für die Domainnamen ein, für die das SAN-Zertifikat gelten soll. Statt die Domains in einer durch Komma getrennten Aufzählung anzugeben, werden sie der Übersichtlichkeit halber in einem eigenen neuen Konfigurationabschnitt [ alt_names ] aufgelistet, auf den wir mit @alt_names verweisen. Pro Domain tragen wir hier eine Zeile mit dem Aufbau DNS.x = FQDN mit x als fortlaufender Nummerierung ein. Ein im Common Name aufgeführter Domainname wird bei einem vorhandenen subjectAltName-Eintrag ignoriert und muss daher bei Bedarf ebenfalls in der Liste angegeben werden.

Subject Alternative Names und weitere Zertifikats-Erweiterungen von OpenSSL werden in x509v3_config detaillierter beschrieben.

Serverzertifikat erstellen

Die folgenden Ausführungen basieren auf dem Artikel Ubuntu Server 14.04 – Certificate Authority mit OpenSSL einrichten und beschreiben das Vorgehen in komprimierter Form. Vorausgesetzt wird, dass ein Root-Zertifikat / CA-Zertifikat /etc/ssl/certs/ca_test.local.pem mit dem privaten Schlüssel /etc/ssl/private/ca_test.local.key einer eigenen Certificate Authority existiert, mit dem wir selbst signierte Zertikate generieren können.

Wir erstellen unser SAN-Serverzertifikat in drei Schritten.

Zunächst legen wir einen privaten Schlüssel server.test.local.key ohne Verschlüsselung durch eine Passphrase an:

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

Mit diesem Schlüssel generieren wir dann eine Zertifikatsanfrage server.test.local.csr:

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

Mit der Option -config /etc/ssl/openssl-san.cnf nutzt OpenSSL hierbei die geänderte Konfigurationsdatei.

Abschließend erzeugen wir mit der Zertifikatsanfrage das Serverzertifikat server.test.local.pem:

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

Die Option -extfile verweist auf die Datei mit den Zertifikats-Erweiterungen, in unserem Fall /etc/ssl/openssl-san.cnf. Mit der Option -extensions legen wir den in dieser Datei zu nutzenden Abschnitt mit Erweiterungen fest, hier v3_req.

Die Ausgabe des Serverzertifikats mit

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

sollte nun die Liste mit den Domainnamen enthalten:

...
X509v3 Subject Alternative Name: 
    DNS:test.local, DNS:www.test.local, DNS:mail.test.local
...

Wenn unser SAN-Zertifikat wie gewünscht aussieht, können wir die nicht mehr benötigte Zertifikatsanfrage löschen:

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

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: ***