Stephan Herbers

Sichere TLS Konfiguration mit NGINX

Über den Autor: Ich bin Fachinformatiker für Systemintegration. Was ich hier zusammen geschrieben habe, habe ich mir in den letzten Jahren angelesen. Ich beziehe mich bei meiner Auslegung von sicher, auf das, was von der Mehrheit (oder was ich glaube die Mehrheit zu sein) der Meinungen im IT-Sicherheits Umfeld, als sicher gilt. Wer objektiv falsche Aussagen findet, oder Fragen hat, soll sich bitte bei mir melden, damit ich das korrigieren / ergänzen kann.

Zuletzt aktualisiert: 03.02.2017

1 Grundlagen und Ressourcen

1.1 Einleitung

Diese Seite gibt eine Einführung in die sichere Einrichtung von TLS mit NGINX. Sicher heißt hier, dass nur Protokolle / Verschlüsselungsalgorithmen / Schlüsselaustausch Cipher benutzt werden, zu denen NOCH keine, ausnutzbaren, Schwachstellen bekannt sind. Die einzige Ausnahme bildet hier, die Kombination von TLS 1.0 und AES-CBC. Warum dies aber wahrscheinlich besser ist, als die Alternative, wird weiter unten erklärt.

TLS steht für Transport Layer Security. In den Konfigurationsparametern kommt noch die Abkürzung SSL (Secure Sockets Layer) vor. Der Begriff SSL ist veraltet, wird aber noch weitläufig benutzt. Das SSL Protokoll wird in der hier gezeigten Konfiguration nicht einmal mehr verwendet.

Gedacht ist die hier besprochene Konfiguration, für Leute denen die Sicherheit ihrer Besucher mehr Wert ist, als die Unterstützung von veralteten Browsern. Mit veralteten Browsern ist allerdings auch nur Internet Explorer 8 und niedriger und nur unter Windows XP gemeint. Auf solche Nutzer darf man keine Rücksicht nehmen, da dies unter Umständen die Sicherheit aller anderen Benutzer gefähren kann. Andere Browser (Desktop/Mobil) verursachen keine Probleme.

Diese Konfiguration erlaubt keine unverschlüsselten Verbindungen, da es offensichtlich die größte Schwachstelle ist, wenn der Benutzer die Möglichkeit hat über HTTP statt HTTPS zu verbinden. Selbst wenn der Benutzer selbst lieber verschlüsseln würde, kann ein Man-in-the-middle (MITM) dem Benutzer vorgaukeln, es gebe keine HTTPS Seite und dann die Verbindung abhören. HSTS kann hier nicht immer Abhilfe schaffen (Bei der ersten Verbindung zum Beispiel).

Es werden ausschließlich Cipher mit Forward Secrecy angeboten, da davon ausgegangen werden kann, dass die meisten/alle verschlüsselten Verbindungen, heutzutage für Jahre gespeichert werden. Ohne Forward Secrecy besteht dann die Gefahr, das gespeicherte Verbindungen im Nachhinein durch Erlangen des privaten Schlüssels (Einbruch in den Server / Zwang zur Herausgabe durch Ermittlungsbehörden), entschlüsselt werden können.

Es wird 256 bit Verschlüsselung bevorzugt, aber auch die 128 bit Varianten angeboten. Beides gilt nach aktuellem Stand, noch für viele Jahre als sicher. Bei privaten oder kleinen Seiten, mit wenig Besucheraufkommen, spielt der zusätzliche Rechenaufwand von 256 bit, gegenüber 128 bit, keine Rolle. Nur bei großen Seiten kann es sich für die Performance lohnen, AES 128 bit zu bevorzugen.

Es wird, wenn möglich, Elliptic Curve Cryptography (ECC) für den Schlüsselaustausch verwendet. ECC verwendet andere mathematische Verfahren als RSA und benötigt dadurch, bei vergleichbarer Sicherheit, eine kürzere Schlüssellänge. Das bringt eine deutliche Performancesteigerung beim Schlüsselaustausch. Ein 256 bit ECC Schlüssel entspricht dabei ca. einem 3072 bit RSA Schlüssel.

1.2 Mögliche Schwachstellen

BEAST: Beast ist ein Angriff auf TLS der nur im Zusammenspiel von TLS 1.0 und AES-CBC zur Gefahr werden kann. Wird TLS 1.1 oder höher verwendet ist man gegen den Angriff sicher. Weit verbreitet ist Heute noch, anstatt AES-CBC lieber RC4 einzusetzen. Da RC4 allerdings selbst schon länger nicht mehr als sicher gilt, und das in Zukunft nur schlimmer wird, ist davon stark abzuraten. Außerdem ist der Beast Angriff mittlerweile Browserseitig bei fast allen modernen Browsern gefixt worden (Siehe auch: Is beast still a threat).

Certificate authorities: Wenn man einen Aluhut auf hat, kann man auch die CAs selbst als Schwachstelle ansehen. Diese können nämlich, freiwillig oder gezwungen, zusätzliche, gültige Zertifikate, für die eigene Domain erstellen und diese an Dritte (Geheimdienste, Ermittlungsbehörden) weitergeben. Diese können zwar nicht direkt zur Entschlüsselung der Verbindung benutzt werden, Angreifer können sich aber zwischen Benutzer und Server setzen und eine Ende-zu-Ende verschlüsselte Verbindung vorgaukeln. Auch ist es möglich, und schon passiert, das in die Server der CAs eingebrochen wird und die Root Zertifikate kopiert wurden. Die Angreifer können sich dann beliebig selbst Zertifikate ausstellen. Eine Lösung des Problems kann das PKP Verfahren liefern.

1.3 SSL Labs

Die Website SSL Labs hat sich darauf spezialisiert, Informationen und Werkzeuge, zum Thema SSL/TLS zur Verfügung zu stellen. Wer seine Website verschlüsselt anbieten möchte, egal mit welchem Webserver, sollte sich vorher das PDF SSL/TLS Deployment Best Practices durchlesen. Auf knapp 10 Seiten wird das Wissen vermittelt, welches zur Bereitstellung einer sicheren SSL/TLS Verbindung benötigt wird. Im Folgenden wird bei der Erklärung der Konfiguration, nochmal das Wichtigste zusammen gefasst. Wenn der Server fertig eingerichtet ist, kann mit dem SSL Server Test überprüft werden, ob alles funktioniert; dazu weiter unten mehr.

1.4 Zertifikate

Zertifikate sollten heutzutage einen mindestens 2048 bit großen RSA Schlüssel enthalten und dieser sollte bei der Erneuerung des Zertifikates neu generiert werden. Die folgende Anleitung nutzt einen 2048 bit langen Schlüssel gibt aber auch Hinweise auf die Verwendung von 4096 bit langen Schlüsseln. Großere Schlüssel sind sicherer aber auch langsamer beim Verbindungsaufbau. Auf meinem Server kann ich mit einem 2048 bit Schlüssel ca. 6,5 mal so viele Signierungen durchführen wie mit einem 4096 bit Schlüssel.

Mit Let’s Encrypt gibt es eine CA von Mozilla, der EFF, Akamai und anderen nennenswerten Organisationen, die kostenlos Zertifikate zur Verfügung stellt. Diese CA ist vollständig automatisiert, sodass Zertifikate in weniger als einer Minuten bereitstehen. Dazu gibt es eine Vielzahl von Clients die das Ausstellen automatisieren, die Zertifikate automatisch erneuern, und sogar den Webserver konfigurieren können. Die Zertifikate von Let’s Encrypt sind für drei Monate gültig.

2 Konfiguration

Genug der Einführung, jetzt kommen wir zur Konfiguration von NGINX. Die einzelnen Komponenten der Konfiguration, werden jeweils ausführlich erklärt.

2.1 HTTP Umleitung

Zuerst werden alle Anfragen auf Port 80 (HTTP) nach Port 443 (HTTPS) umgeleitet. Oft findet man, das Konfigurationen eine rewrite Regel nutzen, anstatt return 301. Das funktiniert zwar, geht aber besser.

server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; }

Es wird für IPv4 listen 80 und für IPv6 listen [::]:80 auf Port 80 gelauscht. Der server_name gibt an, dass nur Anfragen nach example.com, von dieser Konfiguration, beantwortet werden. Dies wird benötigt, wenn man eine oder mehr Subdomains hat, die auf die selbe NGINX Instanz zeigen. return 301 ist die Umleitung auf https (Durch HTTP Status Code 301 - Moved Permanently), alle Argumente in der URL werden übergeben.

2.2 TLS und SPDY bzw. HTTP/2 aktivieren

SPDY ist das Protokol von Google das als Nachfolger von HTTP/1.1 konzipiert ist. Es ist außerdem die Grundlage für HTTP/2. SPDY steht ausschließlich für HTTPS Verbindungen zur Verfügung und benötigt keine Anpassung an der Website. SPDY beschleunigt die HTTPS Verbindung deutlich und wird von allen modernen Browsern unterstützt. NGINX unterstützt SPDY seit Version 1.3.15 in Version 2 und setzt OpenSSL 1.0.1 verraus. Seit NGINX 1.5.10 steht die aktuelle SPDY Version 3.1 bereit. Mit NGINX 1.9.5 ist das SPDY Modul durch das HTTP/2 Modul ersetzt worden. Browser die kein SDPY oder HTTP/2 sprechen, nutzen TLS über HTTP/1.1. Manchmal sieht man noch eine Kombination aus listen 443 und ssl on, dies ist veraltet und sollte nicht mehr verwendet werden.

server { # listen 443 ssl spdy; listen 443 ssl http2; # listen [::]:443 ssl spdy; listen [::]:443 ssl http2; server_name example.com; ssl_certificate /pfad/zum/zertifikat/example.com.crt; ssl_certificate_key /pfad/zum/privaten/schlüssel/private.key;

Es wird für IPv4 listen 443 ssl http2 und für IPv6 listen [::]:443 ssl http2 auf Port 443 gelauscht und TLS mit HTTP/1.1 bzw. HTTP/2 oder SPDY aktiviert. Mit ssl_certificate wird das zu benutzende Zertifikat ausgewählt. Das Zertifikat sollte alle Zwischenzertifikate beinhalten. Mit ssl_certificate_key wird der private Schlüssel ausgewählt. Er muss mindestens 2048 bit haben.

2.3 Protokolle

Alle modernen Browser sprechen TLS 1.0. SSLv3 sollte nicht mehr benutzt werden, weil Angreifer die Verbindung bis auf SSLv3 runterbiegen können. TLS 1.2 ist die neuste Version und es sind keine Schwachstellen dafür bekannt. Sobald genügend Browser TLS 1.2 können, sollten TLS 1.0 und TLS 1.1 abgeschaltet werden. TLS 1.2 wird außerdem für AES-GCM benötigt.

ssl_protocols TLSv1.2 TLSv1.1 TLSv1;

Ein einfaches ssl_protocols reicht aus, um TLS Version 1.0, 1.1 und 1.2 zu aktivieren. Diese Einstellung ist bei aktuellen NGINX Version der Standardwert.

2.4 Cipher

ssl_ciphers EECDH+AESGCM:EDH+AESGCM:EECDH:EDH:!MD5:!RC4:!LOW:!MEDIUM:!CAMELLIA:!ECDSA:!DES:!DSS:!3DES:!NULL; ssl_prefer_server_ciphers on;

Die Zeile ssl_ciphers wählt die zu benutzenden Cipher aus. Die Reihenfolge bestimmt welche zuerst versucht werden, bis eine Cipher gefunden wird, die beide Seiten sprechen. ssl_prefer_server_ciphers weißt NGINX an, zu ignorieren, welche Cipher der Browser bevorzugt, um eine möglichst starke/schnelle Cipher zu wählen. Um ECDHE zu nutzen, wird mindesten OpenSSL 1.0.0 benötigt.

Was sich inter der angegebenen dynamischen Cipherliste befindet, lässt sich wie folgt herausfinden.

openssl ciphers 'EECDH+AESGCM:EDH+AESGCM:EECDH:EDH:!MD5:!RC4:!LOW:!MEDIUM:!CAMELLIA:!ECDSA:!DES:!DSS:!3DES:!NULL'

ECDHE-RSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-SHA384
ECDHE-RSA-AES256-SHA
ECDHE-RSA-AES128-SHA256
ECDHE-RSA-AES128-SHA
DHE-RSA-AES256-SHA256
DHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA256
DHE-RSA-AES128-SHA

Beschreibung der einzelnen Buchstaben in den Cipher:

EC steht für Elliptic Curve Cryptography.
DHE steht für Diffie-Hellman-Schlüsselaustausch. Das E steht für Ephemeral (vergänglich) und gibt an das Forward Secrecy benutzt wird.
RSA steht für Rivest, Shamir und Adleman. RSA ist ein asymmetrisches, kryptographisches Verfahren zum Verschlüsseln und signieren. Wird von TLS nur zum signieren verwendet.
AES steht für Advanced Encryption Standard. AES ist eine Blockverschlüsselung, die zur tatsächlichen Verschlüsselung der Verbindung benutzt wird.
GCM ist der Galois/Counter Mode. GCM ist ein Mode für AES der die Daten verschlüsselt und gleichzeitig die Authentizität der verschlüsselten Daten gewährleistet. GCM gilt als schnell und effizient und im Gegensatz zu CBC, sind noch keine praktischen Schwachstellen bekannt.
CBC ist der Cipher Block Chaining Mode. CBC ist ein Mode für AES. Gegen CBC in Verbindung mit TLS 1.0 sind Angriffe bekannt, die aber sehr unwahrscheinlich sind.
SHA ist der Secure Hash Algorithm. SHA wird zur Integritätsprüfung der Daten benutzt.

Begründung für die Reihenfolge der Cipher

GCM ist CBC vorzuziehen, da für GCM noch keine Schwchstellen bekannt sind. Siehe dazu auch den Blogeintrag vom Google Online Secruity Team. ECDHE wird DHE aus Performancegründen vorgezogen. DHE verlangsamt den TLS Verbindungsaufbau um das dreifache, ECDHE dagegen nur um 15-27%. (Quelle).

2.5 Schlüssellänge für ECDHE und DHE vergrößern

NGINX benutzt für DHE standardmäßig einen 1024 bit langen Schlüssel. Die Schlüssellänge von DHE ist ungefähr vergleichbar mit der Schlüssellänge in RSA. Da wir einen mindestens 2048 bit langen privaten Schlüssel benutzen möchten, sollte der DHE Schlüssel mindestens gleich lang sein. Folgender Befehl generiert einen 2048 bit großen Schlüssel. Das Wichtigste bei DHE ist, dass man sich seine DH Parameter selbst erzeugt und nicht die mitgelieferten benutzt selbst wenn diese lnag genug sein sollten, da sich sonst mit genug Rechenpower alle Websites mit den gleichen Parameter angreifen lassen.

openssl dhparam -outform PEM -out dhparam2048.pem 2048

Das Generieren dauert je nach Größe unterschiedlich lange. Auf meinem Server mit einem CPU-Kern hat die Erstellung einige Minuten gedauert. Die Erstellung eines 4096 bit großen Schlüssels kann schon mehrere Stunden brauchen.
Um die Schlüssellänge von ECDHE zu erhöhen, muss man nur eine Zeile in die NGINX Konfiguration einfügen.

ssl_dhparam /pfad/dhparam2048.pem; ssl_ecdh_curve secp384r1;

ssl_ecdh_curve secp384r1 wählt eine elliptische Kurve mit 384 bit aus (entspricht etwa 7680 bit RSA). Standardmäßig verwendet NGINX secp256r1 (3072 bit RSA) und wäre mit der Verwendung eines 2048 bit RSA Schlüssels ausreichend. Die 521 bit Kurve (secp521r1) sollte man meiden, denn der Internet Explorer spricht nur maximal 384 bit ECDHE und es ist fragwürdig ob ein solch großer Schlüssel nötig ist.

Zum Weiterlesen:
Beschreibung von DHE und ECDHE
Gegenüberstellung verschiedener Schlüssellängen und Verfahren, inklusive Umrechner

2.6 HTTP Strict Transport Security (HSTS)

HTTP Strict Transport Security (RFC 6797) ist eine Antwort des Servers (HTTP Header) an den Browser, wenn dieser eine verschlüsselte Verbindung herstellt. Der Server sagt dem Browser damit, dass der Browser in der nächsten Zeit (Länge wird in der Antwort angegeben, und bei jedem neuen Aufruf wieder auf das Maximum gesetzt), nur noch verschlüsselt mit dem Server kommunizieren soll. Jede unverschlüsselte Verbindung und jede Verbindung mit einem selbst unterschriebenen Zertifikat wird abgebrochen. Dies ist ein Schutz gegen MITM Angriffe, da diese jetzt ein gültiges Zertifikat brauchen um dem Benutzer eine falsche Seite unterzuschieben. Zusäzlich werden alle http:// Links die auf die eigene Domain zeigen in https:// Links umgewandelt, noch bevor der Server kontaktiert wird. Das Maximalalter max-age=31536000 wird in Sekunden angegeben und entpricht hier einem Jahr. Außerdem sollte man mit dem Parameter includeSubDomains angeben, dass alle Subdomains ebenfalls nur mit HTTPS aufzurufen sind.

Wie am Anfang erwähnt ist ein Besucher beim ersten Aufrufen der Website nicht durch HSTS geschützt, da er den Header noch nie empfangen hat. Um dieses Problem zu beheben kann man sich bei Google in eine Liste eintragen lassen, in der Websiten aufgeführt werden für die der HSTS Header schon bei Installation des Browsers enthalten ist. Die HSTS Preload Liste wird im Moment von Chrome, Firefox, Internet Explorer 11, Safari, Opera und Edge genutzt. Unter https://hstspreload.org/ kann man sich in die Liste eintragen lassen wenn man alle dort aufgeführten Vorraussetzungen erfüllt, wie zum Beispiel den preload Parameter.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

Achtung: Wenn man seine Seite wieder unverschlüsselt anbieten möchte, muss man auf hstspreload.org die Austragung beantragen, die allerdings mehrere Monate dauern kann.

2.7 Public Key Pinning für HTTP (HPKP)

Public Key Pinning für HTTP (RFC 7469) ist ein neues Verfahren zum Erschweren von MITM Attacken. Wie oben erwähnt kann jede beliebige CA ein gültiges Zertifikat für jede Website ausstellen. HPKP ist wie HSTS ein HTTP Header der vom Server beim Aufbau einer verschlüsselten Verbindung gesendet wird und vom Browser für eine vorgegebene Zeit gespeichert wird. Im Header enthalten sind mindestens zwei sha256 Hashes von verschiedenen Public Keys, eine Zeitangabe und optional wieder ein includeSubDomains Parameter. Hat der Browser diesen Header gespeichert wird er bei jedem folgenden Verbindungsaufbau von allen Zertifikaten in der Zertifikatskette (CA, Zwischen-CA, Domain-Zetifikat) einen Hash über den enthaltenen Public Key bilden. Sobald einer der Hashes mit einem der gespeicherten Hashes übereinstimmt wird die Verbindung aufgebaut.

add_header Public-Key-Pins 'pin-sha256="AKTUELLER-KEY-HASH"; pin-sha256="BACKUP-KEY-HASH"; max-age=31536000; includeSubDomains';

Man kann sich also entscheiden den Public Key einer CA zu pinnen um die Möglichkeit das hunderte CAs gültige Zertifkate ausstellen können auf eine CA zu begrenzen. Das macht das Wechseln von Zertifikaten nicht aufwendiger, solange man seine CA nicht wechselt. Oder man pinnt den Public Key des eigenen Zertifikates, dann kann nicht einmal mehr die eigene CA andere gültige Zertifkate ausstellen. Entscheidet man sich für die zweite Methoden wird auch klar warum man mindestens zwei Keys pinnen muss. Der zweite Key (Backup-Key) ist nämlich ein noch nicht benutzter Key der sicher (nicht auf dem Webserver) aufbewahrt werden muss. Möchte man nun sein Zertifikat wechseln, sei es weil das Alte ausläuft oder möglicherweise kompromittiert wurde, nutzt man für das neue Zertifikat den Backup-Key. Dann kann man das Zertifikat in seinem Webserver einspielen und den HPKP Header anpassen, indem man den alten Key löscht und einen neuen Backup-Key erstellt und den Hash in den Header schreibt.

Die Hashes bekommt man ganz einfach mit folgendem Befehl. private_key.pem ist eurer Private Key.

openssl rsa -in private_key.pem -outform der -pubout | openssl dgst -sha256 -binary | base64

Die Ausgabe sieht dann wie folgt aus:

writing RSA key Nu/En7xRiHHOfLPkuu7mFYa7lWll5pN0nuikJnw+ltE=

Die zweite Zeile ist der Hash den ihr bei AKTUELLER-KEY-HASH oder bei BACKUP-KEY-HASH einsetzt. Möchte man den Public Key einer CA pinnen lädt man sich das passende Zertifikat runter und führt folgenden Befehl aus.

openssl x509 -in ca.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | base64

ca.crt ist hier dann das Zertifikat der CA.

Achtung: Bei falscher Anwendung oder Verlegung der gültigen Schlüssel, kann man seine Besucher für Wochen oder Monate von der eigenen Seite ausperren. Das Risiko eines MITM Angriffes mit gültigem Zertifikat, wird bei den meisten Leute nicht realistisch sein, man solte sich also genau überlegen, ob einem das Risiko wert ist.

Zum Weiterlesen:
Guidance on setting up HPKP

2.8 OCSP Stapling

Das Online Certificate Status Protocol wird auf der Client Seite (Hier: Browser) benutzt, um die Gültigkeit von Zertifikaten zu überprüfen. Vor OCSP wurden Zertifikate mithilfe von Certificate Revocation List (CRL) überprüft. OCSP kann schneller über zurückgezogene Zertifikate informieren, hat aber auch zwei Nachteile: Es wird nämlich, bei jedem Aufruf eines Zertifikates, eine Anfrage an die CA gestellt, die das Zertifikat herrausgegeben hat. Daraus ergibt sich zum Einen, eine große Last auf den Servern der CAs und zum Anderen, ist es ein Problem für die Privatsphäre des Nutzers, da die CA über jeden verschlüsselten Seitenaufruf Bescheid weiß. Beide Probleme können mit OCSP Stapling vermieden werden.

Beim OCSP Stapling hohlt der Server sich regelmäßig (einige Stunden bis einige Tage), bei der CA eine Unterschrift die angibt, dass das Zertifikat nicht zurückgezogen wurde. Diese Unterschrift schickt der Server dann beim Verbindungsaufbau mit und der Browser muss nicht mehr selbst bei der CA nachfragen. OCSP Stapling benötigt eine NGINX Version von 1.3.7 oder höher.

ssl_stapling on; ssl_trusted_certificate /pfad/bundle.ca.pem; ssl_stapling_verify on;

Ein einfaches ssl_stapling on reicht schon damit es funktioniert. Die ssl_stapling_verify Zeile hilft dabei, dass dem Server keine manipulierte Unterschrift untergeschoben wird. Die Anfrage an den CA Server läuft nämlich über normales http und könnte auf dem Weg verändert werden. Mit der Verify Option prüft NGINX vorher, anhand des Zertifikats der CA, ob die Unterschrift echt ist. In der ssl_trusted_certificate Zeile ist die Datei anzugeben, die das Root Zertifikat und alle Zwischenzertifikate der CA enthält.

Probleme von OCSP

OCSP hört sich im ersten Moment so an als würde es alle Probleme dem dem Zurückziehen von Zertifikaten lösen, es gibt aber ein Problem was das Protokoll fast nutzlos macht. Wenn der Browser keine Verbindung zum OCSP Server de CA aufbauen kann, wird das Zertifikat als Gültig anerkannt (Soft-Fail). Der Grund warum man Zertifikate zurück zieht, ist der dass das Zertifikat inkl. Private Key in die Hände eines Angreifers gefallen ist. Damit dieser Angreifer das Zerifikat nun nutzen kann um einen Benutzer auf einer gefälschten Seite falsche Sicherheit vorzutäuschen, muss er als MITM den Benutzer auf seinen eigenen Server umleiten. Wenn der Angreifer aber die Möglichkeit hat den Benutzer umzuleiten kann er auch die Verbindung zum OCSP Server unterbinden. Adam Langley hat das auf seinem Blog schön zusammengefasst. Google Chrome nutzt OCSP aus diesem Gründen mittlerweile nicht mehr.

Warum ich trotzdem schreibe wie man OSCP Stapling macht ist folgender: Die meisten Browser prüfen noch über OCSP und mit OCSP Stapling kann man dann den Datenschutz seiner Besucher etwas besser gewähren. Es gibt außerdem die Möglichkeit, dass Zertifikate einen Flag enthalten können, dass dem Browser sagt das er vom Webserver eine OCSP Staple Antwort zu erwarten hat und wenn er diese nicht bekommt er die Verbindung nicht aufbauen darf (OCSP Must-Staple). Let’s Encrypt Zertifikate unterstützen dieses Flag und wird von manchen Clients bereits unterstützt.

2.9 Wiederverwendung von TLS Verbindungen (Session Resumption)

Damit nicht bei jedem Seitenaufruf wieder der komplette TLS Handshake durchgeführt werden muss, lassen sich bestimmte Parameter speichern und später wiederbenutzen. Dies erspart dem Server unnötige Rechenzeit. Achtung: Session Resumption macht in vielen Fällen Forward Secrecy zunichte da nun die temporären Schlüssel sehr lange auf Server Seite gespeichert werden können. Es gibt zwei Arten von Session Resumption: Session IDs und Session Tickets. Bei Session IDs speichert der Server die TLS Verbindungsdaten in einem Cache und liest sie wieder ein wenn der Client wiederkommt und bei Session Tickets verschlüsselt der Server die TLS Verbindungsdaten mit einem Schlüssel und schickt diese dem Client, dieser wiederum gibt dem Server dieses Ticket wenn er sich das nächste mal verbindet. Ein Angreifer kann, wenn er Zugriff auf den Server erhält, den Session Cache oder den Ticket Schlüssel auslesen und damit alle Verbindungen nachträglich entschlüsseln, etwas das Forward Secrecy eigentlich verhindern soll. Da NGINX keine Möglichkeit bietet den Session Cache regelmäßig zu löschen, bleibt nur die Option den Session Cache zu deaktivieren. Der Parameter ssl_session_timeout gibt nur an das die Sessions nach einer Zeit nicht mehr benutzt werden, sie befinden sich danach aber weiterhin auf der Festplatte.

ssl_session_timeout 10m; ssl_session_cache off; ssl_session_tickets on; ssl_session_ticket_key /pfad/nginx_ticketkey;

Bleibt also nur Session Tickets, aber auch hier lässt sich bei NGINX nicht einstellen das der Ticket Schlüssel regelmäßig gewechselt wird. Dies lässt sich aber mit einem Cronjob selbst bauen. Dazu gibt man NGINX an Session Tickets zu nutzen ssl_session_tickets on und das als Schlüssel eine von uns angelegte Datei zu verwenden ssl_session_ticket_key.

Als Ticket Key wird eine Datei mit 48 byte Zufall benötigt. Dies lässt sich mit folgendem Script einfach erledigen:

#!/bin/bash head -c 48 /dev/urandom > /pfad/nginx_ticketkey systemctl reload nginx

Dieses Script sollte nun mindestens einmal am Tag per Cronjob ausgeführt werden.

2.10 Komplette Konfiguration

server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; ssl_certificate /pfad/zum/zertifikat/example.com.crt; ssl_certificate_key /pfad/zum/privaten/schlüssel/private.key; ssl_protocols TLSv1.2 TLSv1.1 TLSv1; ssl_ciphers EECDH+AESGCM:EDH+AESGCM:EECDH:EDH:!MD5:!RC4:!LOW:!MEDIUM:!CAMELLIA:!ECDSA:!DES:!DSS:!3DES:!NULL; ssl_prefer_server_ciphers on; ssl_dhparam /pfad/dhparam2048.pem; ssl_ecdh_curve secp384r1; #Nur sinnvoll wenn ein RSA Schlüssel über 3072 bit verwendet wird add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; add_header Public-Key-Pins 'pin-sha256="AKTUELLER-KEY-HASH"; pin-sha256="BACKUP-KEY-HASH"; max-age=31536000; includeSubDomains'; ssl_stapling on; ssl_trusted_certificate /pfad/bundle.ca.pem; ssl_stapling_verify on; ssl_session_timeout 10m; ssl_session_cache off; ssl_session_tickets on; ssl_session_ticket_key /pfad/nginx_ticketkey; [Der Rest eurer NGINX Konfiguration]

3 SSL Server Test

Um zu überprüfen, ob auch alles funktioniert, empfiehlt sich der SSL Server Test von SSL Labs. Am Beispiel meines eigenen Servers, werde ich kurz die wichtigsten Ergebnisse zusammenfassen.

3.1 Zusammenfassung

summary

Die Kriterien für die Bewertung findet man im SSL Server Rating Guide

3.2 Cipher

cipher

Hier kann man gut sehen, ob der Server auch alle Cipher anbieten kann, und ob er dies auch in der richtigen Reihenfolge tut.

3.3 Handshake Simulationen

handshake

Hier kann man sehen, welcher Browser, welche Cipher auswählt. Ein Klick auf die Browsernamen zeigt an, welche Protokolle, Cipher und Erweiterungen die Browser unterstützen. Wie oben schon erwähnt, schließt diese Konfiguration den Internet Explorer, in der Version 8 und niedriger, unter Windows XP, von dem Zugriff auf die Website aus. Da man Windows XP aber sowieso nicht mehr verwenden sollte, bringt man so vielleicht die letzten Leute dazu, endlich XP aufzugeben.

3.4 Details

details

Außerdem sieht man, das alle konfigurierten Optionen (HSTS, OCSP Stapling, Forward Secrecy, Session Resumption), funktionieren.

Changelog

13.07.2017 - Rechtschreibfehler korrigiert, Danke Lennart :-)
03.02.2017 - Tote Links bereinigt, Kleine Textverbesserungen
30.12.2015 - HTTP/2 hinzugefügt, Problematik mit Forward Secrecy und Session Resumption angesprochen
10.01.2015 - HPKP hinzugefügt, HSTS um Subdomains und preload erweitert, SPDY hinzugefügt, Probleme mit OCSP erläutert
10.08.2014 - Auf eine dynamische Cipherliste umgestellt
13.03.2014 - Unterstützung für Android 2.3 hinzugefügt
09.03.2014 - Firefox unterstützt nun auch AES GCM / Bilder Skalierung gefixt
22.01.2014 - Kapitel 3 an den neuen SSL Server Rating Guide angepasst
31.12.2013 - StartSSL Anleitung hinzugefügt, GCM Beschreibung verdeutlicht, 4096 bit Key benutzt
04.12.2013 - Formatierung vereinheitlicht
27.11.2013 - Erste Veröffentlichung