SSL mit Perfect Forward Secrecy unter nginx

SSL ist in den letzten Tagen mal wieder in aller Munde. Dank des Heartbleed Bugs in OpenSSL ist es Angreifern möglich, entschlüsselte Informationen oder sogar den privaten Schlüssel des Zertifikats aus dem Speicher des Webservers zu ziehen, ohne dabei Spuren zu hinterlassen. Sollte der private Schlüssel in fremde Hände gelangen, lässt sich damit einiges an Schindluder treiben. Eine Möglichkeit wäre, bereits aufgezeichnete, jedoch verschlüsselte Kommunikation, nachträglich zu entschlüsseln. Um das zu verhindern, gibt es eine Funktion die sich „Perfect Forward Secrecy“ nennt. PFS nutzt nicht das Public Key Verfahren um einen Sitzungsschlüssel zu erzeugen. Für PFS wird das Diffie-Hellman Verfahren eingesetzt. Hier wird von beiden Seiten (Client/Server) ein gemeinsamer Sitzungsschlüssel erzeugt. Wer’s gern etwas genauer wissen will, kann sich folgenden Wiki Artikel durchlesen Klick

Folgende Komponente werden für SSL mit PFS benötigt.

  • SSL Zertifikat
  • Diffie-Hellman Key für den Schlüsselaustausch
  • Webserver. Ich verwende hier nginx (nginx Website)
  • OpenSSL zur Zertifikatserstellung. Wichtig ist mind. Version 1.0.1g einzusetzen, um nicht mehr von Heartbleed betroffen zu sein. Wer mag, kann sich auch gerne seine eigene Version ohne Heartbeat Funktion kompilieren.

Um an ein eigenes SSL Zertifikat zu kommen, gibt es mehrere verschiedene Möglichkeiten. Ich beschränke mich jetzt auf die Erstellung mittels OpenSSL. Da ein selbstsigniertes Zertifikat zu Fehlern in Browsern bzw. Apps führt, ist es wichtig den öffentlichen Schlüssel auf dem Client zu importieren. Wer sowas umgehen möchte/muss, wird um einen kommerziellen Anbieter nicht rum kommen (StartSSL.com). Folgender Befehl erzeugt ein Zertifikat, welches den heutigen Anforderungen an „vernünftige“ Krypto gerecht wird:

  • openssl req -newkey rsa:4096 -sha512 -x509 -days 365 -nodes -out /etc/nginx/certs/cert.pem -keyout /etc/nginx/certs/cert

Das Zertifikat ist ein Jahr gültig und setzt auf RSA 4096 Bit mit SHA512 Hashalgorithmus. Um den Schlüsselaustausch zu gewährleisten, muss noch ein Diffie-Hellman Key erzeugt werden.

  • openssl dhparam -out /etc/nginx/certs/dhparam.pem 2048

Jetzt, wo alle Voraussetzungen erfüllt sind, ist der Webserver an der Reihe. Die nginx Konfigurationsdatei für einen Host liegt per Default unter

  • /etc/nginx/sites-available/default

Mit dem Editor seiner Wahl lässt sich die Datei bearbeiten. Z.B.

  • nano /etc/nginx/sites-available/default

Um PFS jetzt zu aktivieren, sind ein paar zusätzliche Parameter in der Konfigurationsdatei erforderlich. Im weiter unten folgenden Ausschnitt einer Konfigurationsdatei wird dies ersichtlich.

  • ssl_protocols: Unterstützte TLS/SSL Versionen
  • ssl_prefer_server_ciphers: Vom Server vorgegebene Cipher verwenden
  • ssl_dhparam: Pfad zum Diffie-Hellman Key 
  • ssl_ciphers: Verwendete Cipher. Ohne diese Sektion bzw. mit den falschen Werten ist PFS nicht möglich!

Ausschnitt einer nginx Konfigurationdatei:

server {
listen 443 ssl;
server_name server.example.com;
#SSL/PFS settings
ssl on;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/cert.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/certs/dhparam.pem;
ssl_ciphers HIGH:!aNULL:!MD5:!RC4;
.  
.
.
}

Um die Anpassungen scharf zu schalten, muss der Webserver neu gestartet werden:

  • systemctl restart nginx.service

Wer das Ergebnis jetzt testen möchte, kann dies bei SSL Labs tun. Dort gibt es einen sehr detaillierten Bericht mit den verwendeten Verfahren sowie über die Kompatibilität mit verschiedensten Browsern und Betriebssystemen.