Wer einen Webserver betreibt, sollte darauf achten, dass keine veralteten kryptografischen Protokolle ihr Unwesen treiben. Ein Kandidat hierfür wäre Transport Layer Security (TLS) in den Versionen TLS 1.0 und TLS 1.1. Die Standardkonfiguration von Nginx/OpenSSL unter Ubuntu Server 24.04 LTS mittels Certbot ist schon sehr gut. Ich zeige Euch, wie noch weiter optimiert werden kann.
Diskussion
Transport Layer Security (TLS) ist ein kryptografisches Protokoll zum Verschlüsseln von Nachrichten. TLS ist wesentlicher Bestandteil des Kommunikationsprotokolls Hypertext Transfer Protocol Secure (HTTPS). Die Versionshistorie von TLS sieht wie folgt aus:
| Version | Veröffentlichung |
|---|---|
| TLS 1.0 | Januar 1999 |
| TLS 1.1 | April 2006 |
| TLS 1.2 | August 2008 |
| TLS 1.3 | August 2018 |
Die Versionen 1.0 und 1.1 sind also schon ziemlich alt. Ein Entwurf der Internet Engineering Task Force (IETF) fordert sogar, die Unterstützung für beiden TLS-Varianten komplett zu verbieten. Die dort aufgeführten Gründe sind:
-
Beide Protokollversionen erfordern den Einsatz von veralteten Verschlüsselungsverfahren, die als nicht mehr sicher gelten. TLS 1.0 setzt beispielsweise den Einsatz von TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA als zwingend voraus.
-
Es werden keine aktuellen Verschlüsselungsverfahren unterstützt. Die AEAD-Verschlüsselung wird beispielsweise erst ab Version 1.2 unterstützt.
-
Die Integrität des Handshake-Algorithmus basiert auf einem SHA-1 Hash. Dieser gilt als unsicher.
-
Die Authentifizierung der Gegenseite basiert auf SHA-1 Signaturen. Diese gelten ebenfalls als unsicher.
-
Die Unterstützung von insgesamt vier Protokollversionen erhöht die Wahrscheinlichkeit von Fehlkonfiguration.
-
Einige Programmierbibliotheken haben angekündigt, die Unterstützung für TLS 1.0 und TLS 1.1 einzustellen. Dies hätte zur Folge, dass für die weiter Bereitstellung dieser Protokollversionen keine Updates dieser Bibliotheken mehr möglich wären.
Alle modernen Browser (Chrome, Firefox, Safari, Edge, Opera, etc.) unterstützen mindestens TLS 1.2.
Ein Webserver sollte daher ausschließlich TLS 1.2 oder höher bereitstellen.
Nginx und TLS
Bei Nginx wird TLS in der Regel über OpenSSL implementiert, einer freien Kryptografie-Bibliothek. Für die Konfiguration von TLS unter Nginx empfiehlt sich standardmäßig der Einsatz von Certbot. Certbot ist ein freies Open-Source-Werkzeug, mit dem sich kostenlose TLS-Zertifikate von Let’s Encrypt automatisch erstellen, installieren und erneuern lassen.
Ein einfacher Test unter auf der Webseite SSL Labs zeigt auf, wie Dein TLS konfiguriert ist. Tippe dazu den Hostnamen Deiner Webseite ein, die Du testen möchtest.
Das typische Ergebnis für Nginx/OpenSSL und Certbot unter Ubuntu 24.04 TLS sollte in etwas so aussehen:

Nginx abgesichert
Es gibt keinen dringenden Bedarf, daran etwas zu ändern.
- Die TLS-Versionen 1.0 und 1.1 sind deaktiviert.
- Es werden (aktuell) keine unsicheren kryptographische Verfahren genutzt.
Wer sich die eigene Konfiguration im Detail anschauen möchte, der tippt folgendes sein:
$ sudo nano /etc/letsencrypt/options-ssl-nginx.confDamit öffnen wir die globale TLS-Konfigurationsdatei. Wer mit den Konfigurationsparametern rumspielen möchte, der sei auf das Mozilla-Projekt verwiesen. Unter der folgenden Webseite
https://ssl-config.mozilla.org/
findest Du einen TLS Configuration Generator für Nginx (und andere Webserver).
Weitere Optimierungen
HSTS
HTTP Strict Transport Security (HSTS) ist ein Sicherheitsmechanismus, mit dem eine Webseite einem Browser mitteilt, dass sie ausschließlich über HTTPS aufgerufen werden darf. Der Server sendet dazu folgenden HTTP-Header:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadDamit merkt sich der Browser, dass zukünftige Aufrufe automatisch auf HTTPS umgeleitet werden, auch wenn der Nutzer http:// eintippt oder auf einen unsicheren Link klickt. Ziel ist die Verhinderung von Man-in-the-Middle-Angriffen.
Die Parameter bedeuten:
| Name | Optional | Beschreibung |
|---|---|---|
| max-age | Gibt an, wie lange (in Sekunden) der Browser die HSTS-Regel speichern soll. | |
| includeSubDomains | Ja | Erweitert die HSTS-Regel auf alle Subdomains der angegebenen Domain. |
| preload | Ja | Signalisiert, dass die Domain in die offizielle HSTS-Preload-Liste großer Browser (Chrome, Firefox, Edge, Safari etc.) aufgenommen werden soll. |
Unter Nginx mußt Du diesen Header via add-header hinzufügen. Eine typische Konfiguration sieht wie folgt aus:
server {
server_name beispiel.de;
http2 on;
listen 443 ssl;
# Zertifikate (Certbot/Let’s Encrypt)
ssl_certificate /etc/letsencrypt/live/beispiel.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/beispiel.de/privkey.pem;
# Unser HSTS header
add_header Strict-Transport-Security "max-age=31536000" always;
...
}OCSP-Stapling
OCSP-Stapling ist ein Mechanismus, mit dem ein Webserver die Gültigkeit seines TLS-Zertifikats nachweisen kann, ohne dass der Browser selbst beim Aussteller (Certificate Authority, CA) nachfragen muss. Normalerweise prüft der Browser per OCSP-Anfrage beim CA-Server, ob ein Zertifikat gesperrt wurde. Das verursacht zusätzliche Latenz und verrät, welche Webseite der Nutzer aufruft. Beim Stapling ruft der Server diese OCSP-Antwort regelmäßig selbst ab, heftet (Englisch: staples) sie an die TLS-Verbindung und liefert sie dem Browser direkt mit.
Soweit zur Theorie. Let’s Encrypt hat angekündigt, OCSP und damit auch OCSP-Stapling 2025 vollständig abzuschalten. Gründe sind Datenschutz (OCSP-Abfragen verraten Surfverhalten), technische Komplexität, Kosten und die Tatsache, dass aktuelle Browser Revocations (Widerrrufe) ohnehin anders handhaben. Tatsächlich sind bei Let’s Encrypt aktuell keine Abfragen via OCSP mehr möglich.
Als Alternativen gelten:
- CRL (Certificate Revocation List), also klassische Sperrlisten, die regelmäßig verteilt werden.
- Browser-eigene Mechanismen wie Googles CRLSets oder Mozillas OneCRL
- Kurzlebige Zertifikate (90 Tage bei Let’s Encrypt), welche die Notwendigkeit von Revocations weitgehend überflüssig machen.
OCSP-Stapling muss unter Nginx/OpenSSL explizit aktiviert werden. Ein typische Konfiguration sieht wie folgt aus:
server {
server_name beispiel.de;
http2 on;
listen 443 ssl;
# Zertifikate (Certbot/Let’s Encrypt)
ssl_certificate /etc/letsencrypt/live/beispiel.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/beispiel.de/privkey.pem;
# Unser HSTS header
add_header Strict-Transport-Security "max-age=31536000" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
# Trusted Chain für OCSP-Verify (bei Certbot/Let’s Encrypt: chain.pem)
ssl_trusted_certificate /etc/letsencrypt/live/beispiel.de/chain.pem;
# Resolver (wichtig, sonst kann Nginx den OCSP-Responder nicht auflösen)
resolver 127.0.0.53 valid=300s; # Lokaler Ubuntu-DNS-Resolver "systemd-resolved", Antworten 5 min cachen
resolver_timeout 5s; # Timeout 5s
...
}CAA
Certification Authority Authorization (CAA) ist ein DNS-Eintrag vom Typ “CAA”, mit dem ein Domaininhaber festlegt, welche Zertifizierungsstellen (CAs) für seine Domain TLS-Zertifikate ausstellen dürfen.
Beispiel:
beispiel.de. CAA 0 issue "letsencrypt.org"Dieser Eintrag hätte zur Folge, dass nur Let’s Encrypt ein Zertifikat für beispiel.de ausstellen darf. Würde jemand versuchen, bei einer anderen CA (z. B. DigiCert) ein Zertifikat zu beantragen, lehnt diese den Antrag gemäß RFC-Standard ab.
CAA ist eine Ergänzung zu Maßnahmen wie HSTS und OCSP-Stapling und soll vor ungewollter oder betrügerischer Zertifikatsausstellung schützen. Es handelt sich dabei um eine Konfigurationseinstellung bei Deinem DNS-Provider, nicht direkt bei Nginx.
DH
Diffie-Hellman (DH) ist ein kryptografisches Verfahren zum sicheren Schlüsselaustausch über unsichere Netzwerke. Dabei können zwei Parteien (z.B. ein Browser und ein Webserver) einen gemeinsamen geheimen Schlüssel berechnen, ohne dass dieser jemals direkt übertragen wird.
Das funktioniert wie folgt:
- Server und Client einigen sich zunächst auf gemeinsame öffentliche Parameter: eine große Primzahl und eine Basis (Generator).
- Danach erzeugt jede Seite einen privaten Schlüssel und berechnet daraus einen öffentlichen Schlüssel, der auf diesen gemeinsamen Parametern basiert.
- Die öffentlichen Schlüssel werden ausgetauscht, sodass beide Parteien nun den öffentlichen Schlüssel des jeweils anderen kennen.
- Mit dem eigenen privaten und dem empfangenen öffentlichen Schlüssel kann jede Seite dasselbe gemeinsame Geheimnis berechnen.
Moduli erhöhen
Der Modulus bezeichnet in TLS die Schlüssellänge des mathematischen Moduls, der beim Schlüsselaustausch verwendet wird. Die Größe des DH-Modulus bestimmt dabei maßgeblich die Kryptostärke:
- Früher wurden oft nur 1024 Bit verwendet – heute gilt das als unsicher.
- Empfohlen sind mindestens 2048 Bit, besser 3072 Bit oder mehr.
Nginx/OpenSSL verwendet keine festen Standardwerte, sondern eine explizit bereitgestellte DH-Parameterdatei, falls DHE-Cipher Suites erlaubt sind. Certbot installiert diese Parameterdatei unter /etc/letsencrypt/ssl-dhparams.pem. Auf diese Datei wird in allen von Certbot generierten TLS-Konfigurationen verwiesen:
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pemMöchtest Du wissen, wie groß die Bitlänge von ssl-dhparams.pem ist, tippe folgnden OpenSSL-Befehl ein:
$ openssl dhparam -in /etc/letsencrypt/ssl-dhparams.pem -text -nooutDas Ergebnis sieht standardmäßig wie folgt aus:
DH Parameters: (2048 bit)
GROUP: ffdhe2048Das bedeutet, die Bitlänge ist 2048 Bit. Um Sie zu erhöhen, musst Du OpenSSL mit folgendem Befehl aufrufen:
$ sudo openssl dhparam -out /etc/letsencrypt/ssl-dhparams.pem 3072Die Erstellung dauert ein Weilchen (mehrere Minuten), am Ende hast Du aber eine neue ssl-dhparams.pem mit 3072-Bitlänge. Ein erneuter Test via OpenSSl ergibt dann folgendes Bild:
DH Parameters: (3072 bit)
P:
00:fe:19:17:97:ef:8e:eb:d2:fe:24:e8:63:ef:e0:
25:a6:53:ef:a2:8b:23:50:cc:cc:92:77:f8:21:05:
0f:42:55:c4:97:a0:19:45:7d:dd:77:7a:55:64:05:
c6:3c:6e:2c:5c:9e:79:3d:a4:cb:e3:55:e9:24:55:
3a:b5:a4:df:cc:75:89:5f:bc:b0:8f:c0:13:1f:d1:
6a:83:d5:ff:3b:a9:d9:8e:58:e0:aa:c1:c2:87:e7:
95:7a:70:bd:80:eb:9a:e2:92:c0:66:93:19:00:fd:
06:56:52:02:68:46:c6:ad:67:92:ae:1f:45:a7:af:
cc:e4:b5:29:d5:9b:10:72:a3:fb:6c:ad:ac:c0:fc:
0b:5e:4e:e0:c7:1f:98:83:87:3c:6d:fb:58:33:d0:
e8:1f:c5:98:15:53:9f:98:bf:ba:83:6c:22:e6:9b:
b4:af:96:6a:55:3c:97:e6:62:b9:36:3e:df:1a:8e:
9a:cd:24:57:e8:ae:6f:6c:e0:fe:7d:c7:1f:bc:57:
35:57:1e:73:7f:a2:16:94:4b:e6:77:5d:ea:6e:d5:
f5:ed:55:a6:4a:2c:c0:84:98:71:03:ab:36:29:62:
6c:61:49:eb:a6:e4:5a:77:a1:a6:e0:e6:93:25:c3:
5f:b5:f9:0a:04:c9:77:7a:c4:22:0b:2e:62:88:22:
56:fb:59:61:02:14:0f:4c:b1:bb:4f:9d:31:6f:b5:
95:bf:28:78:e4:c7:05:f8:91:7a:65:b6:fc:47:f7:
0e:e6:4e:68:5d:4b:b2:70:6e:5e:36:da:3e:79:1e:
82:31:b1:f5:b6:d8:67:9b:67:c5:b9:ab:dd:5a:64:
f7:3d:f2:fe:b1:11:ec:74:3a:e4:95:c9:31:ca:c0:
c5:05:f2:1d:00:12:55:7e:ba:69:a6:36:ea:4d:7e:
98:13:fd:17:d5:12:60:48:6c:88:67:02:a4:ea:21:
c5:d3:30:5e:90:44:f9:3e:9b:d5:eb:6c:df:4a:29:
7f:b5:9c:a7:4c:d8:58:3c:3e:3f
G: 2 (0x2)ECDH
Elliptic Curve Diffie-Hellman (ECDH) ist eine moderne Variante des klassischen Diffie-Hellman-Schlüsselaustauschs. Anstatt große Primzahlen und modulare Arithmetik zu verwenden (wie beim ursprünglichen DH-Verfahren), basiert ECDH auf den mathematischen Eigenschaften elliptischer Kurven über endliche Körper.
Aktuelle TLS-Implementierungen nutzen immer mehr das ECDH-Verfahren als Standard.
Ephemeral Key Reuse
Wird der private Schlüssel des Servers für jede Sitzung neu erzeugt (Englisch: ephemer), so bleiben alle bisherigen Verbindungen selbst dann sicher, wenn der langfristige Server-Schlüssel später kompromittiert wird. Dieses Prinzip nennt man Perfect Forward Secrecy (PFS).
Wird dagegen derselbe ECDH-Schlüssel über mehrere Verbindungen hinweg wiederverwendet (Englisch: reuse), spricht man von ECDH Ephemeral Key Reuse, denn PFS ist nicht mehr gegeben.
Unter Nginx/OpenSSL wird Perfect Forward Secrecy durch die Verwendung von (EC)DHE-Cipher Suites bzw. TLS 1.3 standardmäßig erreicht. Dabei werden die für den Schlüsselaustausch benötigten Diffie-Hellman-Parameter für jede neue TLS-Aushandlung ephemer (also kurzlebig) erzeugt.
Im Gegensatz zu SChannel unter Windows gibt es bei Nginx/OpenSSL keine konfigurierbare serverseitige “Ephemeral Key Reuse Time”, die denselben ECDHE-Schlüssel über mehrere unabhängige Handshakes hinweg wiederverwendet.
Elliptische Kurven
Die technische Richtlinie BSI TR-03116-4 Kryptographische Vorgaben für Projekte der Bundesregierung Teil 4 Stand 2025 des Bundesamts für Sicherheit in der Informationstechnik gibt vor, mindestens folgende elliptische Kurven zu unterstützen:
secp256r1(für TLS 1.2 und 1.3)brainpoolP256r1(für TLS 1.2)brainpoolP256r1tls13(für TLS 1.3)
Wir können unsere Nginx/OpenSSL-Instanz kompatibel mit den BSI-Vorgaben machen, indem wir folgende Konfiguration definieren:
# TLS Versionen
ssl_protocols TLSv1.2 TLSv1.3;
# Elliptische Kurven (BSI TR-03116-4)
ssl_ecdh_curve secp256r1:brainpoolP256r1:brainpoolP256r1tls13;
# Cipher Suites TLS 1.3 (BSI-kompatibel)
ssl_ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
# Cipher Suites TLS 1.2 (ECDHE + AEAD)
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# Nginx wählt die erste passende Cipher (und nicht der Client)
ssl_prefer_server_ciphers on;Anmerkungen
Es gibt noch eine Reihe weiterer TLS-Einstellungen für Nginx, die in der Dokumentation unter ngx_http_ssl_module beschrieben sind.
Die bereits erwähnte technische Richtlinie BSI TR-03116-4 Kryptographische Vorgaben für Projekte der Bundesregierung Teil 4 Stand 2025 des Bundesamts für Sicherheit in der Informationstechnik enthält ein ganzes Kapitel “Vorgaben für SSL/TLS”.