Die Mehrheit der Let's Encrypt-Zertifikate kann über die HTTP-Validierung (HTTP-01 Challenge) ausgestellt werden, also über eine einfache Installation von Zertifikaten auf einem einzelnen Webserver. Sobald aber die Zertifikate für Lastverteilte (load-balanced) Websites oder redudante Mailserver mit unterschiedlichen IP-Adressen und Hostnamen ausgestellt werden sollen, stößt diese Methode an ihre Grenzen. Das Gleiche gilt auch für Wildcard-Zertifikate, sie kann somit nicht für Wildcard-Zertifikate verwendet werden.
Mit der DNS-Validierung (DNS-01 Challenge) können Zertifikatsanfragen über DNS-Einträge verifiziert werden, anstatt Inhalte über HTTP bereitzustellen. Das bedeutet, dass Zertifikate gleichzeitig für mehrere Webserver zum Beispiel hinter einem Load Balancer ausgestellt werden können – oder für auch Systeme, die nicht direkt über das Internet erreichbar sind. Selbst Wildcard-Zertifikate werden durch die DNS-Validierung unterstützt.
Mit dem Tool acme-dns-certbot wird Certbot angewiesen, sich mit einem externen DNS-Server zu verbinden, bei dem die Validierungseinträge automatisch per API gesetzt werden können, sobald ein Zertifikat angefordert wird. Der Vorteil liegt darin, dass Certbot nicht direkt in dem DNS-Provider integriert werden muss und ihm auch keinen vollständigen Zugriff auf die eigene DNS-Konfiguration gewährt werden muss – was der Sicherheit zugutekommt.
Dabei werden sogenannte delegierte DNS-Zonen verwendet, um die DNS-Abfragen für die Zertifikatsverifizierung an den Drittanbieter-DNS-Dienst weiterzuleiten. Nach der Ersteinrichtung können beliebig viele Zertifikate angefordert werden, ohne die Validierung manuell durchführen zu müssen.
Sehr von Vorteil des Scriptes acme-dns-certbot ist, dass damit Zertifikate für einzelne Server ausgestellt werden können, die sich hinter einem Load Balancer befinden oder nicht direkt über HTTP erreichbar sind. Die klassische HTTP-01 Challenge funktioniert in solchen Fällen nicht mehr. Alternativ müsste man die Validierungsdateien manuell auf jedem einzelnen Server hinterlegen. Das Tool ist auch dann nützlich, wenn ein Zertifikat für ein System ausgestellt werden soll, das nicht öffentlich zugänglich ist – man denke nur an interne Umgebungen.
Wie hier auf Let’s Encrypt mit Certbot bereits ausführlich beschrieben, muss zunächst Certbot installiert werden. Im Anschluss wird das Skript acme-dns-certbot benötigt. Das Script
~# wget -O /etc/letsencrypt/acme-dns-auth.py github.com/joohoi/acme-dns-certbot-joohoi/raw/master/acme-dns-auth.py
wird direkt in das passende Verzeichnis heruntergeladen und ausführbar gemacht
~# chmod a+x /etc/letsencrypt/acme-dns-auth.py
Wichtig ist jetzt, dass das Script unter Python 3 lauffähig ist. Deshalb muss in dem Script die erste Zeile - sofern das noch nicht der Fall ist -
~# vi /etc/letsencrypt/acme-dns-auth.py
zu
#!/usr/bin/env python3
geändert werden.
Aus Sicherheitsgründen sollte man sich das GitHub-Repository und den Skriptcode ansehen, bevor es ausgeführt wird. Alternativ kann man das Repository auch forken und so sicherstellen, dass der Code unter der eigenen Kontrolle bleibt.
Im folgenden Schritt wird der erstmalige Setup-Prozess in die Wege geleitet, indem über die DNS-Validierung ein Zertifikat angefordert wird.
~# certbot certonly --manual \
--manual-auth-hook /etc/letsencrypt/acme-dns-auth.py \
--preferred-challenges dns \
--debug-challenges -d \*.your-domain \
-d your-domain
Die Option --manual wird verwendet, um alle automatisierten Integrationsfunktionen von Certbot zu deaktivieren. In diesem Fall wird einfach ein reines Zertifikat ausgestellt, anstatt es zusätzlich automatisch auf einem Dienst zu installieren. Certbot so konfiguriert, dass es den acme-dns-certbot-Hook über die Option --manual-auth-hook verwendet. Mit der Option --preferred-challenges erhält Certbot die Anweisung die DNS-Validierung zu bevorzugen.
Certbot muss auch angewiesen werden, vor dem Versuch der Zertifikatsvalidierung zu pausieren. Das wird über das Argument --debug-challenges gesteuert. Damit gewinnt man die Zeit, die notwendigen DNS-CNAME-Einträge in der jeweiligen Zonendatei zu setzen, die von acme-dns-certbot benötigt werden. Mit dem Argument --debug-challenges pausiert der Certbot-Prozess, so dass man die erforderliche DNS-Änderungen vornehmen kann.
Jede der gewünschten Domainnamen können mit der Option -d angegeben werden. Bei der Ausstellung von einem Wildcard-Zertifikat ist es wichtig, mit Escape-Zeichen zu arbeiten. Das Asteriskzeichen * muss also mit einem Backslash “\” maskiert werden.
Im Anschluß daran wird man von Certbot mit einer Nachricht wie dieser zur Interaktion aufgefordert.
...
Output from acme-dns-auth.py:
Please add the following CNAME record to your main DNS zone:
_acme-challenge.your-domain CNAME 47eddf55-38fa-4d22-b43a-882b2366c9bb.auth.acme-dns.io.
Waiting for verification
...
Man also aufgefordert, den erforderlichen DNS-CNAME-Eintrag zur DNS-Zonendatei der Domain hinzufügen. Das wird dann die Kontrolle über die Subdomain _acme-challenge an den ACME-DNS-Dienst delegieren. Dadurch kann acme-dns-certbot letztlich die erforderlichen DNS-Einträge setzen kann, um die Zertifikatsanforderung zu validieren.
Dabei ist es empfohlen, die TTL (Time-to-Live) auf etwa 300 Sekunden zu setzen, um sicherzustellen, damit die Änderungen am Eintrag schnell propagiert werden.
Aber Vorsicht!
Die Ausgabe “_acme-challenge.your-domain CNAME” ist nicht ganz richtig! Denn, für den DNS-Server ist das kein vollqaulifizierter Domainname (FQDN)! BIND9 hängt hier zum Beispiel “example.tld” als den Domainnamen an. Heraus käme dann "_acme-challenge.example.tld.example.tld", diese Subdomain gibt es aber eben nicht. Und die Validierung würde scheitern.
Also sollte man im Hintergrund die Information haben, diesen Eintrag mit abschliessenden Punkt so vorzunehmen:
_acme-challenge.your-domain. CNAME 47eddf55-38fa-4d22-b43a-882b2366c9bb.auth.acme-dns.io.
Oder verkürzt ohne abschliessenden Punkt:
_acme-challenge CNAME 47eddf55-38fa-4d22-b43a-882b2366c9bb.auth.acme-dns.io.
Nachdem dieser Eintrag in die DNS-Zonendatei und ein Reload des Bind9-Services auf dem DNS-Server abgesetzt wurden, wird der Certbot-Prozess mit einem ENTER fortgesetzt. Damit wird die Zertifikatsanforderung validiert und der Ausstellungsvorgang abgeschlossen. Nach ein paar Sekunden erfolgt die erfolgreiche Ausstellung des Zertifikates mit einer ähnlichen Meldung von Certbot.
...
Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/your-domain/fullchain.pem
Your key file has beensaved at:
/etc/letsencrypt/live/your-domain/privkey.pem
...
Damit wurde das Skript acme-dns-certbot zum ersten Mal ausgeführt, um mit der Änderung an der DNS-Zonendatei die Zertifikat-Ausstellung zu gewährleisten.
Soeben haben wir das acme-dns-certbot Skript im Zusammenhang mit Wildcards angewendet. Oft ist es aber gewünscht, dass ganz konkrete Subdomains mit im Zertifikat auftauchen. Damit können Server wie Postfix, Dovecot und Apache2 besser umgehen, respektive man will bei den Benutzer-Clients Fehlermeldungen bezüglich des Zeritifikates vermeiden.
Dazu nutzen wir die gleiche Vorgehensweise, wie oben beschrieben, und nutzen diesmal aber diesen Befehl
~# certbot certonly --manual \
--manual-auth-hook /etc/letsencrypt/acme-dns-auth.py \
--preferred-challenges dns \
--debug-challenges \
-d mail.example.com \
-d smtp.example.com \
-d imap.example.de \
-d pop3.example.com
Certbot fragt dann, ob man das bestehende Zertifikat tatsächlich erweitern will oder besser abbrechen möchte. Wenn man weiter macht, dann folgt das Skript den bisherigen Aufforderungen die jeweiligen Zonendateien auf dem DNS-Server einzutragen.
Mittlerweile ist der Zustand erreicht, dass zumindest ein Let's Encrypt Zertifikat erfolgreich mit diesem Skript über die DNS-01 Challenge ausgestellt worden ist. Wie bei dem ursprünglichen Befehl certbot
können jetzt Zertifikate zu dieser Domain hinzugefügt, zurückgezogen und widerrufen werden. Allerdings mit dem Unterschied, dass eben nicht mehr gegen einen existierenden Virtual Host validiert werden muss. Somit ist die Ausstellung eines weiteren eigenständigen Wildcard-Zertifikat realisierbar:
~# certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.your-domain
Das heißt, das Hinzufügen weiterer Wildcard-Zertifikate zu der bereits validierten DNS-Domain ist wesentlich vereinfacht. So erfolgt das Hinzufügen einer Subdomain mit
~# certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d subdomain.your-domain
und macht das Hinzufügen eines weiteren CNAME-Eintrages in der entsprechenden Zonendatei nortwendig. Es folgt dann wieder die Certbot-Ausgabe, wie sie bei der Erstausstellung erfolgte.
Das Verlängern von Zertifikaten, die vor dem Ablauf stehen, erfolgt genauso wie in “Let’s Encrypt mit Certbot” beschrieben.
Diese Methode der Zertifikaterstellung eignet sich vor allem für Webserver, die hinter Loadbalancer geschaltet sind. Oder das in diesem Fall vorliegende Szenario betrifft redudante Mailserver, die ja für die Anwender gleichbleibende SSL/TSL-Zertifikate haben sollten, wenn via DNS-Failover bei einem Ausfall des Mailservers der Domainname auf die IP-Adresse des Failover-Mailserver gelegt werden soll.