Verbesserung der NGINX-Performance mit Kernel-TLS und SSL_sendfile( )

NGINX | 11. November 2021

Transport Layer Security (TLS) ist ein äußerst weitverbreitetes Kryptografieprotokoll. Die Implementierung von TLS im Kernel (kTLS) verbessert die Leistung, da deutlich weniger Kopiervorgänge zwischen dem Userspace und dem Kernel erforderlich sind.

Durch die Kombination von kTLS und sendfile() werden Daten direkt im Kernel-Space verschlüsselt, bevor sie zur Übertragung an den Netzwerk-Stack weitergeleitet werden. Dadurch entfällt die Notwendigkeit, Daten zur Verschlüsselung durch TLS-Bibliotheken in den User-Space und anschließend zur Übertragung wieder zurück in den Kernel-Space zu kopieren. kTLS ermöglicht außerdem die Auslagerung der TLS-Verarbeitung auf Hardware, einschließlich der Auslagerung der symmetrischen TLS-Kryptoverarbeitung auf Netzwerkgeräte.

Moderne Linux- und FreeBSD-Kernel unterstützen die Auslagerung von TLS in den Kernel – und jetzt gilt das auch für NGINX Open Source! NGINX 1.21.4 führt die Unterstützung für kTLS ein bei der Bereitstellung statischer Dateien und zwischengespeicherter Antworten mit SSL_sendfile(), wodurch sich die Leistung erheblich steigern lässt. Wie nachfolgend erläutert, müssen sowohl der Kernel als auch OpenSSL mit kTLS-Unterstützung kompiliert sein, damit NGINX SSL_sendfile() verwenden kann.

In diesem Blogbeitrag erläutern wir ausführlich, welche Betriebssystem- und OpenSSL-Versionen kTLS unterstützen, und zeigen, wie Sie den Kernel und NGINX für kTLS kompilieren und konfigurieren. Damit Sie sich ein Bild von der Leistungssteigerung machen können, die Sie von kTLS erwarten dürfen, stellen wir außerdem die Spezifikationen und Ergebnisse unserer Tests unter FreeBSD und Ubuntu vor.

Hinweis: kTLS-Implementierungen sind noch recht neu und entwickeln sich schnell weiter. Dieser Blog beschreibt die Unterstützung für kTLS mit Stand November 2021. Achten Sie jedoch auf Ankündigungen auf nginx.org und im NGINX-Blog<.htmla> zu Änderungen an den hier bereitgestellten Informationen und Anweisungen.

Allgemeine Anforderungen

  • Betriebssystem – eines der folgenden:
    • FreeBSD 13.0+. Seit November 2021 ist FreeBSD 13.0+ das einzige Betriebssystem, das kTLS in NGINX unterstützt, ohne dass NGINX manuell kompiliert werden muss, um OpenSSL 3.0.0+ einzubinden. Siehe „Aktivieren von kTLS für NGINX unter FreeBSD“.
    • Eine Linux-Distribution, die auf Linux-Kernel-Version 4.17 oder höher basiert. Wir empfehlen jedoch, nach Möglichkeit eine Distribution zu verwenden, die auf Version 5.2 oder höher basiert. (kTLS-Unterstützung ist zwar bereits ab Version 4.13 verfügbar, OpenSSL 3.0.0 erfordert jedoch Kernel-Header ab Version 4.17.)
  • OpenSSL – Version 3.0.0 oder höher
  • NGINX – Version 1.21.4 oder höher (Mainline)[Redaktion – NGINX Plus R27 und höher unterstützt kTLS auf geeigneten Linux-basierten Betriebssystemversionen; NGINX Plus R26 und höher unterstützt kTLS auf geeigneten FreeBSD-Versionen. Einzelheiten zu den unterstützten Betriebssystemen finden Sie auf der NGINX Plus-Seite „Versionen“.]

Unterstützung für Betriebssysteme

Betriebssysteme mit kTLS-Unterstützung

Mit Stand November 2021 unterstützen von den Betriebssystemen, die von NGINX Open Source unterstützt werden, die folgenden kTLS und die angegebenen Verschlüsselungsverfahren. Einzelheiten zur Unterstützung von Verschlüsselungsverfahren finden Sie unter „Unterstützung von TLS-Protokollen und Verschlüsselungsverfahren“.

 TLSv1.2-VerschlüsselungsverfahrenTLSv1.3-
Verschlüsselungssammlungen
TLS_CHACHA20_POLY1305_SHA256-VerschlüsselungsverfahrenLinux-Kernel-Version
Amazon Linux 2*✅✅❌5.10
CentOS 8**✅❌❌4.18
FreeBSD 13.x✅✅❌ ***k. A.
RHEL 8✅❌❌4.18
SLES 15 SP2✅✅✅5.3
Ubuntu 20.04 LTS✅❌​​❌5.4
Ubuntu 21.04✅✅✅5.11
Ubuntu 21.10✅✅✅5.13

* Die Kernel-Version muss 5.10 und nicht 4.14 sein; siehe Betriebssysteme ohne kTLS-Unterstützung und die FAQ zu Amazon Linux 2
** Übernimmt den Status der kTLS-Unterstützung von RHEL 8 als Upstream-Quelle
*** Siehe das FreeBSD-Commit-Protokoll

Betriebssysteme, die kTLS nicht unterstützen

Die folgenden Betriebssysteme unterstützen kTLS aus dem jeweils angegebenen Grund nicht:

  • Alpine Linux 3.11–3.14 – Der Kernel wird mit der Option CONFIG_TLS=n kompiliert, wodurch die Kompilierung von kTLS als Modul oder als Bestandteil des Kernels deaktiviert wird.
  • Amazon Linux 2 – Die Linux-Kernel-Version für das standardmäßige Amazon Linux 2 AMI ist 4.14 (siehe die FAQ zu Amazon Linux 2).
  • CentOS 7.4+ – Die Linux-Kernel-Version ist 3.10. Der kTLS-Unterstützungsstatus wird von RHEL 7.4+ als Upstream-Quelle übernommen.
  • Debian 10 und 11 – Der Kernel wurde mit der Option „CONFIG_TLS=n“ kompiliert (siehe die Protokolle des Debian-Fehlerberichts).
  • RHEL 7.4+ – Die Linux-Kernel-Version ist 3.10.
  • SLES 12 SP5+ – die Linux-Kernel-Version ist 4.12.
  • Ubuntu 18.04 LTS – Linux-Kernel-Version: 4.15.

Unterstützung für TLS-Protokolle und Verschlüsselungsverfahren

Wie oben beschrieben, unterstützen Betriebssysteme mit kTLS-Unterstützung unterschiedliche TLS-Protokolle und Verschlüsselungsverfahren.

Mit TLSv1.2 unterstützt das kTLS-Modul die folgenden Verschlüsselungsverfahren:

  • AES128-GCM-SHA256
  • AES256-GCM-SHA384
  • ECDHE-RSA-AES128-GCM-SHA256
  • ECDHE-RSA-AES256-GCM-SHA384

Mit TLSv1.3 unterstützt das kTLS-Modul die folgenden Verschlüsselungssammlungen:

Um zu überprüfen, welche von OpenSSL unterstützten TLS-Chiffren in Ihrer NGINX-Binärdatei aktiviert sind, führen Sie den Befehl openssl-3.0.0/.openssl/bin/openssl ciphers in dem Verzeichnis aus, in dem Sie NGINX erstellt haben (zum Beispiel in Ihrem Home-Verzeichnis).

kTLS in NGINX aktivieren

Wie in der Einleitung erwähnt, verbessert kTLS die Leistung von NGINX, da die gesamte Ver- und Entschlüsselung im Kernel erfolgt. Die Daten werden direkt im Kernel-Space verschlüsselt – bevor sie zur Übertragung an den Netzwerk-Stack weitergeleitet werden. Dadurch entfällt die Notwendigkeit, die Daten zur Verschlüsselung durch TLS-Bibliotheken in den User-Space und anschließend zur Übertragung wieder zurück in den Kernel-Space zu kopieren.

Diagramm von Kernel-TLS (kTLS) mit NGINX

kTLS in den Kernel laden

In modernen FreeBSD- und Linux-Distributionen ist kTLS üblicherweise als Modul kompiliert (mit der Option CONFIG_TLS=m). Sie müssen das kTLS-Modul explizit in den Kernel laden, bevor Sie NGINX starten.

  • Führen Sie unter FreeBSD diese Befehle als Benutzer root aus:
# kldload ktls_ocf.ko# sysctl kern.ipc.tls.enable=1
  • Weitere Informationen zu den FreeBSD-Befehlsoptionen finden Sie auf der Manpage zu ktls(4).
  • Führen Sie diesen Befehl auf Linux-Distributionen als Benutzer root aus:
# modprobe tls

NGINX mit kTLS unter FreeBSD aktivieren

Um die kTLS-Unterstützung in NGINX unter FreeBSD zu aktivieren, können Sie dieselben Anweisungen wie für Linux-Distributionen verwenden. Wir empfehlen jedoch, die folgenden Schritte auszuführen, um den NGINX-Build mit kTLS im Port security/openssl-devel der FreeBSD Ports Collection zu nutzen. Weitere Informationen, einschließlich eines Überblicks über kTLS, finden Sie unter TLS-Offloading im Kernel auf der FreeBSD-Website.

  1. Erstellen Sie OpenSSL 3.0 mit kTLS-Unterstützung und wählen Sie dazu die entsprechenden Optionen im Konfigurationsmenü aus:
# cd /usr/ports/security/openssl-devel && make config && make install
  1. Ändern Sie /etc/make.conf, um openssl-devel als standardmäßige SSL-Bibliothek zu verwenden:
# echo "DEFAULT_VERSIONS+=ssl=openssl-devel" >> /etc/make.conf
  1. NGINX kompilieren:
# cd /usr/ports/www/nginx-devel && make install

NGINX mit kTLS auf Linux-Distributionen kompilieren

Die meisten aktuellen Linux-Distributionen enthalten eine OpenSSL-Version vor 3.0.0 (in der Regel Version 1.1). Daher müssen Sie NGINX mit OpenSSL 3.0.0 aus dem Quellcode kompilieren.

Die beiden entscheidenden Optionen des Befehls configure, mit denen die kTLS-Unterstützung aktiviert wird, sind:

  • --with-openssl=../openssl-3.0.0
  • --with-openssl-opt=enable-ktls

Die anderen configure-Optionen gelten für die Module, die in den offiziellen NGINX-Binärpaketen enthalten sind, die unter nginx.org verfügbar sind. Sie können stattdessen eine benutzerdefinierte Auswahl von Modulen angeben. Um die Build-Optionen anzuzeigen, die für Ihre aktuelle NGINX-Binärdatei verwendet wurden, führen Sie nginx -V aus.

Führen Sie die folgenden Befehle aus, um NGINX mit OpenSSL 3.0.0 zu kompilieren:

$ wget https://nginx.org/download/nginx-1.21.4.tar.gz$ wget https://www.openssl.org/source/openssl-3.0.0.tar.gz$ tar xzf openssl-3.0.0.tar.gz$ cd nginx-1.21.4$ ./configure --with-debug --prefix=/usr/local --conf-path=/usr/local/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-openssl=../openssl-3.0.0 --with-openssl-opt=enable-ktls --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' -with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'$ make –j4$ make install

Hinweis: Die resultierende NGINX-Binärdatei ist statisch mit den OpenSSL 3.0.0-Bibliotheken verknüpft. Wenn Sie OpenSSL später patchen müssen, müssen Sie das neue OpenSSL-Quellarchiv herunterladen und entpacken und anschließend die oben aufgeführten Befehle ausführen, um die NGINX-Binärdatei neu zu erstellen.

NGINX konfigurieren

Um kTLS zu aktivieren, fügen Sie die Direktive „ssl_conf_command“ mit dem Parameter „Options KTLS“ in den Kontext „server{}“ ein, wie in dieser Beispielkonfiguration, die wir für unsere Tests verwendet haben:

worker_processes auto;error_log /var/log/nginx/error.log debug;events {}http {    sendfile on;    server {        listen 443 ssl;        ssl_certificate ssl/example.crt;        ssl_certificate_key ssl/example.key;        ssl_conf_command Options KTLS;        ssl_protocols TLSv1.3;        location / {            root /data;    	}    }}

Überprüfen, ob kTLS aktiviert ist

Um zu überprüfen, ob NGINX kTLS verwendet, aktivieren Sie den Debugging-Modus und suchen Sie im Fehlerprotokoll nach BIO_get_ktls_send() und SSL_sendfile().

$ grep BIO /var/log/nginx/error.log2021/11/10 16:02:46 [debug] 274550#274550: *2 BIO_get_ktls_send(): 12021/11/10 16:02:49 [debug] 274550#274550: *3 BIO_get_ktls_send(): 1 $ grep SSL_sendfile /var/log/nginx/error.log2021/11/10 16:02:46 [debug] 274550#274550: *2 SSL_sendfile: 10485762021/11/10 16:02:49 [debug] 274550#274550: *3 SSL_sendfile: 1048576

Hinweis: Wir empfehlen, den Debugging-Modus nach diesen Überprüfungen zu deaktivieren, insbesondere in Produktionsumgebungen. Die Debug-Protokollierung beeinträchtigt aufgrund der großen Anzahl an Schreibvorgängen die Leistung. Außerdem können Debug-Protokolle sehr groß werden und den verfügbaren Speicherplatz auf der Festplattenpartition schnell aufbrauchen.

Leistungsverbesserung mit kTLS

Bei der Bereitstellung statischer Dateien und zwischengespeicherter Antworten unter hoher Last kann SSL_sendfile() den Durchsatz um bis zu 100 % steigern – verglichen mit TLS im Userspace. Wie stark die Leistung tatsächlich steigt, hängt jedoch maßgeblich von verschiedenen Faktoren ab (Festplattenleistung, Systemlast usw.). Wenn Ihre Netzwerkkarte TLS-Offloading unterstützt, lässt sich zudem die CPU-Auslastung reduzieren.

Leistung testen

Um die Leistungssteigerung auf Ihrem System zu messen, führen Sie anhand der folgenden Anleitung einen einfachen Test mit nur einem Thread durch. Wie unten näher erläutert, zeigen unsere Testergebnisse ohne spezielle Optimierungen eine Leistungssteigerung von bis zu knapp 30 %.

Verwendete Hardware und Software:

  • AWS-t3.medium-Instanz mit:
    • 4 GB RAM
    • 20 GB Allzweck-SSD
    • Intel® Xeon® Platinum 8259CL CPU @ 2,50 GHz mit 2 Kernen
  • FreeBSD 13.0 und Ubuntu 21.10
  • TLSv1.3 mit der Verschlüsselungssuite TLS_AES_256_GCM_SHA384 cipher suite
  • NGINX 1.21.4, kompiliert und konfiguriert wie unter „Aktivieren von kTLS in NGINX“ beschrieben.

So führen Sie den Test durch:

  1. Erstellen Sie eine große Datei, die vollständig in den Festplatten-Cache passt:
# truncate -s 1g /data/1G
  1. Führen Sie diesen Befehl aus, um den Durchsatz zu überprüfen. Für genauere Ergebnisse wird der Basisbefehl mehrmals wiederholt. Leiten Sie die Ausgabe für eine grundlegende statistische Analyse an das Dienstprogramm „ministat“ weiter[FreeBSD][Ubuntu].
# for i in 'seq 1 100'; do curl -k -s -o /dev/null -w '%{speed_download}n' https://localhost/1G | ministat

Ergebnisse der Leistungstests

In den folgenden Ergebnissen unserer Tests, die als Ausgabe von ministat dargestellt sind, gibt jeder Wert die Downloadgeschwindigkeit in kByte/Sekunde an. Zur besseren Lesbarkeit ist die Ausgabe auf zwei Zeilen verteilt.

Durchsatz für FreeBSD 13.0 ohne kTLS:

    N           Min           Max        Median     ...x  10        532225        573348        555616     ...     ...      Avg        Stddev     ... 555155.6     10239.137

Durchsatz für FreeBSD 13.0 mit kTLS:

    N           Min           Max        Median     ...x  10        629379        723164        717349     ...         ...      Avg        Stddev   ... 708600.4     28304.766

Durchsatz für Ubuntu 21.10 ohne kTLS:

    N           Min           Max        Median     ...x  10        529199        705720        662354     ...         ...      Avg        Stddev   ... 654321.6     48025.103

Durchsatz für Ubuntu 21.10 mit kTLS:

    N           Min           Max        Median     ...x  10        619105        760208        756278     ...         ...      Avg        Stddev   ... 741848.3     43255.246

In unseren Tests steigerte kTLS die Leistung unter FreeBSD stärker als unter Ubuntu. Die prozentuale Verbesserung stellte sich wie folgt dar:

 Min.Max.MedianDurchschnitt
FreeBSD 13.018%26%29%28%
Ubuntu 21.1016%8%14%13%

Zusammenfassung

NGINX 1.21.4 führt Unterstützung für kTLS bei der Bereitstellung statischer Dateien und zwischengespeicherter Antworten mit SSL_sendfile() ein. Unsere Tests zeigen, dass sich die Leistung je nach Betriebssystem um 8 % bis 29 % verbessert.

Wir würden gerne mehr über Ihre Erfahrungen mit kTLS und NGINX erfahren – insbesondere über die Ergebnisse Ihrer Tests auf anderen Betriebssystemen! Teilen Sie sie uns bitte unten im Kommentarbereich mit.


Teilen
Schlagwörter: F5 NGINX, 2021, News, Tech

Ähnliche Blogbeiträge

Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
NGINX | 23.08.2022

Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln

Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
NGINX | 08.09.2021

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen

Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.

Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
NGINX | 16.08.2021

Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet

Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
NGINX | 12.12.2018

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77

Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.

Ankündigung von NGINX Plus R16
NGINX | 05.09.2018

Ankündigung von NGINX Plus R16

NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.

5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
NGINX | 13.10.2016

5 Gründe für den Umstieg auf softwarebasiertes Load Balancing

Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.