Nginx启用kTLS提升https性能

介绍

自从https普及以来,tls的性能开销一直是web的痛,针对这tls的性能调优一直是经久不衰的话题,协议层面比如握手优化、session复用,算法层面比如ChaCha20-Poly1305,硬件层面cpu的硬件支持等

如今,系统层面也有了一种新的优化,就是kTLS(Kernel TLS)。

Kernel TLS 其实就是将原本TLS的过程放到内核中来做,甚至如果网卡本身支持的话可以直接交给网卡。

目前nginx已经支持了ktls,是在 SSL_sendfile() 传输静态文件时引入了 kTLS 支持,毕竟改动不大,所以支持的比较快。(不像http3,已经延期一年了)

要求

kTLS 很早就引入了,但是直到最近也才可用,只要是一直在增加功能,现在各方组件基本已经完善可用了。所以自己尝尝鲜。
要求:

  • 内核版本 4.17+
  • openssl 3.0.0+
  • Nginx 1.21.4+

具体操作系统支持如下:

TLSv1.2 密码TLSv1.3
密码套件
TLS_CHACHA20_POLY1305_SHA256 密码Linux 内核版本
Amazon Linux 2*5.10
CentOS 8**4.18
FreeBSD 13.0❌ ***N/A
RHEL 84.18
SLES 15 SP25.3
Ubuntu 20.04 LTS❌​​5.4
Ubuntu 21.045.11
Ubuntu 21.105.13

但表格中并未列出Ubuntu22.04和RockyLinux9系统,这两款操作系统都是今年才发布的。

另外还要注意一下,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(仅部分操作系统)

下面开始

本次演示基于

  • 操作系统:Ubuntu 22.04
  • Nginx:nginx-1.23.1
  • Openssl:3.0.5

1. 编译Nginx

# 下载nginx源码
wget https://nginx.org/download/nginx-1.23.1.tar.gz

# 下载openssl源码
https://www.openssl.org/source/openssl-3.0.5.tar.gz

# 安装依赖
apt install libpcre3-dev zlib1g-dev libxml2-dev libxslt-dev install libgd-dev

# 编译
./configure \
--user=www-data \
--group=www-data \
--prefix=/usr/share/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--lock-path=/var/lock/nginx.lock \
--pid-path=/run/nginx.pid \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
--http-scgi-temp-path=/var/lib/nginx/scgi \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-scgi-temp-path=/var/lib/nginx/scgi \
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
--with-compat \
--with-debug \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_v2_module \
--with-http_dav_module \
--with-http_slice_module \
--with-threads \
--with-http_addition_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-stream \
--with-stream_realip_module \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-openssl=../openssl-3.0.5 \
--with-openssl-opt=enable-ktls \
--with-cc-opt='-g -O2 -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' \
--with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -fPIC'

make -j$(nproc --all)
make install

构建参数基本基于Ubuntu22.04原版分发的Nginx。以下异同:

  • 不引入额外的源码比如pcre,zlib等通过apt安装前置依赖
  • 文件生成路径,完全按照原版参数构建的话,是不会和apt安装的路径一样的
    正常apt install nginx的话会安装如下包:
    libnginx-mod-http-geoip2 libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libnginx-mod-stream-geoip2 nginx-common nginx-core
    可以看出原版Ubuntu nginx分发的包是拆开的,本次构建只添加了stream相关模块,其他模块未包含
  • kTLS 构建参数,就两行

    –with-openssl=../openssl-3.0.5
    实际上openssl用ubuntu原本分发的openssl-dev就行,不过由于openssl是关键,未避免不必要的情况,采用源码构建

    –with-openssl-opt=enable-ktls
    启用kTLS

注意:构建完成后还需建立如下目录,构建过程中不会自动生成

mkdir -p /var/lib/nginx/body
mkdir -p /var/lib/nginx/fastcgi
mkdir -p /var/lib/nginx/proxy
mkdir -p /var/lib/nginx/scgi
mkdir -p /var/lib/nginx/uwsgi

如果需要查看openssl支持的TLS密码套件,在openssl源码目录下执行:

.openssl/bin/openssl ciphers

2. 加载ktls模块

# 手动加载
modprobe tls
# 开机挂载
echo tls > /etc/modules-load.d/modules.conf

3. Nginx配置文件

在原来配置ssl相关地方增加一行

ssl_conf_command Options KTLS;

可选择在http或者server中添加

4. 验证

日志开启debug,需要构建参数中添加 –with-debug,否则设置了也不生效。
出现BIO_get_ktls_send 和 SSL_sendfile 代表生效

tail -f /var/log/nginx/error.log | grep -E "BIO_get_ktls_send|SSL_sendfile"
2022/09/11 20:42:09 [debug] 980#980: *43 BIO_get_ktls_send(): 1
2022/09/11 20:42:09 [debug] 982#982: *44 BIO_get_ktls_send(): 1
2022/09/11 20:42:10 [debug] 982#982: *40 SSL_sendfile: 3304
2022/09/11 20:42:29 [debug] 982#982: *51 BIO_get_ktls_send(): 1
2022/09/11 20:42:30 [debug] 982#982: *51 SSL_sendfile: 3304
2022/09/11 20:42:31 [debug] 980#980: *53 BIO_get_ktls_send(): 1
2022/09/11 20:42:49 [debug] 980#980: *57 BIO_get_ktls_send(): 1

参考

https://juejin.cn/post/7104795466809753607
https://www.nginx-cn.net/blog/improving-nginx-performance-with-kernel-tls/#oss-without-support

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注