Seit Dezember 2015 gibt es die Möglichkeit über Let’s Encrypt kostenlos SSL-Zertifikate für Webanwendungen zu erhalten. Wie funktioniert das genau? Wie geht es am Einfachsten?
Verschlüsselung von Webseiten über HTTPS mittels SSL bzw. TLS gibt es schon eine geraume Zeit. Nichtsdestotrotz werden weiterhin eine Vielzahl gerade kleinerer Webseiten unverschlüsselt übertragen. Warum? Ganz einfach: Die Ausstellung eines Verschlüsselungszertifikats ist mit Kosten verbunden, typischerweise ab 40 Euro pro Jahr. Das ist für Seiten, die keine Einnahmen erzielen nicht rentabel. Dennoch möchte man bei Eingabeformularen für Benutzer oder gerade bei der Eingabe von Benutzernamen und Passwort eine Verschlüsselte Kommunikation haben, da sonst diese Daten unter Umständen von Dritten im Klartext gesehen werden können (wenn z.B. der Nutzer sich in einem öffentlichen WLAN befindet).
Die Zertifizierungsstelle Let’s Encrypt
Glücklicherweise hat die Internet Security Research Group (ISRG) mit Unterstützung durch ein paar Branchengrößen (Mozilla, Electronic Frontier Foundation, Cisco, Facebook, usw.) die Let’s Encrypt Initiative ins Leben gerufen. Seit Ende 2015 befindet sich das Programm in der öffentlichen Betaphase und kann von jedem für seine Webseiten genutzt werden. Voraussetzung ist dabei allerdings, dass man einen Konsolenzugriff zum Server hat, als auch die Konfigurationen des Webservers ändern kann.
Vorteile
- Kostenlos
- wird von den meisten Browsern erkannt
Nachteile
- noch in der Public Beta
- 90 Tage Gültigkeit der Zertifikate (Automatisierung erforderlich)
- keine IDN unterstützt (internationale Domainnamen, z.B. mit Umlauten)
Verwendung
Wie können nun SSL-Zertifikate bei Let’s Encrypt beantragt werden?
Bei bisherigen Zertifizierungsstellen ist es meist so, dass man selbst auf seinem Server händisch die Schlüssel und einen zugehörigen Zertifizierungsantrag (Certificate Signing Request, CSR) erstellt, diesen dann beim Anbieter hochlädt und danach ein signiertes Zertifikat zurück erhält.
Der Let’s Encrypt Client
Bei Let’s Encrypt hat man sich zu diesem Vorgehen Gedanken gemacht und versucht, die Erstellung von Zertifikaten zu vereinfachen. Es wird einfach ein Programm auf dem Webserver ausgeführt, auf dem man Zertifikate nutzen möchte. Mit Hilfe dieses Let’s Encrypt Client können dann Zertifikate beantragt und verlängert werden. Der Let’s Encrypt Client hat für mich aber entscheidende Nachteile:
- Zum einen startet der Client einen eigenen Webserver auf Port 80 – das unterbricht z.B. den Service für den Apache-Webserver, wenn dieser auf dem gleichen Rechner läuft. Es können also während der Zertifikat-Erneuerung keine normalen Webseiten vom Server ausgeliefert werden.
- Weiterhin hat der Client erhebliche Abhängigkeiten, die dann erst auf einem Server installiert werden müssen. Das sorgt wieder für unnötigen „Overhead“.
- Schließlich benötigt der Client auch Root-Berechtigungen, um den integrierten Webservice auf Port 80 starten zu können.
Ein alternativer Client
Aus diesen Gründen habe ich mich nach einer Alternative umgesehen und bin bei Github auf acme_tiny gestoßen. Das Skript hat keinerlei zusätzliche Abhängigkeiten, lässt sich also gut auf einem Server hinterlegen. Zudem lassen sich die Zertifikate mit acme_tiny auch erneuern ohne dass der Webserver beendet werden muss. Es kann also Unterbrechungsfrei erfolgen.
Verwendung von acme_tiny
Als erstes legen wir uns unter /opt/acme-tiny ein Arbeitsverzeichnis für die Verschlüsselung an. Dort laden wir dann auch mittels
wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py
den Acme_tiny Client herunter.
Eigenen Schlüssel und Account anlegen
Zuerst muss ein Let’s Encrypt Account-Schlüssel angelegt werden. Dabei handelt es sich um einen 4096-Bit RSA Schlüssel, der einfach mittels OpenSSL erzeugt werden kann:
openssl genrsa 4096 > account.key
Alternativ kann auch der offizielle Client verwendet werden. Danach müsste aber der Schlüssel konvertiert werden – Eine Anleitung dazu ist bei Acme_tiny verfügbar.
Account-Key sichern
Dieser Account-Key ist, genauso wie die privaten Domainschlüssel, die wir später erzeugen, geheim zu halten und zu sichern. Ohne den Account-Key können keine Zertifikate ausgestellt werden. Diese Schlüssel dürfen auch keinen Dritten zugänglich sein.
Domain private Key erzeugen
Der private Schlüssel für die zu verschlüsselnde Domain wird analog zum Account-Key erzeugt:
openssl genrsa 4096 > einbeispiel.key
Diesen privaten Schlüssel hinterlegt man dann auch gleich unter /etc/ssl/private/, da wir später den Webserver entsprechend auf diesen Pfad zugreifen lassen.
CSR erstellen
Nun haben wir unsere privaten Schlüssel erstellt und können eine Signaturanfrage stellen (Certificate Signing Request, CSR).
Hier gibt es zwei verschiedene Möglichkeiten: Entweder wir brauchen nur einen Domänennamen (z.B. einbeispiel.de), oder wir brauchen das Zertifikat für mehrere Domänennamen (einbeispiel.de, ein-beispiel.de). Das gilt auch, wenn wir Subdomains (wie www) mit dem Zertifikat abdecken wollen. Also wird meistens ein sogenannter Subject Alternate Name (SAN) benötigt.
ohne SubjectAltName
openssl req -new -sha256 -key einbeispiel.key -subj "/CN=einbeispiel.de" > einbeispiel.csr
mit SubjectAltName
openssl req -new -sha256 -key einbeispiel.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:einbeispiel.de,DNS:www.einbeispiel.de")) > einbeispiel.csr
Challenge hinterlegen
Ein Teil des Signatur-Prozesses ist die Prüfung, ob die Domain auch unter der eigenen Kontrolle steht. Dazu muss eine sogenannten Challenge hinterlegt werden, die vom Let’s Encrypt-Server dann abgefragt wird.
Dazu legen wir uns einen Challenges-Ordner an:
mkdir /var/www/challenges
Dieser muss dann bei der gewünschten Domain in der Apache-Konfiguration unter /etc/apache2/sites-available/einbeispiel.conf hinterlegt werden:
# Letsencrypt Challenges
Alias /.well-known/acme-challenge/ /var/www/challenges/
Danach ist die Konfiguration vom Webserver noch neu einzulesen (Apache reload), so dass das Verzeichnis auch korrekt angesprochen werden kann.
Zertifikat signieren lassen
Nun kommt der große Moment des Clients:
python acme_tiny.py --account-key ./account.key --csr ./einbeispiel.csr --acme-dir /var/www/challenges/ > ./einbeispiel.crt
Damit erhält man in der Datei einbeispiel.crt das signierte Zertifikat. Nun kann man diese Datei noch um das Zwischenzertifikat von Let’s Encrypt anreichern:
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat einbeispiel.crt intermediate.pem > /etc/ssl/certs/einbeispiel.pem
Nun hat man den öffentlichen Schlüssel korrekt hinterlegt und kann die Dateien im Webserver einbinden.
Zertifikat in Apache einbinden
Grundsätzlich muss das Modul SSL geladen werden, damit Seiten per HTTPS ausgeliefert werden können. Erst dann ist ein Zugriff auf die folgenden Befehle möglich. Nun legen wir unseren VHost-Eintrag an:
<VirtualHost *:443>
ServerName einbeispiel.de
ServerAlias www.einbeispiel.de
DocumentRoot /var/www/
SSLEngine on
SSLCertificateFile /etc/ssl/certs/einbeispiel.pem
SSLCertificateChainFile /etc/ssl/certs/einbeispiel.pem
SSLCertificateKeyFile /etc/ssl/private/einbeispiel.key
# Letsencrypt Challenges
Alias /.well-known/acme-challenge/ /var/www/challenges/
</VirtualHost>
Nach einem Neustart des Apachen ist nun die Seite auch per HTTPS verfügbar. Hurra.
Automatisierung
Jetzt wird zwar die Webseite verschlüsselt übertragen, das zugehörige Zertifikat ist aber nur 90 Tage gültig. Also das Zertifikatsprozedere in 3 Monaten wiederholen? Nein, ein kleines Shell-Skript mit zugehörigem Cronjob schafft Abhilfe:
#!/bin/sh
python /opt/acme-tiny/acme_tiny.py --account-key /opt/acme-tiny/account.key --csr /opt/acme-tiny/einbeispiel.csr --acme-dir /var/www/challenges/ > /tmp/signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat /tmp/signed.crt intermediate.pem > /etc/ssl/certs/einbeispiel.crt
service apache2 reload
Dieses Skript kann nun als Cronjob (geplanter Task) monatlich aufgerufen werden, und das Zertifikat wird automatisch erneuert. Man muss sich somit nicht wieder um die Webseiten-Verschlüsselung kümmern. Und das ist sogar ein Vorteil gegenüber kommerziellen SSL-Zertifikatsanbietern.
Fazit und Ausblick
Bei den Umgang mit den privaten Schlüsseln (sowohl Account als auch Domain) ist darauf zu achten, dass keine Unberechtigten Zugriff darauf haben. Es sollten also sowohl Verzeichnis als auch Dateirechte so gesetzt werden, dass nur der eigene Benutzer darauf lesend Zugriff hat.
Leider ist es aus der Sicherheitssicht nicht mit dem Einschalten der Verschlüsselung getan. Damit HTTPS auch wirklich sicher betrieben wird, sind weitere Einstellungen nötig. Eine gute Zusammenfassung dazu findet sich in den Empfehlungen von Mozilla.
Let’s Encrypt bietet eine tolle Möglichkeit für alle Webseitenbetreiber, die eigene Seite kostenlos im Internet verschlüsselt anzubieten. Mit Hilfe des acme_tiny Programms und den kleinen Shell-Skript ist die Erneuerung komplett automatisiert möglich und bedarf keiner weiteren Pflege.
Update Mai 2016: Der EFF Certbot bietet nun auch eine recht einfache Möglichkeit an, die Zertifikate automatisch zu erstellen und zu verlängern. Wer sich also nicht mit acme_tiny spielen will, dem sei diese Variante ans Herz gelegt.
Funktioniert mittlerweile auch für IDN Domains und für Umlautdomain.
Hi,
vielen Dank für die tolle Anleitung. Nur eins ist mir aufgefallen: Müsste es in dem Automatisierungsscript am Ende
cat /tmp/signed.crt intermediate.pem > /etc/ssl/certs/einbeispiel.crt
nicht so heißen
cat /tmp/signed.crt intermediate.pem > /etc/ssl/certs/einbeispiel.pem
?
Im Apache ist ja nur .pem hinterlegt.
Gruß
Florian
Hallo Florian,
vielen Dank für dein Feedback. crt/pem sind inhaltlich gleich, es ist also nur eine Dateierweiterung. Du kannst also natürlich auch .pem als Erweiterung nutzen.
Ich würde übrigens wie im Update beschrieben den Certbot (https://certbot.eff.org/) als Automatisierung fürs Let’s Encrypt empfehlen.
Viele Grüße
Dieter