User Tools

Site Tools


server:letsencrypt

This is an old revision of the document!


Let's Encrypt

Bei Let's Encrypt handelt es sich um eine offene Zertifizierungsstelle, bei der man kostenlos X.509-Zertifikate für TLS1) (ehemals SSL) erstellen kann. Gegründet wurde das Projekt 2014 von der EFF2), Mozilla und der University of Michigan. Am 3. Dezember 2015 startete die öffentliche Beta-Phase, ab der man ohne vorherige Einladung mithilfe des in Python geschriebenen letsencrypt-Clients weitestgehend automatisiert Zertifikate für den eigenen Server erhalten kann.

Installation ohne Wrapper

Unter Arch Linux befindet sich der letsencrypt-Client in den Community-Quellen und kann mittels

# pacman -S letsencrypt

einfach installiert werden. Anstatt alle Einstellungen als Argumente zu übergeben, besteht auch die Möglichkeit, eine Konfigurationsdatei zu erstellen. Standardmäßig sucht der Client nach /etc/letsencrypt/cli.ini. Im Folgenden will ich alles weitestgehend automatisieren und erstelle Domain-spezifische Konfigurationsdateien.

# vim /etc/letsencrypt/domain.tld.cnf

In diese Datei kommt der folgende Inhalt:

/etc/letsencrypt/domain.tld.cnf
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096
# use the webroot authenticator
authenticator = webroot
webroot-path = /tmp/letsencrypt/
# Use acme-v01 server (public beta), should be used by default
#server = https://acme-v01.api.letsencrypt.org/directory
 
# Uncomment and update to register with the specified e-mail address
email = mail@domain.tld
 
renew-by-default
agree-tos
 
# domain list
domains = domain.tld, www.domain.tld, subdomain.domain.tld
 
# Uncomment to use a text interface instead of ncurses
text = True

Bei der erstmaligen Verwendung wird ein Benutzerkonto angelegt, das mit der E-Mail-Adresse verknüpft ist und unter /etc/letsencrypt/accounts wichtige Dateien wie den Private Key ablegt.

nginx

Bevor die Zertifikate ausgestellt werden, wird nach dem ACME3)-Protokoll dem Challenge-Response-Verfahren folgend eine mit dem Private Key verifizierte Challenge erstellt. Um den Besitz der Domains zu überprüfen, versucht der ACME-Server die jeweilige Challenge passend zur (Sub-)Domain unter (subdomain.)domain.tld/.well-know/acme-challenge/kryptographischerstring abzurufen. Dazu müssen wir nginx beibringen, wie es die Challenge ausliefert. Dazu in jeden server {} Block, zu dem ein Zertifikat ausgestellt werden soll, die folgende location einfügen:

location ~ '/.well-known/acme-challenge' {
	default_type "text/plain";
	root /tmp/letsencrypt;
}

Danach mit

# systemctl restart nginx

den nginx-Server neustarten, damit die Änderungen übernommen werden. Damit haben wir die Vorbereitungen abgeschlossen und können mit der Ausstellung der Zertifikate beginnen.

Ausführung

Zuerst erstellen wir den unter webroot-path angegebenen Pfad, da sich der letsencrypt-Client ansonsten mit einer Fehlermeldung beendet:

$ mkdir /tmp/letsencrypt

Nun können wir den Vorgang mit

# letsencrypt certonly -c /etc/letsencrypt/domain.tld.cnf

starten. Das Ganze dauert ein wenig; was aktuell ausgeführt wird, kann durch hinzufügen der Flag -v am Ende des Befehls angezeigt werden. War alles erfolgreich, müssen wir nur noch die Zertifikate in nginx einbinden.

Sollte etwas schief gelaufen sein, kann unter /var/log/letsencrypt/letsencrypt.log der Log des letzten Vorgangs eingesehen werden.

Zertifikate in nginx

Die fertigen Zertifikate werden unter /etc/letsencrypt/live/domain.tld abgespeichert. Entsprechend müssen wir die Pfade in die jeweiligen server {} Blöcke der nginx.conf einfügen:

	ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem;
	ssl_trusted_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;

Dabei wird ssl_trusted_certificate nur für OCSP Stapling benötigt. Soll OCSP Stapling aktiviert werden, sollte Folgendes im http {} Block der nginx.conf stehen:

    # enable ocsp stapling (reduces amount of time until first byte)
    ssl_stapling on;
    ssl_stapling_verify on;

Zum Schluss noch mit

# systemctl restart nginx

den nginx-Server neustarten.

Mehr zu nginx und den SSL/TLS spezifischen Einstellungen für mehr Sicherheit kann hier gefunden werden.

Erneuerung der Zertifikate

Das Erneuern der Zertifikate ist denkbar einfach und läuft analog zu der erstmaligen Ausführung ab. Da alle Einstellungen in einer Konfigurationsdatei hinterlegt sind, kann mit dem Aufruf von

# letsencrypt certonly --renew -c /etc/letsencrypt/domain.tld.cnf

die Erneuerung angestoßen werden. Ist das Skript durchgelaufen, muss der Server nur noch mit

# systemctl restart nginx

neugestartet werden, um die neuen Zertifikate zu laden. Fertig.

Automatisierung mittels cron

Der Vorteil von Let's Encrypt besteht darin, dass nach Möglichkeit alles automatisch ablaufen soll und einem der Client das erstellen von Certificate Signing Requests etc. abnimmt. Aus diesem Grund sind die Zertifikate auch aktuell nur auf eine Laufzeit von 90 Tagen ausgelegt. Später, wenn alles gut läuft, soll die Gültigkeit auf nur 30 Tage herabgesetzt werden. Aus diesem Grund kann es von Vorteil sein, wenn der Server sich automatisch ohne Zutun von außen um die Erneuerung der Zertifikate kümmert.

Dazu habe ich folgendes Bash-Skript erstellt, welches dafür sorgt, dass das verwendete webroot-Verzeichnis existiert, die Zertifikate erneuert werden und bei erfolgreicher Ausstellung nginx neugestartet wird:

/etc/letsencrypt/renew.sh
#!/usr/bin/bash
# Automate certificate renewal for a given domain, assuming all necessary config parameters are set in /etc/letsencrypt/domain.tld.cnf
# Usage: /etc/letsencrypt/renew.sh domain.tld
 
DOMAIN=${1?"No argument given! Please provide the domain which should be renewed"}
EMAIL=$(awk '/email/ {print $3}' /etc/letsencrypt/$DOMAIN.cnf)
 
if [ ! -f /etc/letsencrypt/$DOMAIN.cnf ]; then
        echo "Config file /etc/letsencrypt/$DOMAIN.cnf does not exist!"
        exit 1;
fi
 
# Renew Let's Encrypt SSL cert
mkdir -p /tmp/letsencrypt
letsencrypt certonly --renew -c /etc/letsencrypt/$DOMAIN.cnf
 
if [ $? -ne 0 ]; then
        ERRORLOG=`tail /var/log/letsencrypt/letsencrypt.log`
        echo -e "The Lets Encrypt Cert has not been renewed!\n\n" $ERRORLOG | mail -s "Lets Encrypt Cert Alert" $EMAIL
else
        systemctl restart nginx
fi
 
rm -rf /tmp/letsencrypt
 
exit 0

Ist das Skript ausführbar

# chmod +x /etc/letsencrypt/renew.sh

muss es mit der Domain aufgerufen werden, die erneuert werden soll:

# /etc/letsencrypt/renew.sh domain.tld

Sollte etwas schief laufen, wird eine E-Mail an admin@domain.tld gesendet, vorausgesetzt, der Server ist dazu eingerichtet, Mails versenden zu können.

Dieses Skript können wir mittels cron in definierten Zeitintervallen ausführen lassen, wozu ein Befehl in crontab hinzugefügt wird. Mit

# crontab -e

können neue Befehle hinzugefügt werden. Wird etwas geändert, lädt cron die neuen Befehle automatisch. Mit

# crontab -l

können alle registrierten cron-Jobs angezeigt werden.

Sollen die Zertifikate z. B. alle zwei Wochen erneuert werden, und zwar montags um 5 Uhr nachts, können wir folgendes mit crontab -e eintragen:

# renew letsencrypt certificates for domain domain.tld every other monday at 5:00
0 5 * * 1 expr `date +\%W` \% 2 > /dev/null || /etc/letsencrypt/renew.sh domain.tld

Cron Regeln testen

Sollten die cron-Regeln eher kryptisch anmuten, ist es mit der Cron Sandbox möglich, sich die nächsten Termine anzeigen zu lassen, die mit der jeweiligen Regel zutreffen.

Komplett manuell ohne Client

Es ist auch möglich, komplett manuell ohne Verwendung des letsencrypt-Clients Zertifikate zu beziehen. Dazu hat jemand eine statische Seite geschrieben, bei der man sich selbst um die Arbeit kümmern muss: https://gethttpsforfree.com/. Dazu sollte man jedoch wissen, wie man Zertifikate mit einem CSR beantragt.

1)
Transport Layer Security
2)
Electronic Frontier Foundation; NGO, die sich für Grundrechte im Internet einsetzt
3)
Automated Certificate Management Environment
server/letsencrypt.1449530765.txt.gz · Last modified: by sascha