Letsencrypt

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"

Weitere Quellen

Published by

Steven Varco

Steven ist ein Redhat RHCE- und Kubernetes CKA Zertifizierter Linux-Crack und ist seit über 20 Jahren sowohl beruflich wie auch privat auf Linux spezialisiert. In seinem Keller steht ein Server Rack mit diversen ESX und Linux Servern.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert