Kostenlose SSL/TLS-Zertifikat von LetsEncrypt installieren

Dies ist eine Anleitung, um ein kostenloses SSL/TLS-Zertifikat von LetsEncrypt auf dem eigenen Server zu installieren, und die eigene Webseite über HTTPS zugänglich zu machen.

Seit Ende 2015 gibt es eine gemeinnützige Certificate Authority, die SSL-Zertifikate kostenlos und mit einer einfachen Installation anbietet. LetsEncrypt wird von der Linux Foundation getragen und von zahlreichen bekannten Vereinen und großen Unternehmen (EFF, Mozilla, Cisco, Internet Society, usw.) unterstützt. Die Installation der Zertifikate wird über eine Software weitgehend automatisiert.

Im ersten Schritt wird der LetsEncrypt-Client installiert. Im zweiten Schritt wird ein neues Zertifikat abgerufen. Schritt drei zeigt die manuelle Einrichtung des Nginx-Webservers für SSL/TSL, um aus einer HTTP-Webseite eine sichere HTTPS-Seite zu machen. Im Schritt vier wird die notwendige, regelmäßige Erneuerung der Zertifikate automatisiert.

Die LetsEncrypt-Anwendung installieren

LetsEncrypt existiert erst seit Ende 2015, und viele Linux-Distributionen haben den letsencrypt-Client noch nicht in ihre Software-Repositories aufgenommen. Der Client kann jedoch einfach aus dem LetsEncrypt Github-Konto geladen und installiert werden.

Die Installation sollte im /opt-Verzeichnis erfolgen, wie für manuell installierte Software auf Linux-Systemen üblich.

root@server:~# cd /opt
root@server:~# git clone https://github.com/letsencrypt/letsencrypt
root@server:~# cd letsencrypt
root@server:~# ./letsencrypt-auto --help

Mit letsencrypt-auto werden automatisch alle notwendigen Einstellungen vorgenommen, und zum Schluss noch die Hilfe angezeigt. Der LetsEncrypt-Client ist nun einsatzbereit.

SSL-Zertifikat installieren

Zur Installation eines SSL-Zertifikats bietet Letsencrypt zwei Varianten an, die sich in der Art unterscheiden, wie LetsEncrypt die Zugehörigkeit der Domain zum Server überprüft.

Soll für example.com ein Zertifikat erstellt werden, so sendet unser LetsEncrypt-Client dies an den LetsEncrypt Zertifikate-Server. Dieser muss nun überprüfen, ob "example.com" auch wirklich auf unserem Server liegt. Dazu ruft er eine bestimmte Test-Datei ab, zum Beipiel example.com/well-known/testdatei.html. Ist die Datei abrufbar, dann ist die Domain "example.com" tatsächlich auf unseren Server konfiguriert.

Die "standalone"-Methode ist also einfacher zu konfigurieren, die "webroot"-Methode ist nur bei stark frequentierten Webseiten vorzuziehen, da es hierbei keine Downtime des Webservers gibt. Im folgenden Beispiel muss "example.com" natürlich durch die eigene Domain ersetzt werden.

root@server:~# service nginx stop
root@server:~# /opt/letsencrypt/letsencrypt-auto certonly \
      --standalone --standalone-supported-challenges tls-sni-01 \
      -d example.com -d www.example.com -d mail.example.com
root@server:~# service nginx start

Einschränkungen der LetsEncrypt-Zertifikate

Bisher unterstützt Letsencrypt noch keine Wildcard-Domains, also *.example.com geht nicht. Das Zertifikat sollte daher für example.com und übliche Subdomains wie www und mail (damit auch Email über eine verschlüsselte Verbindung gesendet und abgerufen werden kann) ausgestellt werden.

Das SSL-Zertifikat liegt nun unter /etc/letsencrypt/live/example.de in vier *.pem Dateien.

Zu beachten ist, dass eine Domain mit SSL-Zertifikat dazu führen kann, dass einige Browser auch automatisch annehmen, dass alle ihre Subdomains über HTTPS ausgeliefert werden. Eine Domain mit Zertifikat https://example.com veranlasst den Webbrowser also, auch die Subdomain http://foo.example.com auf ein https:-Protokoll umzuleiten, indem sie den HTTP-Header Upgrade-Insecure-Requests: 1 an den Server zurücksenden. Der Webserver wird auf den Header antworten, und den Browser umleiten auf die HTTPS-Version, also https://foo.example.com.

Wurde jedoch die Subdomain nicht explizit in das Zertifikat integriert (mit -d foo.example.com), dann wird der Server nur ein selbst-signiertes HTTPS zurückliefern, und der Browser wird keinen dazu passenden C.A.-Eintrag finden. Ein selbst-signiertes HTTPS ist jedoch keine echte Verschlüsselung, so dass dem Benutzer eine dicke Warnung im Webbrowser angezeigt wird: "Die Verbindung ist nicht geschützt!" Das sollte nicht passieren.

SSL/TLS auf Nginx einrichten

Um eine bestehende Webseite unter Nginx auf ein SSL/TLS-Zertifikat umzustellen, müssen einige Zeilen in die Konfigurationsdatei der jeweiligen Seite eingefügt werden. Sieht die Konfiguration der Beispielseite bisher so aus

root@server:~# vim /etc/nginx/sites-available/example.com

server {
    listen *:80;
    listen [::]:80;
    server_name example.com *.example.com;
    root /var/www/example.com;
    index index.html;
    location / { try_files $uri $uri/ =404; }
}

Dann würde sie mit dem SSL-Zertifikat so aussehen. Der Server auf Port 80 leitet jetzt also nur noch um auf Port 443, den HTTPS-Port. Der Server auf Port 443 reagiert nur auf "ssl"-Anfragen.

root@server:~# vim /etc/nginx/sites-available/example.com

server {
    listen *:80;
    listen [::]:80;
    server_name example.com *.example.com;
    return 301 https://example.com$request_uri;
}
server {
    listen *:443 ssl;
    listen [::]:443 ssl;

    server_name example.com *.example.com;
    root /var/www/example.com;
    index index.html;
    location / { try_files $uri $uri/ =404; }

    ssl on;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5';
    ssl_prefer_server_ciphers on;

    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
}

Die beiden Zeilen ssl_certificate und ssl_certificate_key müssen ebenfalls mit der eigenen Domain angepasst werden.

Erneuerung der LetsEncrypt-Zertifikate automatisieren

LetsEncrypt-Zertifikate haben nur eine relativ kurze Lebensdauer von 3 Monaten. Danach müssen sie verlängert werden, oder verlieren ihre Gültigkeit. Die Verlängerung kann jedoch ganz einfach über ein Skript erfolgen, dass regelmäßig durch Cron ausgeführt wird.

root@server:~# mkdir -P /opt/letsencrypt_updater
root@server:~# vim /opt/letsencrypt_updater/example.com

#!/bin/bash

DOMAIN=$(basename $0)
EMAIL=admin@example.com
LOGFILE=/tmp/$(date +%s).log

echo '.' | mail -s "Start LetsEncrypt renew $DOMAIN" $EMAIL
echo "Log start: $(date)" >>$LOGFILE
service nginx stop >>$LOGFILE 2>&1

/opt/letsencrypt/letsencrypt-auto certonly --standalone --non-interactive --agree-tos --text --standalone-supported-challenges tls-sni-01 -d $DOMAIN -d mail.$DOMAIN -d www.$DOMAIN >>$LOGFILE 2>&1

service nginx start >>$LOGFILE 2>&1
service postfix reload >>$LOGFILE 2>&1
service dovecot reload >>$LOGFILE 2>&1

echo "Log done: $(date)" >>$LOGFILE
mail -s "v874 cert $DOMAIN start" $EMAIL < $LOGFILE
rm -f $LOGFILE

Das Bash-Skript benutzt den Dateinamen (example.com) als Domain, für die ein Zertifikat erstellt oder erneuert werden soll. Beim Start des Skripts wird eine Status-Meldung an die EMAIL-Adresse gesendet. Dann wird der Nginx-Webserver angehalten, das Zertifikat abgerufen, und Nginx wird wieder neu gestartet. Die Email-Server Postfix und Dovecot laden ebenfalls ihre Konfiguration neu. Alle Ausgaben und Fehlermeldungen werden am Ende wieder an die EMAIL-Adresse geschickt.

Nun wird in die Crontab des Root-Benutzers noch ein Aufruf des Skripts eingefügt.

root@server:~# crontab -e

EMAIL="admin@example.com"
45 3 * * 3 /opt/letsencrypt_updater/example.com

Dadurch läuft das Update-Skript jeden Donnerstag um 03:45 Uhr. Das Skript sollte mindestens einmal pro Woche aufgeführt werden. Ein Update wird aber nur ausgeführt, wenn dem Zertifikat weniger als ein Monat bis zum Laufzeitende bleiben.