DecaTec

Home-Server | Linux | Nextcloud | Raspberry Pi | Programmierung | Fotografie

RSA und ECDSA-Zertifikate mit nginx (Hybrid-Lösung)

Let's Encrypt Logo

Wer Webdienste wie Nextcloud betreibt, der sollte auf jeden Fall sicher stellen, dass die Verbindung zum Server stets mittels HTTPS verschlüsselt ist. Damit dies funktioniert, benötigt man ein TLS-Zertifikat. Dank Let’s Encrypt kann man solche Zertifikate kostenlos beziehen und die Generierung geht leicht von der Hand.

Zum Thema TLS-Zertifikate und v.a. auch Let’s Encrypt sind hier im Blog schon einige Beiträge veröffentlicht worden. Heute soll es um eine spezielle Optimierung gehen:

RSA und ECDSA-Zertifikate im Hybrid-Betrieb mit dem Webserver nginx. Damit kommen moderne Zertifikate (ECDSA) zum Einsatz und gleichzeitig wird die Kompatibilität zu älteren Clients mittels RSA-Zertifikaten sicher gestellt.

Update-Historie (letztes Update 18.05.2019)
  • 18.05.2019:
    • Hinweis hinzugefügt, dass bei der Generierung der Zertifikate am besten Copy&Paste und „Suchen & Ersetzen“ genutzt wird.

 

Ein kleiner Ausflug in die Kryptografie

Zunächst soll erst einmal mit einfachen Worten geklärt werden, was sich hinter RSA bzw. ECDSA verbirgt.

Ohne nun zu weit in die Theorie abzuschweifen, sind beides asymmetrische kryptografische Verfahren, die zum Verschlüsseln, also auch zum digitalen Signieren genutzt werden. Dabei wird ein Schlüsselpaar bestehend aus einem öffentlichen und einem privaten Schlüssel genutzt. Ganz allgemein ausgedrückt können mittels des öffentlichen Schlüssels Nachrichten verschlüsselt werden, die nur mit dem privaten Key wieder entschlüsselt werden können.
Ein Anwendungsgebiet ist dabei die Kommunikation über HTTPS: Der öffentliche Schlüssel ist im Zertifikat enthalten, so dass ein Client (z.B. Browser) damit eine Nachricht verschlüsseln kann. Der private Schlüssel ist nur dem Webserver bekannt, so dass nur dieser die HTTPS-Nachrichten entschlüsseln kann.

RSA ist dabei das ältere Verfahren, welches schon in den 1970er Jahren zum Einsatz kam. Für die Sicherheit spielt hier die Schlüssellänge eine entscheidende Rolle. Momentan werden meist Schlüssellängen von 4096 empfohlen. Dennoch wird sich das vermutlich in Zukunft ändern, da immer leistungsstärkere Rechner zum Einsatz kommen, mit dem eine solche Verschlüsselung irgendwann geknackt werden kann. Hier helfen dann nur längere Schlüssel, da zum Ver- und Entschlüsseln mehr Rechenleistung benötigt wird, je länger der verwendete Schlüssel ist.

ECDSA ist ein neueres asymmetrisches Verfahren, welches auf elliptischen Kurven basiert. Der Vorteil bei ECDSA ist, dass sehr viel kürzere Schlüssellängen (bei gleicher oder gar besserer Sicherheit) zum Einsatz kommen können. So entspricht eine Schlüssellänge von 384 Bit bei ECDSA einer Schlüssellänge von 7680 bei RSA (siehe OpenSSL Wiki).

Ich möchte hier nun nicht weiter auf die technischen/mathematischen Details beider Krypto-Verfahren eingehen. Wer es genau wissen möchte, findet in den entsprechenden Artikeln bei Wikipedia genug Informationen.

Zusammengefasst kann man sagen, dass ECDSA-Zertifikate effizienter sind als RSA-Zertifikate, da durch eine kürzere Schlüssellänge weniger Rechenleistung für die Ver- und Entschlüsselung benötigt werden.

Warum sollte man nun RSA- und ECDSA-Zertifikate parallel einsetzen? Dies liegt darin begründet, dass ECDSA das neuere Verfahren ist, welches gerade von älteren Clients nicht immer unterstützt wird. Das ECDSA-Zertifikat sollte bevorzugt zum Einsatz kommen. Falls jedoch ein Client ECDSA nicht unterstützt, kommt das RSA-Zertifikat sozusagen als Fallback zum Zug.

Voraussetzungen

In diesem Artikel liegt der Fokus nur auf der Erzeugung der passenden Zertifikate und deren Einbindung in nginx. Damit das Ganze funktioniert, müssen ein paar Voraussetzungen erfüllt sein:

  • Es muss eine Domain vorhanden sein (Let’s Encrypt kann Zertifikat nur auf Domains, nicht jedoch auf IP-Adressen ausstellen). Im Heim-Bereich wird dies in den meisten Fällen eine DynDNS-Adresse sein, unter der der eigene Router aus dem Internet erreichbar ist. In diesem Artikel wird dazu beispielhaft die Domain meinedomain.de verwendet.
  • Der Router muss in diesem Fall so konfiguriert sein, dass ein Portweiterleitung für die Ports 80 und 443 für die Maschine eingerichtet ist, auf der der Webserver läuft.
  • Webserver: nginx (ab Version 1.11.0)
  • Ein Let’s Encrypt Client, der sowohl RSA-, als auch ECDSA-Zertifikate unterstützt. Ich empfehle hier den Client acme.sh.
  • Der Webserver muss bereits so eingerichtet sein, dass Zertifikate von Let’s Encrypt bezogen werden können. Dazu müssen Verbindungen über Port 80 zur URL http://meinedomain.de/.wellknown/acmechallenge möglich sein.

Details zur möglichen Einrichtung des Webservers und der Verwendung des Let’s Encrypt Clients acme.sh sind im Artikel Let’s Encrypt Zertifikate mit acme.sh und nginx zu finden.

Generierung der Zertifikate

Wenn alle Voraussetzungen erfüllt sind, dann kann es an die Generierung der Zertifikate gehen.

Da zwei unterschiedliche kryptografische Verfahren für die Zertifikate zum Einsatz kommen, müssen dementsprechend auch zwei Zertifikate getrennt voneinander erzeugt werden.

RSA-Zertifikate

Als erstes kümmern wir uns um das „klassische“ RSA-Zertifikat. Dieses kann mittels acme.sh durch folgenden beispielhaften Befehl erstellt werden.
Tipp: Am besten übernimmt man den Befehl mittels Copy&Paste in einen beliebigen Text-Editor, mit dem man dann die Domain mit „Suchen und Ersetzen“ einfach durch die tatsächlich verwendete Domain einfügt. Auf diese Weise kann man Tippfehler vermeiden.

Durch die Angabe --keylength 4096 wird ein RSA-Zertifikat mit der Schlüssellänge von 4096 Bit erzeugt.

Wenn die Konfiguration des Webservers passt, sollte das Zertifikat nach wenigen Augenblicken generiert worden sein.

ECDSA-Zertifikate

Der zweite Schritt ist nun die Erzeugung des ECDSA-Zertifikats. Auch hier nutzen wir wieder den beispielhaften Befehl:

Dieser Befehl sieht eigentlich genau so aus wie der vorhergehende. Lediglich über den Parameter --keylength ec-384 wird angegeben, dass diesmal ein ECDSA-Zertifikat (384 Bit) angefordert wird.

Zertifikate einbinden

Wenn die Zertifikate ohne Fehler erzeugt wurden, können diese anschließend in der Webserver-Konfiguration eingebunden werden. Ich lagere dabei alle SSL-spezifischen Einstellungen immer in eine gesonderte Datei aus. Dies ist kein Muss, sondern dient nur der besseren Übersichtlichkeit.

Hier der gesamte Inhalt:

Wichtig für die Kombination RSA/ECDSA-Zertifikate sind hier besonders folgende Einstellungen:

  • Zunächst werden mit ssl_certificate und ssl_certificate_key die Zertifikate eingebunden. Diese Anweisungen sind doppelt (einmal für RSA, einmal für ECDSA) aufgeführt, da wir ja auch zwei Zertifikate parallel einbinden wollen.
  • Welches Zertifikat vorzugsweise zum Einsatz kommt, wird durch die ssl_ciphers gesteuert: Dadurch, dass die Ciphers ECDHE-ECDSA-CHACHA20-POLY1305 (speziell für ECDSA) am Anfang aufgeführt sind, wird erst mal versucht, damit eine Verbindung aufzubauen. Wenn das klappt, kommt automatisch das ECDSA-Zertifikat zum Einsatz. Falls das nicht klappen sollte, kommen die anderen Ciphers (und damit das RSA-Zertifikat) zum Zug. Dadurch haben wir einen effizienten Fallback-Mechanismus, falls z.B. der Client keine ECDSA-Zertifikate unterstützt.
  • Alle anderen Einstellungen bzgl. SSL sind nicht spezifisch für RSA/ECDSA und sind hier einfach nur für maximale Sicherheit ausgelegt.

Die Datei mit den SSL-spezifischen Einstellungen kann dann in den virtuellen Hosts von nginx durch eine einzige Zeile eingebunden werden (im server-Block für den HTTPS-Server):

Nach der Durchführung der Änderungen muss der Webserver natürlich noch neu gestartet werden:

Hier sollten keine Fehler auftreten. Falls doch, liegt vermutlich in der Konfiguration noch ein Fehler vor. Um das genaue Problem zu ermitteln, hilft in diesem Fall folgender Befehl, der die genaue Zeile in den vHosts anzeigen sollte, wo die Ursache des Fehlers zu finden ist:

Wenn alles geklappt hat, läuft nginx im „Zerifikat-Hybrid-Betieb“ und wir können uns ansehen, wie sich das in der Praxis auswirkt.

Test der Zertifikate

Zum Testen der Zertifikate nutze ich immer gern den SSL-Test von Qualys SSL Labs. Hier sollte zunächst einmal ein A+ Rating erzielt werden können (inkl. 100% bei allen Kategorien). Das wäre aber auch mit einem reinen RSA-Zertifikat möglich. Durch das zusätzliche ECDSA-Zertifikat sollte der Test nun allerdings zwei Zertifikate anzeigen: Ein RSA-Zertifikat mit der Schlüssellänge von 4096 Bit und ein ECDSA-Zertifikat mit der Schlüssellänge von 384 Bit.

Beim SSL-Test werden zwei Zertifikate angezeigt (RSA und ECDSA)

Beim SSL-Test werden zwei Zertifikate angezeigt (RSA und ECDSA)

Falls beim SSL-Test kein A+ Rating erreicht wurde, sollten nochmals die SSL-Einstellungen des Webservers überprüft werden.

Auch im Browser (z.B. Firefox) sollte man nun bei den Details zum verwendeten Zertifikat sehen, dass ein ECDSA-Zertifikat zum Einsatz kommt.

Firefox nutzt nun automatisch das ECDSA-Zertifikat

Firefox nutzt nun automatisch das ECDSA-Zertifikat

Welches Zertifikat genutzt wird, lässt sich übrigens Client-seitig nicht festlegen. Der Client wird hier immer den ersten SSL-Cipher nehmen, mit dem er kompatibel ist. ECDSA wird hier vom Webserver bevorzugt behandelt, da die entsprechenden Ciphers am Anfang der Cipher-Liste aufgeführt sind.

Fazit

Der Artikel hat gezeigt, wie man mit dem Webserver nginx auf einfache Weise RSA- und ECDSA-Zertifikate im Hybrid-Betrieb installieren kann.

Was bringt das nun? In der Praxis wird man hier kaum einen Unterschied feststellen können, ob nun ein (traditionelles) RSA-, oder ein (moderneres) ECDSA-Zertifikat zum Einsatz kommt. Trotzdem ist bei einem ECDSA-Zertifikat weniger Rechenleistung für die Ver- und Entschlüsselung notwendig.

Durch den allgemeinen Anstieg der Leistung moderner Rechner ist zu erwarten, dass immer längere Schlüssel für TLS-Zertifikate benötigt werden – vielleicht ist hier in Zukunft ein RSA-Zertifikat mit 4096 Bit auch schon nicht mehr ausreichend. Mit dem Hybrid-Betrieb RSA/ECDSA ist man auf jeden Fall mit einem modernen Schlüsselaustausch (ECDSA) bestens für die Zukunft gerüstet, währenddessen der Einsatz von RSA die Kompatibilität mit älteren Clients sicherstellt.

Weiterführende Artikel

Links

, , , , , , , , , , , , ,

Kommentare: 11

  • Hans sagt:

    Hallo Jan,

    wieder klasse Artikel.

    Vielen Dank dafür.

    Gruß Hans

  • Markus sagt:

    Hi Jan,

    von mir auch einen herzlichen Dank für den Artikel.

    Ich hatte gedacht ich komme jetzt mit ECDSA-Zertifikaten auf SSL Labs auf 100% (wie es bei Dir ja der Fall ist) und habe nginx dementsprechend nach deiner Anleitung umgestellt.

    Jedoch komme ich bei SSL Labs unter Cipher Strength nur auf 90%.
    Bei Key Exchange bekomme ich nur 100% wenn ich die prime256v1 Kurve nicht benutze.

    Ich kenne mich leider zu wenig mit der ganzen Zertifikat Sache aus, aber mir kommt es so vor als würde es an TLSv1.3 liegen, was bei dir ja anscheinend nicht zum Einsatz kommt. -Warum eigentlich nicht? Aus diesem Grund?

    Kannst du mir einen Tipp geben wie ich mit aktivem TLSv1.3 auf 100% Cipher Strength kommen kann.

    Grüße
    Markus

    • Jan sagt:

      Hi Markus,

      schicke mir doch mal bitte deine konkrete Domain per Mail, dann kann ich das genauer analysieren.

      Genau, ich nutze (noch) kein TLSv1.3. Der Grund dafür ist recht einfach: Mit Ubuntu 18.04 kommt noch eine zu alte OpenSSL-Version zum Einsatz. Erst ab Version 1.1.1 wird hier TLSv1.3 unterstützt. Das wird vermutlich erst in Zukunft unter 18.04 verfügbar. Wenn das mal so weit ist, dann werden auch noch Änderungen an den SSL-Ciphers notwendig sein. Ich werde hier sicherlich im Blog berichten und die Artikel dementsprechend anpassen.

      Aber auch wenn „nur“ TLSv1.2 zum Einsatz kommt, sollte ein A+ Rating möglich sein.

      Gruß,
      Jan

  • Frank sagt:

    Hi Jan,

    danke für das tolle Tutorial. Ich nutze auf meinem Server mehrere subdomains jeweils mit einer eigenen aber identischen configuration. In all diesen Konfigurationen habe ich jeweils die Ordner für die Certificate entsprechend der Domain bzw. dem richtigen Ort der Zertifikate abgelegt.

    Nun erreiche ich bei SSL Labs 100% und ein A+ für alle meine subdomains nur wird komischerweise neben dem RSA als auch ECDSA Zertifkat für die richtige Domain auch immer das RSA einer spezifische subdomain angezeigt. Komischerweise das aus der ersten Konfig.

    Beispiel:

    subdomain1.example.com
    subdomain2.example.com
    subdomain3.example.com

    Wenn ich den SSL test für subdomain3.example.com durchführe zeigt er das RSA als auch ECDSA Zertifikat für subdomain3.example.com an aber auch das RSA für subdomain1.example.com. Das gleiche für subdomain2.example.com

    Weiß jemand woran das liegt?

    • Jan sagt:

      Hi Frank,

      sehe ich das richtig, dass beim SSL-Test immer drei Zertifikate angezeigt werden (also neben „Certificate #1: RSA 4096 bits (SHA256withRSA)“ und „Certificate #2: EC 384 bits (SHA256withRSA)“ immer noch ein drittes)?
      Das ist in der Tat seltsam.
      Wie hast du die Zertifikate erzeugt? Ich verwende bei mehreren Subdomains, die am gleichen DynDNS-Anschluss „hängen“ immer nur ein Zertifikat. Beim Erzeugen gibst du dann einfach in einem Befehl alle Subdomains an (immer mit dem Parameter „-d“). Also z.B.:
      acme.sh --issue -d sub1.meinedomain.de -d sub2.meinedomain.de --keylength 4096 -w /var/www/letsencrypt --key-file /etc/letsencrypt/meinedomain.de/rsa/key.pem --ca-file /etc/letsencrypt/meinedomain.de/rsa/ca.pem --cert-file /etc/letsencrypt/meinedomain.de/rsa/cert.pem --fullchain-file /etc/letsencrypt/meinedomain.de/rsa/fullchain.pem --reloadcmd "systemctl reload nginx.service"
      Das gleiche natürlich nochmal für ECDSA-Zertifikate.

      Warum bei dir nun drei Zertifikate angezeigt werden, ist mir nicht wirklich klar. Wenn du mir mal deine Domain(s) mitteilst (gern auch per Mail), dann kann ich mir das mal auf SSL-Labs genauer ansehen.

      Gruß,
      Jan

      • Frank sagt:

        Hi Jan,

        ja du hast es richtig verstanden. Genau das passiert. Erzeugt habe ich die Zertifikate alle mit den Befehlen aus deinem Beispiel. Ich hab halt für jede Subdomain das Zertifikat separat erstellt und jeweils einen eigenen Ordner wo diese abliegen.

        Aber das mit mehrere Subdomains in einem Zertifikat wusste ich nicht und ist ja genial. Das erspart mir ja die unterschiedlichen Ordner und macht die Konfiguration um einiges leichter weil ich den Abschnitt mit den Zertifikaten nun auch in das Snippet einfügen kann. Ich glaube ich werde das so einrichten. Dann sollte mein Problem mit dem 3ten Zertifikat hinfällig sein.

        Gruß und Danke
        Frank

  • Bernd sagt:

    Hallo Jan,

    ich habe es ja schon einmal unter die N-Cloud Installationsanleitung geschrieben. – Ich bekomme es einfach nicht hin :D

    Die Zertifikate werde beide Problemlos erstellt, aber ich bekomme diese nicht eingebunden ohne das Nginx rebelliert.

    Gibt es in diesem Zusammenhang ein Update für die bestehende Anleitung? :D „ganzlieb guggt“

    Vielen Dank

    Gruß Bernd

    • Jan sagt:

      Hi Bernd,

      was sagt denn „nginx -t“?
      Wenn das alles nichts hilft, dann schick mir doch mal bitte deine vHosts gezippt per Mail mit der Info, wo sich die Zertifikate bei dir im Dateisystem befinden. Dann schaue ich die Tage mal drüber.

      Gruß,
      Jan

Schreibe einen Kommentar

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