Vorwort
Nachdem Mozilla starke Kritik an Wosign und Startcom geübt hat, entfernte nun Apple als erstes die Zertifizierungsstelle aus seinen Trust-Stores. Für den Otto-Normal-Verbraucher heißt das nun, dass die Zertifikate von StartCom und Wosign faktisch wertlos sind; es ist ungewiss, ob sich die CA davon wieder erholt, auch wenn die Maßnahme vorerst auf ein Jahr begrenzt ist, und sich WoSign dann erneut einer unabhängigen Überprüfung unterziehen lassen kann.
Damit bleibt Let’s Encrypt die letzte mir bekannte Möglichkeit, kostenlos SSL-Zertifikate zu nutzen. Und bei aller berechtigten Kritik an dem Vorgehen, Zertifikte nur für 90 Tage auszustellen und diese mit einem Client automatisiert erneuern zu lassen, ist das Verfahren zumindest transparent und quelloffen.
Wem der native Python-Client nicht zusagt, der kann aus einer Vielfalt von alternativen Clients wählen. Ich habe mich für getssl entschieden, und möchte hier kurz eine Einführung geben.
Installation
Getssl ist ein simples Bash-Skript – daher kann auch ein unerfahrener Entwickler in den Code schauen und nachvollziehen, was dort eigentlich passiert. Installiert wird das Skript folgendermaßen:
curl --silent https://raw.githubusercontent.com/srvrco/getssl/master/getssl > /usr/local/sbin/getssl
chmod 700 /usr/local/sbin/getssl
Anschließend kann man das Skript mit -h aufrufen, um sich verfügbare Parameter ausgeben zu lassen:
$ getssl -h
getssl ver. 1.61
Obtain SSL certificates from the letsencrypt.org ACME server
Usage: getssl [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-Q|--mute] [-u|--upgrade] [-U|--nocheck] [-w working_dir] domain
Options:
-h, --help Display this help message and exit
-d, --debug Outputs debug information
-c, --create Create default config files
-f, --force Force renewal of cert (overrides expiry checks)
-a, --all Check all certificates
-q, --quiet Quiet mode (only outputs on error, success of new cert, or getssl was upgraded)
-Q, --mute Like -q, but mutes notification about successful upgrade
-u, --upgrade Upgrade getssl if a more recent version is available
-U, --nocheck Do not check if a more recent version is available
-w working_dir Working directory
Konfiguration
Nun kann man die erste Konfiguration für eine Domain anlegen. Für example.org würde der Aufruf so aussehen:
getssl -c example.org
Wenn das der erste Aufruf des Skripts überhaupt ist, wird automatisch das Verzeichnis ~/.getssl angelegt. Darin befindet sich die globale getssl.cfg (die ebenfalls beim ersten Lauf angelegt wird), sowie ein Konfigurationsverzeichnis für jede Domain.
Globale Konfiguration
Hier eine Übersicht über die Konfigurationsvariablen:
Variable | Bedeutung |
---|---|
CA | Let’s Encrypt bietet zwei unterschiedliche APIs. Einmal das Staging-API, welches für Tests vorgesehen ist, und das Live-API, welches die echten Let’s Encrypt Zertifikate ausstellt. Der Unterschied ist, dass das Staging-API keine vertrauenswürdigen Zertifikate erstellt. Dafür gibts dort aber keine Rate-Limits, wie im Live-API. Zum Testen sollte man also unbedingt das Staging-Environment nutzen. Mehr Informationen dazu gibt es hier. Per Default wird das Staging-API verwendet, was auch sinnvoll ist, da man am anfang sicherlich noch den ein oder anderen Fehler machen wird. Ich persönlich habe das nach wie vor das Staging-API global aktiviert, und überschreibe diese Einstellung erst in den Domain-Konfigurationen. Dann hat man nicht das Problem, dass wenn eine neue Domain dazu kommt, man gleich beim Test das Live-API verwendet. |
AGREEMENT | Hier ist der Link zur Lizenzvereinbarung hinterlegt. Mit dem Nutzen von Let’s Encrypt stimmt man dieser zu – man sollte Sie daher zumindest mal überflogen haben. |
ACCOUNT_EMAIL | Die Email-Adresse für den Let’s Encrypt Account. |
ACCOUNT_KEY_LENGTH | Die Länge des zu generierenden Account-Keys. Dieser wird zur Authentifizierung verwendet. |
ACCOUNT_KEY | Speicherort des Account-Keys. |
PRIVATE_KEY_ALG | Algorithmus für den privaten Key. Aktuell kann man dort rsa oder prime256v1 nutzen. |
RELOAD_CMD | Hier kann ein Befehl definiert werden, der einen bestimmten Dienst (Apache2, nginx, …) automatisch neu startet, wenn ein Zertifikat erneuert wurde. |
RENEW_ALLOW | Dieser Wert legt fest, wie viele Tage vor Ablauf ein Zertifikat frühestens erneuert werden darf. Ein Zertifikat bei Let’s Encrypt hat eine Laufzeit von 90 Tagen. RENEW_ALLOW steht standardmäßig auf 30, das heißt frühestens 30 Tage vor Ablauf würde das Zertifikat neu ausgestellt. Wenn man getssl täglich als Cronjob laufen lässt kann man diesen Wert auch noch etwas verringern. |
SERVER_TYPE | Der Server-Typ ist ausschließlich für getssl selbst interessant und hat nichts mit Let’s Encrypt oder dem Zertifikat an sich zu tun. Es definiert den Weg, über den geprüft wird, ob und wie lange das entsprechende Zertifikat noch gültig ist. Ist hier also smtp definiert, wird getssl das Zertifikat von |
CHECK_REMOTE | Kann „true“ oder „false“ annehmen. Der Wert definiert, ob das Zertifikat überprüft werden soll. |
SSLCONF | Hier kann eine eigene OpenSSL-Konfiguration mitgegeben werden. |
VALIDATE_VIA_DNS | Prinzipiell kann Let’s Encrypt auf zwei Wegen eine Domain-Validierung durchführen: Via DNS oder via einer HTTP-Ressource (mehr Infos). Auch getssl unterstützt beide Wege. Möchte man das DNS-Verfahren nutzen, muss hier „true“ eingetragen werden. |
DNS_ADD_COMMAND | Diese Direktive beinhaltet den Befehl zum setzen von DNS-Einträgen, beispielsweise nsupdate. |
DNS_DEL_COMMAND | Kommando, um den DNS-Eintrag wieder zu löschen |
AUTH_DNS_SERVER | Definiert den authoritativen Nameserver |
DNS_WAIT | Zeit in Sekunden, die gewartet wird, bis der DNS-Eintrag erfolgreich gesetzt wurde |
DNS_EXTRA_WAIT | Nachdem das Skript selbst erfolgreich geprüft hat, dass der DNS-Eintrag korrekt war, sendet es die Informationen an den ACME-Server, der die Verifikation seinerseits durchführt. Mit der Option DNS_EXTRA_WAIT kann man noch eine Wartezeit einbauen, zwischen der skripteigenen Verifikation und dem Senden der Infos an den ACME-Server. Für die meisten Leute sollte die Standardeinstellung zureichend sein. |
Domain Konfiguration
Wie gesagt, existiert für jede angelegte Domain ein Verzeichnis unterhalb von ~/.getssl. Darin befindet sich eine weitere getssl.cfg, in welcher Einstellungen der globalen Konfiguration überschrieben werden können, und weitere Einstellungen getätigt werden müssen. In der Liste gehe ich nur auf Variablen ein, die nicht in der globalen Konfiguration auftauchen.
| SANS | Hier kann man SubjectAlternativeNames definieren. Es ist zu beachten, dass Let’s Encrypt für jeden Namen eine separate Prüfung verlangt. Man braucht also für alle Namen administrative Rechte. Wildcard-Einträge sind bei Let’s Encrypt nicht möglich. ACL Dieser Eintrag ist ein Bash-Array mit Pfaden, an denen das Challenge-File angelegt werden soll. Der erste Eintrag gilt für den eigentlichen Domainname. Wenn es SANS gibt, muss für jeden Name ein Pfad hinzugefügt werden (Reihenfolge entscheidet!). Let’s Encrypt prüft dieses Challenge indem es die Ressource per HTTP(S) abruft: http(s)://
Hat das Zertifikat keine weiteren Namen, enthält ACL logischerweise nur einen Eintrag.
Wenn nicht der lokale Webserver für die Domain zuständig ist, kann man das Challenge auch per SSH oder FTP auf einen entfernten Server schaffen lassen. Die Syntax dazu findet man in der Beispielkonfiguration.
Variable | Bedeutung |
---|---|
USE_SINGLE_ACL | Wenn der lokale Webserver für alle Domains innerhalb des Zertifikats zuständig ist, kann man sich es auch einfach machen und für alle Zertifikate den gleichen ACL-Pfad nutzen. Im Apache kann man beispielsweise einen Alias definieren, der VHost-unabhängig einen bestimmten URL an einen definierten Ort umleitet. |
DOMAIN_CERT_LOCATION, DOMAIN_KEY_LOCATION, CA_CERT_LOCATION, DOMAIN_CHAIN_LOCATION, DOMAIN_KEY_CERT_LOCATION DOMAIN_PEM_LOCATION | Diese Direktiven geben an, wohin die entsprechenden Bestandteile kopiert werden sollen. Auch hier ist es wieder möglich, einen entfernten Ort per SSH oder FTP anzugeben. Wenn die Variablen nicht gesetzt sind, wird nichts kopiert. Dann existieren nur die lokalen Files in ~/.getssl/ |
Nachdem man sowohl die globale als auch die domain-spezifische Konfiguration erstellt und angepasst hat, kann man das Zertifikat ausstellen lassen:
getssl -f <domain>
Der Parameter -f forciert dabei das Erstellen des Zertifikats, unabhängig davon, ob das aktuelle Zertifikat noch gültig ist oder nicht. Wenn es einen Fehler gibt, kann man auch noch -d angeben. Dann läuft getssl im Debug-Modus und ist gesprächiger. Wenn die Ausstellung dann geklappt hat, kann man die Domain auf das Live-API umstellen.
Um getssl periodisch laufen zu lassen kann man einen Cronjob einrichten:
# Zertfikate erneuern
0 3 * * * root getssl -q -a
Der Parameter -a bewirkt, dass alle Zertifikate überprüft werden, -q heißt, dass getssl keine unnötigen Ausgaben produziert. Der Entwickler empfiehlt noch die Option -u mit anzugeben, welche das Skript selbstständig updated. Das ist natürlich nicht unbedenklich, bedenkt man, was passieren könnte, wenn der Github-Account des Entwicklers kompromittiert würde, und das Update statt einer neuen Version einen Schadcode herunterladen würde. Aber nicht nur das wäre ein Problem, sondern auch eine Änderung im Verhalten des Skripts wäre möglich. Im schlimmsten Fall kriegt man das erst mit, wenn ein Zertifikat abgelaufen ist. Ob man die Auto-Update-Funktionalität also nutzen will, hängt von einem selbst ab.
Fazit
getssl ist eine schöne und saubere Möglichkeit Let’s Encrypt auf dem eigenen Server auszurollen. Auch der Entwickler ist sehr nett und kompetent, und hat mir bei meinen 2 Problemen innerhalb kürzester Zeit geholfen.