https pimpen

Heute geht es ans Pimpen von https

Posted by Holm Spitzer on 3. September 2016
In Verschlüsselung, Nginx,

Wie im vorherigen Beitrag angekündigt, möchte ich nun beschreiben, wie man die Verschlüsselung pimpen kann und es somit unerwünschten Lauschern erschweren kann, ihrer Lieblingstätigkeit nachzugehen.

Für die Tests benutze ich die Seite von Qualys SSL labs.

Mit der bisherigen Konfiguration reicht es nur für die Note B.

Zuerst aktivieren wir Perfect Forward Secrecy. Damit kann aufgezeichneter verschlüsselter Verkehr nachträglich nicht entschlüsselt werden, sollte der private geheime Schlüssel mal entfleuchen. Dafür müssen wir sogenannte Diffie Hellman Parameter erzeugen. 4096 Bit lang sollten sie heutzutage schon sein und mit folgendem Befehl selbst generiert werden.


cd /usr/local/etc
openssl dhparam -out ssl/letsencrypt/holminger.de/dhparams.pem 4096

Während die Parameter generiert werden, können wir schon nginx vorbereiten. Dazu fügen wir folgende Zeile in den server block für https der nginx.conf ein:


ssl_dhparam /usr/local/etc/ssl/letsencrypt/playground.holminger.de/dhparams.pem;
ssl_ecdh_curve secp384r1;

Ich habe sie hinter die Definitionen der Dateien für das Zertifikat und des geheimen Schlüssels gepackt, der Ordnung halber. Die zweite Zeile setzt die Länge der DH Parameter für eliptic curve Verschlüsselungsalgorithmen (EC) auf 384 Bit.

Als nächstes habe ich OCSP stapling aktiviert. Damit kann der Client die Gültigkeit des Zertifikats überprüfen, ohne die Certificate Authority (CA) selber kontaktieren zu müssen. Das macht unser Webserver nun, um die CA zu entlassten und damit einen möglichen Timeout zuverhindern. Ein Browser wartet nur eine bestimmte Zeit. Erhält er keine Antwort von der CA, geht er davon aus, dass das Zertifikat weiterhin gültig ist. Das muss natürlich längst nicht mehr der Fall sein. Außerdem verhindern wir mit OCSP stapling, dass bei einem Client Request die CA die IP-Adresse unseres Besuchers bekommt. Das Ergebnis wird für ca. eine Stunde gecachet. Wir müssen ein Zertifikat angeben, dem der Client vertrauen muss, das ist das CA Bundle, das wir bekommen haben.


ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate      /usr/local/etc/ssl/letsencrypt/holminger.de/fullchain.pem;

Im nächsten Schritt aktivieren wir den Strict Transport Security Header (HSTS). Bitte darauf achten, dass dieser Header nur über https gesendet wird, also nur im server-Block für https auftaucht, andernfalls ist dies der berühmte Schuss in den Fuß, wir katapultieren uns selber aus dem Internet. ;-(


add_header Strict-Transport-Security “max-age=15552000; includeSubDomains;”;

Damit wird dem Browser mitgeteilt, dass er für das nächste halbe Jahr die Seite nur per https besuchen soll und dies auch für alle Subdomains gilt.

Als vorläufig letzten Schritt aktivieren wir das HTTP Public Key Pinning (HPKP). Ich bin diesen HowTo’s von Scott Helme und Bjørn Johansen gefolgt und finde das Pinning des Leafs, also meines öffentlichen Schlüssels, am schlüssigsten, weil ich nur diesen unter Kontrolle habe. Gerade vor kurzem wurde auf golem.de berichtet, das letsencrypt.org es direkt in den Firefox geschafft hat und kein intermediate Zertifikat mehr benötigt. Für den Fall der Fälle, dass unser private Key kompromitiert werden sollte und wir ein neues Schlüsselpaar benötigen, generieren wir ein zusätzliches Schlüsselpaar, von dem wir ebenfalls den Hash des öffentlichen Schlüssels im HPKP Header hinterlegen. Den Backupschlüssel selber legen wir an einem wirklich sicheren Ort ab, oder noch besser, generieren ihn dort mit:


openssl genrsa 4096 >privkey.pem

Die Hashes erzeugen wir mit folgendem Kommando, einmal für unseren aktuellen Schlüssel und für unseren Backupschlüssel:


openssl rsa -in letsencrypt/holminger.de/privkey.pem -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

Den generierten Output nach ‘writing RSA key’ kopiert man und fügt ihn an Stelle von SHA256HASH bzw. SHA256HASHBCK ein, wobei SHA256HASH für den hash unseres aktuellen Schlüssels und SHA256HASHBCK für den hash unseres Backup-Schlüssels stehen:


add_header Public-Key-Pins 'pin-sha256="SHA256HASH"; pin-sha256="SHA256HASHBCK"; max-age=15552000; includeSubDomains;';

Der Parameter includeSubDomains sagt es schon, wird dieser gesetzt, dann sind nur unser aktueller öffentlicher Schlüssel und sein Backup für die Domain und alle Subdomains gültig. Hat man weitere Subdomains, die eigene Zertifikate haben sollen, dann muss includeSubDomains weggelassen werden, oder man fügt die Hashes deren öffentlicher Schlüssel in die Liste ein. Andernfalls kann es passieren, dass ein Browser die Verbindung verweigert, da der Hash des öffentlichen Schlüssels der Subdomain nicht in der Liste der gültigen Schlüsselhashes gelistet ist. Dieses Verhalten ist auch von der Reihenfolge des ersten Besuchs der Domain und der Subdomain abhängig.

Nach Speichern der Konfiguration, Neustarten des Webservers und Neustartens des Test von Qualys SSL labs für unsere Domain erhalten wir ein A+. Yeah!