Tutorial: SSL-Zertifikate von Let's Encrypt
Wie bereits geschrieben verwende ich für diesen Blog jetzt ein SSL Zertifikat von Let's Encrypt. Und das funktioniert erstaunlich gut. Zu Beginn kann man aber schon mal etwas überfordert sein, da das Vergabesystem von Let's Encrypt sich doch von allen bisherigen Vergabestellen stark unterscheidet (nicht nur im Preis :)).
Deshalb hier eine kompakte Anleitng von Null bis SSL. Ich verwende den alternativen Client acme-tiny, da mir der offizielle Client viel zu mächtig und selbstständig erschien. acme-tiny hingegen ist sehr übersichtlich, eine einfache Python-Datei und gerade mal 200 Zeilen groß.
Wir erstellen uns zunächst ein eigenes Verzeichnis und legen darin das acme-tiny.py Script ab sowie das Zwischenzertifikat von Let's Encrypt, welches wir an alle erhaltenen Zertifikate anhängen müssen.
mkdir acme-tiny
cd acme-tiny/
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
wget -O - --no-check-certificate http://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py > acme_tiny.py
acme-tiny erstellt für uns automatisch einen Let's Encrypt Account. Hierfür benötigen wir vorab einen Private-Key, welchen wir wie folgt erstellen:
openssl genrsa 4096 > account.key
Um eine Domain zu verifizieren ruft LE eine URL auf dieser Domain auf und erwartet einen bestimmten Inhalt. acme-tiny erstellt diesen Inhalt als Datei im per Parameter angegebenen Ordner. Via Webserver-Konfiguration muss man sicherstellen, dass der Ordner unter folgender URL gelistet wird: domain.com/.well-known/acme-challenge/. Wichtig: LE ruft für alle Subdomains im Zertifikat ebenfalls die .well-known Location auf.
Wir legen uns also am besten an zentraler Stelle einen Ordner für Challenges an:
sudo -u www-data mkdir /var/www/challenges
Ein passender Apache Alias könnte so aussehen:
Alias /.well-known/acme-challenge /var/www/challenges
Alternativ kann der Ordner ".well-known/acme-challenge" natürlich auch tatsächlich auf dem Dateisystem angelegt werden oder als Symlink nach /var/www/challenges zeigen.
Soviel zu den allgemeinen (einmalig notwendigen) Schritten. Im folgenden das Prozedere um tatsächlich ein SSL-Zertifikat für eine bestimmte Domain zu erhalten. Wir möchten die Domain example.org sowie die Subdomains www.exsmple.org und mail.example.org mit einem einzigen Zertifikat sichern.
Für jedes Zertifikat benötigen wir zunächst einen Private-Key
openssl genrsa 4096 > example.org.key
Jetzt erstellen wir den CSR mit dem wir unser SSL-Zertifikat beantragen:
openssl req -new -sha256 -key example.org.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.org,DNS:www.example.org,DNS:mail.example.org")) > example.org.csr
Jetzt führen wir acme-tiny aus:
python acme_tiny.py --account-key ./account.key --csr ./example.org.csr --acme-dir /var/www/challenges/ > ./example.org.crt
Die Ausgabe sollte so oder so ähnlich aussehen:
Parsing account key...
Parsing CSR...
Registering account...
Already registered!
Verifying example.org...
example.org verified!
[..]
Signing certificate...
Certificate signed!
Das Zertifikat muss jetzt um das Intermediate erweitert werden:
cat example.org.crt intermediate.pem > example.org.pem
Das wars! Das Zertifikat "example.org.pem" und der zugehörige Key "example.org.key" kann jetzt für Apache, Postfix, Dovecot, etc. verwendet werden!
Gültigkeit der Zertifikate
Zertifikate von LE haben aktuell eine Gültigkeit von 3 Monaten, in Zukunft wahrscheinlich noch weniger. Um ein SSL-Zertifikat zu aktualisieren genügt der Aufruf von acme-tiny. Danach muss nur noch das Intermediate-Zertifikat angehängt werden und das alte Zertifikat damit überschrieben werden. Anschließend müssen alle Dienste, die dieses Zertifikat nutzen reloaded werden.
Dies kann also von einem einfachen batch-script und Aufruf per cron erledigt werden.
Probleme
Erscheint folgende Fehlermeldung
ImportError: No module named argparse
benötigt man noch folgende Datei im selben Verzeichnis wo sich die acme-tiny.py befindet:
https://raw.githubusercontent.com/ThomasWaldmann/argparse/master/argparse.py