原文链接:https://www.f5.com/company/blog/nginx/improving-nginx-performance-with-kernel-tls#Enabling-kTLS-in-NGINX
原文作者:Mikhail Isachenkov
翻译:KIMI
校对和补充:邢万里
❞
传输层安全性(TLS)是一种极为流行的加密协议。在内核中实现 TLS(即 kTLS)可以通过显著减少用户空间与内核之间复制操作的需求来提高性能。
将 kTLS 与 sendfile()
(Man Pagesendfile(2)
网址: https://man7.org/linux/man-pages/man2/sendfile.2.html ) 结合使用意味着数据在被传递到网络栈进行传输之前,会直接在内核空间中加密。这消除了将数据复制到用户空间以供 TLS 库加密,然后再复制回内核空间进行传输的需要。kTLS 还可以将 TLS 处理卸载到硬件
参考链接:https://people.freebsd.org/~gallatin/talks/euro2019-ktls.pdf,包括将 TLS 对称密码处理卸载到网络设备。
现代 Linux 和 FreeBSD 内核支持将 TLS 卸载到内核,现在 NGINX 开源版本也支持了!NGINX 1.21.4 引入了在使用 SSL_sendfile()
(参考链接:https://docs.openssl.org/master/man3/SSL_write/) 提供静态文件和缓存响应时对 kTLS 的支持,这可以极大地提高性能。如以下详细说明,内核和 OpenSSL 都必须构建了 kTLS,NGINX 才能使用 SSL_sendfile()
。
在本文章中,我们详细说明了哪些操作系统和 OpenSSL 版本支持 kTLS,并展示了如何构建和配置内核和 NGINX 以启用 kTLS。为了让你了解可以从 kTLS 中期待的性能提升,我们还分享了我们在 FreeBSD 和 Ubuntu 上进行测试的规格和结果。
「注意」:kTLS 实现相对较新且发展迅速。本文章描述了截至 2021 年 11 月的 kTLS 支持情况,但请注意关注 「nginx.org」 和 NGINX 文章上关于此处提供的信息和说明的更改公告。
一般要求
「操作系统」 — 以下二者之一:
FreeBSD 13.0 及以上版本。截至 2021 年 11 月,FreeBSD 13.0 及以上版本是唯一一个无需手动构建 NGINX 以整合 OpenSSL 3.0.0 及以上版本即可在 NGINX 中支持 kTLS 的操作系统。请参阅在 FreeBSD 上启用带有 kTLS 的 NGINX。
基于 Linux 内核版本 4.17 或更高版本的 Linux 发行版,尽管我们建议尽可能使用基于版本 5.2 或更高版本的发行版。(实际上,版本 4.13 就支持 kTLS,但 OpenSSL 3.0.0 需要内核头文件版本 4.17 或更高版本。)
「OpenSSL」 — 版本 3.0.0 或更高版本
「NGINX」 — 版本 1.21.4 或更高版本(主线版本)
「原文编辑」 — NGINX Plus R27 及更高版本支持在符合条件的基于 Linux 的操作系统版本上使用 kTLS;NGINX Plus R26 及更高版本支持在符合条件的 FreeBSD 版本上使用 kTLS。有关支持的操作系统的详细信息,请参阅 NGINX Plus 发行版页面。
操作系统支持
支持 kTLS 的操作系统
截至 2021 年 11 月,在 NGINX 开源版本支持的操作系统中,以下操作系统支持 kTLS 及其指示的密码。有关密码支持的详细信息,请参阅 TLS 协议和密码支持。
密码套件 | TLS_CHACHA20_POLY1305_SHA256 | |||
---|---|---|---|---|
「*」 内核版本必须是 5.10,而不是 4.14;请参阅不支持 kTLS 的操作系统以及 Amazon Linux 2 常见问题解答。
「**」 继承其上游源 RHEL 8 的 kTLS 支持状态。
「***」 请参阅 FreeBSD 提交日志 (链接地址: https://cgit.freebsd.org/src/commit/?id=6372fd253e32)。
不支持 kTLS 的操作系统
以下操作系统不支持 kTLS,原因如下:
Alpine Linux 3.11–3.14 — 内核是使用 CONFIG_TLS=n
选项构建的,这会禁用将 kTLS 作为模块或内核的一部分构建。Amazon Linux 2 — 默认的 Amazon Linux 2 AMI 的 Linux 内核版本是 4.14(请参阅 Amazon Linux 2 常见问题解答)。 CentOS 7.4+ — Linux 内核版本是 3.10。继承其上游源 RHEL 7.4+ 的 kTLS 支持状态。 Debian 10 和 11 — 内核是使用 CONFIG_TLS=n
选项构建的(请参阅 Debian 错误报告日志)。RHEL 7.4+ — Linux 内核版本是 3.10。 SLES 12 SP5+ — Linux 内核版本是 4.12。 Ubuntu 18.04 LTS — Linux 内核版本是 4.15。
TLS 协议和密码支持
如上所述,支持 kTLS 的操作系统在对 TLS 协议和密码的支持上存在差异。
对于 TLSv1.2,kTLS 模块支持以下密码:
AES128-GCM-SHA256
AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
对于 TLSv1.3,kTLS 模块支持以下密码套件:
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
(仅部分操作系统支持,具体参见支持 kTLS 的操作系统)
要验证您的 NGINX 二进制文件中启用的 OpenSSL 支持的 TLS 密码,请在您构建 NGINX 的目录中(例如,您的主目录)运行 openssl-3.0.0/.openssl/bin/openssl ciphers
命令。
在 NGINX 中启用 kTLS
正如引言中提到的,kTLS 提升了 NGINX 的性能,因为所有的加密和解密操作都在内核中完成。数据在被传递到网络栈进行传输之前,直接在内核空间中进行加密,从而消除了将数据复制到用户空间以供 TLS 库加密,然后再复制回内核空间进行传输的需要。
在内核中加载 kTLS
在现代 FreeBSD 和 Linux 发行版中,kTLS 通常作为模块构建(使用 CONFIG_TLS=m
选项)。在启动 NGINX 之前,您必须明确地将 kTLS 模块加载到内核中 *(参考链接: https://freebsdfoundation.org/wp-content/uploads/2020/07/TLS-Offload-in-the-Kernel.pdf)*。
在 FreeBSD 上,以 root
用户身份运行以下命令(如果没有特殊声明,均使用root用户身份执行):
$ kldload ktls_ocf.ko
$ sysctl kern.ipc.tls.enable=1
有关 FreeBSD 命令选项的详细信息,请参阅 ktls(4)
的手册页。
在 Linux 发行版上,以 root
用户身份运行以下命令(如果没有特殊声明,均使用root用户身份执行):
$ modprobe tls
在 FreeBSD 上启用带有 kTLS 的 NGINX
要在 FreeBSD 上启用 NGINX 的 kTLS 支持,您可以使用与 Linux 发行版相同的说明。但是,我们建议您按照以下步骤操作,以利用 FreeBSD Ports Collection 中 「security/openssl-devel」 端口构建的带有 kTLS 的 NGINX。有关更多信息,包括 kTLS 的概述,请参阅 FreeBSD 网站上的内核中的 TLS 卸载。
构建带有 kTLS 支持的 OpenSSL 3.0,选择配置菜单中的适当选项:
$ cd /usr/ports/security/openssl-devel && make config && make install
修改 「/etc/make.conf」 以使用 「openssl-devel」 作为默认的 SSL 库:
$ echo "DEFAULT_VERSIONS+=ssl=openssl-devel" >> /etc/make.conf
构建 NGINX:
$ cd /usr/ports/www/nginx-devel && make install
在 Linux 发行版上构建带有 kTLS 的 NGINX
大多数当前的 Linux 发行版包含的 OpenSSL 版本早于 3.0.0(通常是 1.1 版本)。因此,您需要从源代码构建 NGINX,并使用 OpenSSL 3.0.0。
在 configure
命令中启用 kTLS 支持的两个关键选项是:
--with-openssl=../openssl-3.0.0
--with-openssl-opt=enable-ktls
其他 configure
选项是为在 「nginx.org」 上提供的官方 NGINX 二进制包中包含的模块。您可以指定一组自定义模块。要查看当前 NGINX 二进制文件使用的构建选项,请运行 nginx -V
。
要使用 OpenSSL 3.0.0 构建 NGINX,请运行以下命令:
$ 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
「注意」:生成的 NGINX 二进制文件与 OpenSSL 3.0.0 库静态链接。如果您之后需要修补 OpenSSL,您必须下载并解包新的 OpenSSL 源代码存档,然后运行上述命令以重新构建 NGINX 二进制文件。
配置 NGINX
要启用 kTLS,请在 server{}
上下文中包含带有 Options KTLS
参数的 ssl_conf_command
(参考链接:https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_conf_command) 指令,如下所示的测试中使用的示例配置:
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;
}
}
}
实现更严格的PCI DSS合规标准的WEB服务器配置,请参考《Mozilla SSL Configuration Generator》
Nginx 1.27.3 和 OpenSSL 3.4.0 下的配置:
https://ssl-config.mozilla.org/#server=nginx&version=1.27.3&config=intermediate&openssl=3.4.0&guideline=5.7
❞
验证 kTLS 是否启用
要验证 NGINX 是否使用了 kTLS,请启用调试模式 (参考链接:https://docs.nginx.com/nginx/admin-guide/monitoring/debugging/) ,并在错误日志中检查 BIO_get_ktls_send()
和 SSL_sendfile()
。
$ grep BIO /var/log/nginx/error.log
2021/11/10 16:02:46 [debug] 274550#274550: *2 BIO_get_ktls_send(): 1
2021/11/10 16:02:49 [debug] 274550#274550: *3 BIO_get_ktls_send(): 1
$ grep SSL_sendfile /var/log/nginx/error.log
2021/11/10 16:02:46 [debug] 274550#274550: *2 SSL_sendfile: 1048576
2021/11/10 16:02:49 [debug] 274550#274550: *3 SSL_sendfile: 1048576
「注意」:我们建议您在完成这些检查后禁用调试模式,特别是在生产环境中。调试日志由于大量的写操作会产生性能损失;此外,调试日志可能会非常大,并迅速耗尽磁盘分区上的可用空间。
kTLS 带来的性能提升
在高负载下提供静态文件和缓存响应时,SSL_sendfile()
与用户空间 TLS 相比可以将吞吐量提高多达 2 倍,但性能提升的大小显著取决于各种因素(磁盘性能、系统负载等)。如果您的网卡支持 TLS 卸载,也有可能降低 CPU 使用率。
测试性能
要测量您的设置中的性能提升,请按照以下说明运行一个简单的单线程测试。正如以下详细说明,我们的测试结果表明,在没有任何特定调整的情况下,性能提升接近 30%。
使用的硬件和软件:
AWS t3.medium 实例,具有: 4 GB 内存 20 GB 通用 SSD Intel® Xeon® Platinum 8259CL CPU @ 2.50GHz,2 个核心 FreeBSD 13.0 和 Ubuntu 21.10 TLSv1.3,使用 TLS_AES_256_GCM_SHA384
密码套件NGINX 1.21.4,按照在 NGINX 中启用 kTLS 中指定的方式构建和配置。
要进行测试:
创建一个可以完全放入磁盘缓存的大文件:
$ #$ truncate -s 1g /data/1G
运行以下命令以检查吞吐量;多次重复基本命令以获得更准确的结果,并将输出通过管道传输到 FreeBSD 的 ministat
或 Ubuntu 的ministat
工具进行基本统计分析。
$ #$ for i in 'seq 1 100'; do curl -k -s -o /dev/null -w '%{speed_download}\n' https://localhost/1G | ministat
性能测试结果
在以下测试结果中,以 ministat
的输出形式呈现,每个值是下载速度(以 kBytes/second 为单位)。为了便于阅读,输出被分成了两行。
FreeBSD 13.0 未启用 kTLS 时的吞吐量:
N Min Max Median ...x 10 532225 573348 555616 ...
... Avg Stddev
... 555155.6 10239.137
FreeBSD 13.0 启用 kTLS 时的吞吐量:
N Min Max Median ...x 10 629379 723164 717349 ...
... Avg Stddev
... 708600.4 28304.766
Ubuntu 21.10 未启用 kTLS 时的吞吐量:
N Min Max Median ...x 10 529199 705720 662354 ...
... Avg Stddev
... 654321.6 48025.103
Ubuntu 21.10 启用 kTLS 时的吞吐量:
N Min Max Median ...x 10 619105 760208 756278 ...
... Avg Stddev
... 741848.3 43255.246
在我们的测试中,kTLS 在 FreeBSD 上的性能提升比 Ubuntu 更为显著。百分比提升如下:
总结
NGINX 1.21.4 引入了在使用 SSL_sendfile()
提供静态文件和缓存响应时对 kTLS 的支持。我们的测试表明,性能提升了 8% 到 29%,具体取决于操作系统。

優(yōu)網(wǎng)科技秉承"專業(yè)團隊、品質(zhì)服務(wù)" 的經(jīng)營理念,誠信務(wù)實的服務(wù)了近萬家客戶,成為眾多世界500強、集團和上市公司的長期合作伙伴!
優(yōu)網(wǎng)科技成立于2001年,擅長網(wǎng)站建設(shè)、網(wǎng)站與各類業(yè)務(wù)系統(tǒng)深度整合,致力于提供完善的企業(yè)互聯(lián)網(wǎng)解決方案。優(yōu)網(wǎng)科技提供PC端網(wǎng)站建設(shè)(品牌展示型、官方門戶型、營銷商務(wù)型、電子商務(wù)型、信息門戶型、微信小程序定制開發(fā)、移動端應(yīng)用(手機站、APP開發(fā))、微信定制開發(fā)(微信官網(wǎng)、微信商城、企業(yè)微信)等一系列互聯(lián)網(wǎng)應(yīng)用服務(wù)。