Seit letsencrypt gegründet wurde, ist es jedermann möglich kostenlose SSL Zertifikate mit unterschiedlichen Methoden zu erstellen.
Die gängigsten werden hier vorgestellt.
Inhalt
HTTP
Dies ist das am meisten eingesetzte vorgehen.
DNS
Das beziehen eines SSL Zertifikats per DNS ist auch wegen zusätzlichen Sicherheitsüberlegungen etwas aufwändiger. Dafür hat man den Vorteil, dass zum Zeitpunkt der Erstellung (noch) kein Webserver laufen muss und man auch wildcard Zertifikate erstellen kann.
Nachfolgende wir das erstellen eines Wildcard SSL Zertifikats (z.B.: ‚*.example.com‘ erklärt.
Dedizierte DNS Zone erstellen
Da später das letsencrypt Script TXT Einträge in der DNS Zone machen muss, erstellt man eine dedizierte Zone (sog. Zone Delegation) für nur diesen Eintrag. Somit ist die Hauptzone geschützt vor externen Zugriffen.
Dies ist ähnlich wie im Tutorial DDNS Server.
Dazu fügt man seinem DNS Zonefile folgende Zeilen hinzu:
_acme-challenge.example.com. IN NS ns1.example.com.
Ein einfaches Beipsiel Zonefile würde dann wie folgt aussehen:
$TTL 3600
$ORIGIN example.com.
@ 86400 IN SOA ns1.example.com. dnsadmin. example.com. (
2021021601 ; Serial
86400 ; Refresh
7200 ; Retry
3600000 ; Expire
3600 ) ; Minimum
@ 86400 IN NS ns1.example.com.
@ 86400 IN NS ns2.example.com.
@ IN A 93.184.216.34
@ IN MX 10 mail.example.com.
@ IN TXT "v=spf1 ip4:93.184.216.34 ~all"
mail IN A 93.184.216.34
www IN A 93.184.216.34
; Sub-zone delegation
_acme-challenge.example.com. IN NS ns1.example.com.
Diese trägt man nun in die Konfigurationsdatei wo die Zonen konfiguriert werden wie folgt ein:
zone "_acme-challenge.example.com" IN {
type master;
file "/var/named/dynamic/_acme-challenge.example.com";
allow-query { any; };
update-policy {
grant "letsencrypt" subdomain _acme-challenge.example.com. TXT;
};
};
Im vergleich zu „normalen“ Zonen sind folgende Einträge speziell:
file "/var/named/dynamic/_acme-challenge.example.com
: Da dies eine „dynamische“ Zone wird, wird sie in dem Verzeichnis: /var/named/dynamic/ (anstelle von /etc/named/zones/ o.ä.) gespeichert.update-policy { grant [...]
: Hier wird einem Schlüssel (den wir gleich noch erstellen werden) mit dem Namen ‚letsencrypt‘ erlaubt TXT Einträge in der Subdomain ‚_acme-challenge.example.com‘ zu erstellen, ändern und löschen
Nun wird das dynamische Zonefile in: /var/named/dynamic/_acme-challenge.example.com erstellt:
$ORIGIN .
$TTL 60 ; 1 minute
_acme-challenge.example.com IN SOA ns1.example.com. dnsadmin.example.com. (
1 ; serial
3600 ; refresh (1 hour)
900 ; retry (15 minutes)
604800 ; expire (1 week)
300 ; minimum (5 minutes)
)
NS ns1.example.com.
Zugriffsschlüssel erstellen
Damit nicht jeder diesen Eintrag ändern kann, wird noch ein Zugriffsschlüssel mit dem Tool dnssec-keygen
erstellt:
dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST letsencrypt
Hinweis: Das erstellen des Schlüssel könnte sehr lange dauern, wegen der fehlenden entropy auf dem System. Wenn das so ist, schafft der Dienst haveged Abhilfe.
dnssec-keygen
erstellt zwei Dateien (Kletsencrypt.*.{private,key}
) in welchen sich der Schlüssel (key) findet.
Diesen tragen wir nun in der bind Konfiguration ein:
key "letsencrypt" {
algorithm hmac-sha512;
secret "wIh3AOp1tzOhCb05AxkNeT24wz24DU/jCd3Cvc19sf4kd8nvOwEL8J/APUX5ysLyOCxLlUzHBCz3eOPKHMHW3g==";
};
Nach einem Neustart des Nameservers ist die Konfighhuration auch schon fertig:
systemctl restart named
Testen
Test lässt sich das mit dem Tool nsupdate
.
Zuvor muss jedoch noch der Schlüssel welcher in der bind Konfuguration steht in eine externe Datei gespeichert werden.
Dazu wird eine neue Datei mit exakt dem selben Teil wie vorher bei der bind Konfiguration gemacht wurde erstellt:
letsencrypt.key
key "letsencrypt" {
algorithm hmac-sha512;
secret "wIh3AOp1tzOhCb05AxkNeT24wz24DU/jCd3Cvc19sf4kd8nvOwEL8J/APUX5ysLyOCxLlUzHBCz3eOPKHMHW3g==";
};
Nun kann man nsupdate
mit der Option -k
den Key mitgeben:
nsupdate -k letsencrypt.key
> server ns1.example.com.
> zone _acme-challenge.example.com.
> update delete _acme-challenge.example.com. TXT
> update add _acme-challenge.example.com. 300 TXT "test-string"
> send
Das man das ganze nicht immer wieder Zeile für Zeile eingeben muss, kann man es auch automatisieren:
/usr/bin/nsupdate -k letsencrypt.key << EOM
server ns1.example.com.
zone _acme-challenge.example.com.
update delete _acme-challenge.example.com. TXT
update add _acme-challenge.example.com. 300 TXT "test-string"
send
EOM
Nun kann man den neu erstellten Eintrag mit dig anzeigen:
dig _acme-challenge.example.com. TXT +noall +answer
letsencrypt konfigurieren
Läuft alles braucht man nur noch eine Konfigurationsdatei für den letsencrypt certbot
mit Angabe des DNS keys zu erstellen:
dns-auth.sh
#!/bin/bash
if [ -z "$CERTBOT_DOMAIN" ] || [ -z "$CERTBOT_VALIDATION" ]
then
echo "EMPTY DOMAIN OR VALIDATION"
exit -1
fi
HOST="_acme-challenge"
/usr/bin/nsupdate -k letsencrypt.key << EOM
server ns1.example.com
zone ${HOST}.${CERTBOT_DOMAIN}
update delete ${HOST}.${CERTBOT_DOMAIN} TXT
update add ${HOST}.${CERTBOT_DOMAIN} 300 TXT "${CERTBOT_VALIDATION}"
send
EOM
echo ""
Und dann den certbot
aufrufen:
certbot certonly --dry-run --agree-tos --email "test@example.com" --manual --preferred-challenges=dns --manual-auth-hook ./dns-auth.sh -d "*.example.com"
Hinweis: Um das Zertifikat tatsächlich zu erstellen, aus dem obigen Aufruf den Parameter --dry-run
raus nehmen. 😉
Weitere subdomains
Damit lassen sich nun nur Wildcard SSL Zertifikate für die Hauptdomain (*.example.com), nicht aber für allfällige subdomains wie z.B: *.www.example.com.
Möchte man dies noch machen, kann jedoch im Haupt-Zone file einfach ein CNAME angelegt werden:
[...]
$ORIGIN example.com.
[...]
_acme-challenge.www.example.com. IN CNAME _acme-challenge.example.com.
[...]
; Sub-zone delegation
[...]
Dann muss noch das dns-auth.sh Script angepasst werden, so dass es immer den Eintrag: _acme-challenge.example.com aktuallisiert und nicht: _acme-challenge.www.example.com:
dns-auth2.sh
#!/bin/bash
if [ -z "$CERTBOT_DOMAIN" ] || [ -z "$CERTBOT_VALIDATION" ]
then
echo "EMPTY DOMAIN OR VALIDATION"
exit -1
fi
HOST="_acme-challenge"
/usr/bin/nsupdate -k letsencrypt.key << EOM
server ns1.example.com
zone ${HOST}.example.com
update delete ${HOST}.example.com TXT
update add ${HOST}.example.com 300 TXT "${CERTBOT_VALIDATION}"
send
EOM
echo ""
Danach kann man certbot
mit dem neuen Script und Angabe der Subdomain aufrufen:
certbot certonly --dry-run --agree-tos --email "test@example.com" --manual --preferred-challenges=dns --manual-auth-hook ./dns-auth2.sh -d "*.www.example.com"