DecaTec

Programmieren, Fotografie, Home-Server und einiges mehr

HTTPS für alle: SSL-Zertifikate mit Let’s Encrypt und nginx

Let's Encrypt LogoSeit Anfang Dezember befindet sich das Projekt Let’s Encrypt in der öffentlichen Beta-Phase. Hiermit können TLS-/SSL-Zertifikate für eigene Domains erstellt werden. Ziel des Projekts ist ein möglichst einfacher und automatisierter Prozess für die Ausstellung von Zertifikaten, so dass Verschlüsselung im Web sich als Normalfall durchsetzen soll.

Der Vorteil für den Betreiber eines Servers ist dabei v.a., dass diese Zertifikate komplett kostenlos sind und dennoch alle gängigen Browser diese als vertrauenswürdig einstufen, d.h. keine für den User abschreckenden Warnungen mehr ausgegeben werden, was bei selbst signierten Zertifikaten immer ein Problem darstellt.

Der folgende Artikel zeigt, wie man mit Let’s Encrypt ein SSL-Zertifikat für den Webserver nginx erzeugt und einbindet.

Update 19.01.2016: Informationen bzgl. Let’s Encrypt in Verbindung mit DynDNS hinzugefügt.

Ausführung über virtuelle Maschine

Der Let’s Encrypt Client hat zwei Eigenschaften, die schon auf Kritik gestoßen sind: Zunächst ist dieser in Python geschrieben und zweitens erfordert die Ausführung Admin-Rechte. Daher muss zunächst einmal eine Python-Umgebung installiert sein. Wer einen Webserver betreibt, möchte diesen Overhead oftmals vermeiden. Die benötigten Admin-Rechte sind u.a. damit zu erklären, dass die Zertifikat-Dateien in einem Verzeichnis unter /etc gespeichert werden – ohne Admin-Rechte ist hier kein schreibender Zugriff möglich. Trotzdem wird häufig kritisiert, dass für die Generierung von ein paar Dateien eigentlich keine Admin-Rechte benötigt werden sollten.

Ebenfalls ist die Unterstützung von nginx durch den Let’s Encrypt Client momentan noch als experimentell anzusehen. Hier sind also Unwegbarkeiten nicht auszuschließen.

Aus diesen Gründen habe ich mich für einen alternativen und vielleicht auch etwas ungewöhnlichen Weg entschieden: Der Let’s Encrypt Client wird auf einer virtuellen Maschine ausgeführt, die vom eigentlichen Webserver vollkommen getrennt läuft. Gerade weil sich das Projekt noch in der Beta-Phase befindet, hat man auf diese Weise das kleinste Risiko.
Sobald Let’s Encrypt die Beta-Phase hinter sich gelassen hat und Pakete für die Debian-Paketverwaltung bereitstehen, wird sich das empfohlene Vorgehen wahrscheinlich ändern. Ein entsprechender Blog-Beitrag wird dann folgen.

Im Artikel ist die Rede von der virtuellen Maschine (VM), wenn Schritte beschrieben werden, die auf dem Rechner ausgeführt werden, auf dem Let’s Encrypt installiert wird. Dagegen bezeichnet Webserver den Rechner, auf dem der eigentliche Webserver (nginx) installiert ist.

Installation Let’s Encrypt

Zunächst wird der Client auf der virtuellen Maschine installiert. Als Basis dient hier eine beliebige Linux-VM. Ich selbst benutze hier einen Ubuntu Server, der mittels Hyper-V virtualisiert wurde (siehe Ubuntu Server als Hyper-V Gastsystem installieren und optimal einrichten). Der Let’s Encrypt Client kommt nicht als Paket, sondern muss aus einem GitHub-Repository heruntergeladen werden. Dazu benötigen wir zunächst einmal git. Auf einem Ubuntu Server ist git bereits im Lieferumfang dabei, ansonsten muss es manuell installiert werden:

Danach folgt der Download von Let’s Encrypt:

Aufruf Let’s Encrypt

Wie bereits erwähnt, benötigt die Ausführung des Clients Admin-Rechte. In meinem Fall reichte hier eine normales sudo allerdings nicht aus, das Programm gab daraufhin Warnungen aus.

Let's Encrypt: Warnung auf Grund fehlender Berechtigungen

Let’s Encrypt: Warnung auf Grund fehlender Berechtigungen

Anscheinend wurde hier lediglich ein Cache-Mechanismus deaktiviert, weil der (sudo-)User keinen Zugriff auf das aufgeführte Verzeichnis hat. Allerdings bekommt man auch gleich eine Lösung des Problems präsentiert.

Also erfolgt der Aufruf nun folgendermaßen (immer noch auf der virtuellen Maschine):

Die Parameter beim Programmaufruf bewirken folgendes:

  • certonly: Es wird lediglich das Zertifikat generiert. Ein evtl. laufender Webserver (nginx, Apache) wird dabei nicht verändert/beeinträchtigt.
  • -a manual: Die Validierung muss hier manuell durchgeführt werden. certonly und -a manual sind in unserem Fall zwingend erforderlich, da das Zertifikat auf einer anderen (vom Webserver getrennten) Maschine erzeugt werden sollen.
  • –rsa-key-size 4096: Erzwingt die Erzeugung eines 4096 Bit RSA-Keys (Standard: 2048 Bit). Man beachte die doppelten Striche („-„) bei diesem Parameter.

Nach Absetzen des Befehls werden evtl. noch fehlende Pakete (Python) heruntergeladen und installiert.
Zunächst fragt der Client nach einer E-Mail-Adresse und man muss den Nutzungsbedingungen zustimmen.
Anschließend erfolgt die Eingabe der Domain, für die das Zertifikat ausgestellt werden soll (in diesem Beispiel meinedomain.de). Hier können auch gleich mehrere Domains angegeben werden (durch Kommata oder Leerzeichen getrennt). Dies empfiehlt sich, wenn die Website z.B. sowohl unter meinedomain.de, als auch www.meinedomain.de verfügbar ist.

Angabe einer Domain

Angabe einer Domain

Let’s Encrypt loggt die IP Adressen mit, die für die Zertifikat-Generierung verwendet werden. Im nächsten Schritt muss man diesem Vorgehen zustimmen.

Nun folgt ein Wichtiger Schritt: Let’s Encrypt überprüft nun, ob der Webserver auch unter der Kontrolle des Nutzers steht. Dazu erwartet der Client eine bestimmte Datei mit einem genau definierten Inhalt an einer spezifischen URL, die im Folgenden angezeigt wird.

Informationen zu der Datei, die auf dem Webserver verfügbar sein muss

Informationen zu der Datei, die auf dem Webserver verfügbar sein muss

Um diese Datei bereit zu stellen, müssen wir auf den Webserver wechseln. Dafür lassen wir den Let’s Encrypt Client auf der VM einfach weiterlaufen.

Anlegen der Verifikations-Datei auf dem Webserver

Zunächst muss die nginx Config-Datei des entsprechenden Servers bearbeitet werden, der für meinedomain.de zuständig ist:

Hier fügen wir folgende Anweisungen hinzu (direkt im Server-Block):

Dies sorgt zum einen dafür, dass unter meinedomain.de/.well-known/acme-challenge nur die reine Text-Datei ausliefert (text/plain). Zum anderen geben wir hier das Verzeichnis an, in dem die Verifikations-Datei auf der lokalen Festplatte erzeugt werden muss.
Der zweite location-Block sorgt dafür, dass ansonsten keine Dateien unter /.well-known/acme-challenge ausgeliefert werden.

Also legen wir im nächsten Schritt die von Let’s Encrypt geforderte Datei an. Zu beachten ist hier, dass Name und Inhalt der Datei dabei immer ein anderer ist (pro Aufruf von Let’s Encrypt):

Danach wird nginx neu gestartet:

Nun empfehle ich, die von Let’s Encrypt geforderte URL einmal im Browser aufzurufen. Dadurch kann zunächst getestet werden, ob das Anlegen der Datei geklappt hat und der Webserver diese auch im entsprechenden Format ausliefert. Falls es hier zu Problemen kommt, hilft meinst ein Blick in das nginx-Error-Log (/var/log/nginx/nginx_error.log).

Wenn der Aufruf im Browser geklappt hat, kann wieder auf die virtuelle Maschine gewechselt werden, auf der Let’s Encrypt noch immer läuft.

Zurück auf die virtuelle Maschine

Hier wird nun mit Enter bestätigt, dass die von Let’s Encrypt erwartete Datei zur Verfügung steht. Let’s Encrypt überprüft nun diese Datei und fährt mit der nächsten Domain fort. Dazu muss das oben beschriebene Vorgehen mit einer weiteren Verifikations-Datei wiederholt werden.

Wenn der Vorgang abgeschlossen ist, sind die erzeugten Zertifikat-Dateien nun unter /etc/letsencrypt/live/<domain> (auf der virtuellen Maschine) zu finden:

  • cert.pem: Das öffentliche Zertifikat in Reinform
  • chain.pem: Öffentliches Zertifikat aus der sog. Keychain
  • fullchain.pem: entspricht cert.pem + chain.pem
  • privkey.pem: Privates Zertifikat

Damit der Server das Zertifikat nun verwenden kann, müssen diese Dateien noch auf den Webserver kopiert werden. In diesem Beispiel nutze ich hierfür ein temporär gemountetes Verzeichnis, auf welche sowohl die VM, als auch der Server Zugriff haben:

Nach dem Kopieren der Zertifikat-Dateien ist die Arbeit auf der virtuellen Maschine abgeschlossen.

Zertifikate auf dem Webserver einbinden

Auf dem Webserver kopieren wir die Zertifikate nun an die bekannte Stelle:

Anschließend wird wieder die nginx-Konfiguration der entsprechenden Seite bearbeitet:

Hier fügen wir den Pfad zu den Zertifikaten in den server-Block ein, der für HTTPS zuständig ist:

Wichtig ist dabei, dass unter ssl_certifikate die fullchain.pem und unter ssl_certificate_key der private Schlüssel (privkey.pem) angegeben wird.

Nun können wir auch gleich die location-Blöcke aus der Config auskommentieren, die wir für die Erzeugung der Zertifikate angelegt hatten (optional). Die kryptischen Dateien, die zur Verifikation der Domain erzeugt wurden, können nun auch gelöscht werden:

Abgeschlossen wird die Konfiguration, indem sichere Dateiberechtigungen gesetzt werden:

Wichtig: Das Zertifikat (v.a. der private Schlüssel) ist schützenswert, d.h. man sollte die privkey.pem niemals weitergeben und sicher verwahren.

Ebenfalls zu beachten: Die über Let’s Encrypt ausgestellten Zertifikate sind für einen Zeitraum von 90 Tagen gültig. Vor Ablauf der Gültigkeit muss das Zertifikat erneuert werden. Dazu wird das in diesem Artikel gezeigte Vorgehen einfach wiederholt. Verliert das Zertifikat seine Gültigkeit und wurde nicht erneuert, wird eine entsprechende Warnung im Browser angezeigt.

Let’s Encrypt mit DynDNS

Noch ein Wort zu Let’s Encrypt in Verbindung mit DynDNS: Prinzipiell funktioniert Let’s Encrypt auch mit DynDNS-Domains. Allerdings gibt es in der Beta-Phase Limits, wie viele Zertifikate für eine Domain/von einer IP aus ausgestellt werden können (siehe Let’s Encrypt Quick Start Guide):

  • Pro IP-Adresse: 10 in 3 Stunden
  • Pro Domain: 5 innerhalb von 7 Tagen

Auf Grund dieser Limits kann das Ausstellen eines Zertifikats für einen DynDNS-Domain durchaus funktionieren, aber die Wahrscheinlichkeit ist recht hoch, dass dies fehlschlägt, wenn bereits zu viele Leute Zertifikate für eine die DynDNS-Second-Level-Domain erzeugt haben. In einem solchen Fall erhält man dann eine Fehlermeldung: Too many certificates already issued for: domain.tld.
Auch wenn ein Zertifikat für eine DynDNS-Domain erfolgreich erstellt wurde – das Zertifikat muss nach Ablauf der Gültigkeit von 90 Tagen erneuert werden. Hier kann das Problem jederzeit wieder auftreten.

Auf der sicheren Seite ist man hier nur mit einer eigenen (Second-Level-)Domain. Diese kostet nur ein paar Euro im Jahr und kann bei jedem Webhoster bestellt werden (empfehlen kann ich hier All-Inkl.com).

Der Trick ist nun, den CNAME-Eintrag der eigenen Domain auf die DynDNS-Domain zu setzen. Hiermit wird ein alternativer Name (die eigene Domain) für die DynDNS-Domain festgelegt. Das Let’s Encrypt Zertifikat wird dann auf die eigene Domain ausgestellt. Auf diese Weise hat man nicht nur seine eigene Domain, sondern umgeht die Problematik, wenn bereits zu viele Zertifikate für eine DynDNS-Second-Level-Domain ausgestellt wurden, da die DynDNS-Domain beim Zugriff auf die Website nicht mehr in Erscheinung tritt.

Let’s Encrypt immer noch in der Beta-Phase

Das beschriebene Vorgehen zum Erzeugen von SSL/TLS-Zertifikaten funktioniert recht reibungslos. Dennoch sollte man beachten, dass sich das Projekt Let’s Encrypt noch in der Beta-Phase befindet. Dadurch kann sich in Zukunft noch einiges am Client oder auch an der Vorgehensweise zur Zertifikat-Generierung ändern.

Im Moment ist das Projekt meiner Meinung nach eher etwas für die Early Adopter und technisch versierten Anwender. Massentauglich wird das Projekt wohl erst, wenn die Beta-Phase abgeschlossen wurde und Pakete in den offiziellen Repositories zu finden sind.

Mit ein wenig Aufwand ist es allerdings jetzt schon möglich, dass sich jedermann eigene (kostenlose) Zertifikate über Let’s Encrypt generieren kann, die von fast allen modernen Browsern als vertrauenswürdig eingestuft werden. Vielleicht ist dies ein wichtiger Schritt zu einem Internet, in dem Verschlüsselung der Standard ist.

Weiterführende Artikel

Links

, , , , , , , , , , ,

Kommentare: 6

  • Markus sagt:

    Guten Tag,
    eine Frage habe ich zum Thema 2nd-Level-Domain: Da Sie all-inkl.com empfehlen – ist es bei diesem Anbieter auch möglich, die DNS-Einträge entsprechend anzupassen und beim reinen Domain-Paket eigene SSL-Zertiifkate zu verwenden?
    Danke und Gruß
    Markus

    • Jan sagt:

      Hallo Markus,

      bei all-inkl.com ist es ab dem Webhosting-Paket „PrivatPlus“ möglich, DNS-Einträge zu ändern und eigene SSL-Zertifikate zu verwenden, das Paket „Privat“ reicht hier leider noch nicht (siehe Paketvergleich).
      Noch eine Anmerkung zu Let’s Encrypt bei all-inkl.com: Laut Support laufen hier z.Zt. Vorbereitungen, ein Let’s Encrypt Zertifikat per Ein-Klick-Lösung bereit zu stellen. Aus technischen Gründen ist daher der Zugriff auf die URL .well-known/acme-challenge für Endkunden nicht möglich. Folglich können Let’s Encrypt Zertifikate momentan für einen all-inkl.com Webauftritt nicht selbst erzeugt werden.
      Allerdings reicht hier eine E-Mail an den Support, dieser kann das Zertifikat für dich erzeugen und einbinden.

      Gruß,
      Jan

      • Markus sagt:

        Hallo Jan,

        vielen Dank für die schnelle Rückmeldung! 🙂

        Laut dem Paketvergleich handelt es sich hierbei schon um ein Webhosting-Paket mit 8€/Monat, das wäre mir rein für eine Domain mit SSL doch ein wenig zu viel, zumal ich die sonst gebotenen Leistungen wie Storage & Co nicht benötige. Es scheint so, als ob man für ~10 EUR/Jahr wohl doch keine Domain bekommt, mit der man auch DNS/SSL konfigurieren kann, oder hast du zufällig noch einen Tipp/Anbieter dazu? 😉

        Vielen Dank vorab!

        Gruß
        Markus

        • Jan sagt:

          Hallo Markus,

          wenn du bei all-inkl.com eine Domain bestellst, hast du wohl auch Zugriff auf die DNS-Einstellungen (siehe hier).
          Die Eigenschaft „SSL“ hängt allerdings nicht von der Domain oder deren Anbieter ab. Dies ist allein Aufgabe des Webservers. Angenommen du hast eine Domain, die per CNAME auf eine DynDNS-Adresse verweist, hinter der wiederum dein eigener Webserver hängt (z.B. auf einem Raspberry). Dann wird das SSL-Zertifikat auf deine Domain ausgestellt, einbinden musst du das allerdings in deiner Webserver-Konfiguration. Die Domain selbst hat damit nichts zu tun.

          Gruß,
          Jan

          • Markus sagt:

            Hi Jan,

            verstehe, ich dachte bisher nämlich, dass ich das Zertifikat über das Admin-Panel des Anbieters importieren muss. Demnach ist auch sichergestellt, dass der User durchgehend die Original-Domain im Browser angezeigt bekommt und niemals die dahinterliegende DDNS-Adresse, richtig?

            Das klingt schon deutlich besser … 🙂

            Danke für all Deine Infos, sie haben mir sehr weitergeholfen!

            Viele Grüße,
            Markus

          • Jan sagt:

            Hi Markus,

            bei einem Shared Webhosting musst du in der Tat das Zertifikat im Admin-Panel des Anbieters angeben (falls diese Option überhaupt angeboten wird), da du ansonsten ja keinen direkten Zugriff auf den Webserver hast.
            Dass die DynDNS-Domain niemals direkt angezeigt wird, dafür sorgt dann einzig und allein der CNAME-Eintrag deiner (Haupt-)Domain. Natürlich dürfen dann auch keine Direkt-Links zur DynDNS-Adresse mehr in deinem Webangebot zu finden sein.

            Gruß,
            Jan

Schreibe einen Kommentar

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