很高兴宣布推出 NGINX Plus Release 31(R31)版本。NGINX Plus 基于 NGINX 开源版构建而成,是唯一一款将软件 Web 服务器、负载均衡器、反向代理、内容缓存和 API 网关集于一身的多合一产品。
NGINX Plus R31 的新增特性和增强特性包括:
- 原生 NGINX 使用报告 – NGINX Plus 现在原生支持报告整个企业的 NGINX 部署情况,便于在 NGINX Instance Manager 中全面了解 NGINX 基础设施。该功能有助于加强对 NGINX 实例的治理,以确保合规性。
- SNI 配置的增强功能 – 此前,通过使用 proxy_ssl_name 指令传递服务器名称标识(SNI)的服务器名称,并由上游组中的所有服务器使用。NGINX Plus R31 允许将此 SNI 设置为选定的上游服务器。
- 使用 NGINX JavaScript 定期执行任务 – NGINX JavaScript 引入了 js_periodic 指令,允许定期运行内容。该增强功能无需设置 cron 作业,可配置为在所有或特定 worker 进程中运行,以实现最佳性能。
- 提升 NGINX 启动体验 – 针对配置中包含大量“locations”的情况,NGINX Plus R31 可整体提升 NGINX 的启动体验。
- QUIC+HTTP/3 优化和改进 – NGINX Plus R31 为 QUIC 实现引入了许多增强功能和性能优化,包括支持路径最大传输单元(MTU)发现、改进拥塞控制,并能够在整个 QUIC 会话中重用加密上下文。
此外,该版本还包括从 NGINX 开源版继承的新功能和漏洞修复,以及对 NGINX JavaScript 模块的更新。
重要行为变更
注:如果您不是从 NGINX Plus R30 升级至 NGINX Plus R31,请务必查看之前公告博客中的“重要行为变更”部分,了解当前版本和最新版本之间所有版本的嬗变过程。
弃用 OpenTracing 模块
NGINX Plus R18 中引入的 OpenTracing 模块正逐渐被弃用,计划自未来的 NGINX Plus R34 版本起不再提供。但在此之前,该模块包将包含在所有 NGINX Plus 版本中。我们强烈建议您使用 NGINX Plus R29 中引入的 OpenTelemetry 模块。
未报告 NGINX 使用情况的警告消息
NGINX Plus 用户必须向 F5 报告其 NGINX 使用情况,以确保合规性。随着 NGINX Plus R31 的发布,向 NGINX Instance Manager 报告 NGINX 使用情况的功能已原生存在,并默认启用。如果 NGINX 实例因故无法向 NGINX Instance Manager 提供其使用信息,一条警告消息则会被记录到日志中。
如欲详细了解如何在您的环境中配置这一功能,请参阅本文下方“原生 NGINX 使用报告”一节。
平台支持的变更
全新操作系统支持:
- FreeBSD 14
- Alpine 3.19
不再支持的旧版操作系统:
- Alpine 3.15,已于 2023 年 11 月 1 日停服
以下旧版操作系统已弃用,并计划在 NGINX Plus R32 中移除:
- FreeBSD 12,已于 2023 年 12 月 31 日停服
新增特性详情
原生 NGINX 使用报告
NGINX Plus R31 引入了与您网络环境中的 NGINX Instance Manager 的原生通信功能,可自动实现许可合规性。若您使用 F5 灵活使用购买计划(FCP),则不必再手动跟踪您的 NGINX Plus 实例。
默认情况下,NGINX Plus 会尝试在启动时通过对 nginx-mgmt.local
主机名进行 DNS 查询来发现 NGINX Instance Manager。虽然主机名可以配置,但为了简单起见,我们建议将一条 A 记录添加到本地 DNS 中,从而将默认主机名与运行 NGINX Instance Manager 的系统的 IP 地址关联起来。然后,NGINX Plus 将与 NGINX Instance Manager 建立 TLS 连接,每 30 分钟报告一次其版本号、主机名和唯一标识符。
为了进一步加强保护,我们还建议使用可选的 mgmt
配置块以通过 mTLS 配置此连接。然后,NGINX Instance Manager 会定期向 F5 服务报告 NGINX Plus 实例的总体使用情况。
如果 NGINX Plus 在解析 nginx-mgmt.local
主机名或与 NGINX Instance Manager 通信时遇到任何问题,您将在错误日志中看到一条警告消息。
以下为显示 NGINX Plus 实例无法解析 nginx-mgmt.local
的错误消息示例:
2023/12/21 21:02:01 [warn] 3050#3050: usage report: host not found resolving endpoint "nginx-mgmt.local”
以下为显示 NGINX Plus 实例与 NGINX Instance Manager 通信时出现了问题的错误消息示例:
2023/12/21 21:02:01 [warn] 3184#3184: usage report: connection timed out
自定义 mgmt
配置块设置
如果您希望微调 NGINX Plus 实例与 NGINX Instance Manager 的通信方式,则可选择使用新增的 mgmt
配置块和相关指令,通过定义自定义解析器、使用 IP 地址或备用主机名来识别 NGINX Instance Manager 系统、指定 TLS 选项、使用 mTLS 增强安全防护,并指定其他自定义参数。
以下是自定义配置示例:
mgmt {
usage_report endpoint=instance-manager.local interval=30m;
resolver 192.168.0.2; # Sample internal DNS IP
uuid_file /var/lib/nginx/nginx.id;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers DEFAULT;
ssl_certificate client.pem;
ssl_certificate_key client.key;
ssl_trusted_certificate trusted_ca_cert.crt;
ssl_verify on;
ssl_verify_depth 2;
}
有关这些指令的更多详细信息,请参阅产品文档。
有关下载和安装 NGINX Instance Manager 的更多信息,请参阅《安装指南》。
注:如果您使用的是早期版本的 NGINX Plus,则仍可按照这些说明报告您的实例。
SNI 配置的增强功能
在此版本之前,NGINX Plus 假定上游组中的所有服务器别无二致。这意味着它们需要能够处理相同的请求,响应相同的 SNI 名称(使用 proxy_ssl_server_name
时),并返回与相同名称匹配的 SSL 证书。
但在某些情况下,仅这些行为是不够的。例如,多台虚拟服务器共享一个上游服务器,并需要通过不同的 SNI 和/或主机请求头进行区分,以便将请求路由到特定资源。亦或是,上游组中的所有服务器无法使用相同的证书,或者将上游服务器放入不同的上游组受到限制。
NGINX Plus R31 引入了 SNI 支持,可按上游服务器进行配置。变量 $upstream_last_server_name
指的是所选上游服务器的名称,可使用 proxy_ssl_server_name
和 proxy_ssl_name
指令传递给代理服务器。
以下显示了如何将 proxy_ssl_server_name
设置为 on,以便服务器名称能够通过 SNI 传递:
proxy_ssl_server_name on;
下面是使用 proxy_ssl_name
传递所选上游服务器名称的方法:
proxy_ssl_name
$upstream_last_server_name;
使用 NGINX JavaScript 定期执行任务
NGINX JavaScript v0.8.1 引入了一个新指令 js_periodic
。该指令可在 http
和 stream
上下文中使用,允许指定一个 JavaScript 内容处理器定期运行。在自定义代码需要定期运行并可能需要访问 NGINX 变量的情况下,该功能非常实用。内容处理器会接收一个会话对象作为参数,而且还可访问全局对象。
默认情况下,内容处理器在 worker 进程 0 上运行,但也可将其配置为在特定或所有 worker 进程上运行。
该指令可在 location
上下文中使用:
example.conf:
location @periodics {
# 在 worker 进程 1 和 3 中每隔 15 分钟运行一次
js_periodic main.handler interval=900s worker_affinity=0101;
resolver 10.0.0.1;
js_fetch_trusted_certificate /path/to/certificate.pem;
}
example.js:
async function handler(s) {
let reply = await ngx.fetch('https://nginx.org/en/docs/njs/');
let body = await reply.text();
ngx.log(ngx.INFO, body);
}
有关语法和配置详细信息,请参阅 NGINX JavaScript 文档。
提升 NGINX 启动体验
在 NGINX 配置包含大量“locations”的情况下,NGINX 启动可能会花费较长时间。在很多情况下,这可能是不可接受的。导致这个问题的根本原因是用于对 locations 列表进行排序的排序算法。
NGINX R31 引入了一项增强功能,可将现有排序算法从插入排序(时间复杂度为 O(n2)
)替换为归并排序(时间复杂度为O(n*log n)
)。
我们看到在此更新后,在具有 20,000 个 locations 的测试配置中,总启动时间从 8 秒缩短到了 0.9 秒。
QUIC+HTTP/3 优化和改进
NGINX Plus R31 为 QUIC+HTTP/3 实现引入了多项增强功能和性能优化,例如:
- 使用 QUIC+HTTP/3 时路径最大传输单元(MTU)发现 – 路径 MTU 是可通过网络传输的最大数据帧或数据包的字节度量值。在此变更之前,QUIC 实现对所有数据报使用 1,200 字节的路径 MTU。NGINX Plus 现在支持发现路径 MTU 大小,然后将其用于所有传出数据报。
- 在整个 QUIC 会话中重用加密上下文 – 这一优化与 QUIC 数据包的加密和解密行为有关。此前,每次加密或解密操作都要创建单独的加密上下文。现在,整个 QUIC 会话都使用同一上下文,因此性能得以提高。
其他性能优化包括:减少发送确认数据包时可能出现的延迟、将确认(ACK)数据帧放在队列的前面以减少数据帧重传和 ACK 数据帧传送延迟,以及改进通用分段卸载(GSO)模式下的拥塞控制行为。
NGINX Plus R31 中的其他增强功能和漏洞修复
其他 mgmt
模块
在 NGINX Plus R31 中,ngx_mgmt_module
支持您向 NGINX Instance Manager 报告 NGINX 使用信息,其中包括 NGINX 主机名、NGINX 版本及唯一实例标识符。
该模块提供了多个指令,用于微调 NGINX 实例与 NGINX Instance Manager 的通信方式。有关可用指令和配置选项的完整列表,请参阅 NGINX 文档。
MQTT 模块中的漏洞修复
NGINX Plus R29 引入了消息队列遥测传输(MQTT),并针对 MQTT 模块中发现的问题进行了一些漏洞修复。
其中的一个重要的修复解决了在未提供密码的情况下 CONNECT 消息被拒绝的问题。以前,我们认为填写用户名字段后就必须输入密码。然而,在 MQTT 规范中有一些特殊情况,例如匿名身份验证不要求提供密码。该漏洞修复通过查看数据包的 cflags
字段,有条件地检查是否需要密码。如果未设置该标志,则表示不必提供密码。
另一漏洞修复是,当信息长度小于接收的字节数时,将停止解析 MQTT CONNECT 信息。
使用变量支持 HTTP/3 server_tokens
NGINX Plus R31 增加了对 HTTP/3 连接中缺失的 server_tokens
变量的支持。string
字段可用于明确设置错误页面上的签名和“Server”响应头字段值。如果 string 字段为空,则会禁用“Server”字段的生成。
从 NGINX 开源版继承的变更
NGINX Plus R31 基于 NGINX 开源版 1.25.3,继承了自 NGINX Plus R30 发布以来(NGINX 1.25.2 和 1.25.3)的功能变更、特性及漏洞修复。
特性
- 使用 QUIC 时执行路径 MTU 发现 – 此前,所有数据报都使用 1200 MTU 的默认大小。作为 QUIC+HTTP/3 改进的一部分,我们现在支持发现路径 MTU 大小,然后将其用于所有传出数据报。
- QUIC 的性能优化 – NGINX 主线版本 1.25.2 引入了 QUIC 实现的优化,以便在整个 QUIC 会话中重用加密上下文。这可减少发送 ACK 数据包的延迟,并将 ACK 数据帧放在队列的前面,从而减少数据帧重传和 ACK 数据帧传送延迟。
- 使用 HTTP/3 时支持
TLS_AES_128_CCM_SHA256
密码套件 – 这一增强功能为 QUIC 增添了TLS_AES_128_CCM_SHA256
支持,后者是 NGINX QUIC 实现目前唯一不支持的密码套件。OpenSSL 默认禁用该功能,但可通过以下指令启用:ssl_conf_command Ciphersuites TLS_AES_128_CCM_SHA256
; - 在加载 OpenSSL 配置时提供
nginx
appName – 当使用OPENSSL_init_ssl()
接口时,NGINX 现在不再检查OPENSSL_VERSION_NUMBER
,而是测试OPENSSL_INIT_LOAD_CONFIG
是否已定义且为真。这可确保该接口不会与 BoringSSL 和 LibreSSL 共用,因为它们不提供额外的库初始化设置(特别是OPENSSL_INIT_set_config_appname()
调用)。
变更
- NGINX 队列排序算法变更 – 如上所述,NGINX 现在使用归并排序,其时间复杂度为
O(n*log n)
。这有助于提升 NGINX 启动体验,特别是当配置中有大量“位置”时。 - HTTP/2 迭代流处理限制 – 这一改进通过限制一个事件循环中可引入的新数据流数量,确保及早检测到 NGINX 上的洪水攻击。该限值是阈值的两倍,并使用
http2_max_concurrent_streams
进行配置。在发送请求后立即重置数据流的情形中,即使从未达到允许并发流的最大阈值,也会对账户应用该限值。
漏洞修复
- 修复了 HTTP/2 自动检测的缓冲区管理问题 – 作为针对普通 TCP 连接的 HTTP/2 自动检测的一部分,初始数据首先读入
client_header_buffer_size
指令指定的缓冲区,后者没有状态保存功能。这会导致一个问题,即在保存状态时,缓冲区可能已被过度读取。当前漏洞修复允许仅读取可用的缓冲区大小,而非固定的缓冲区大小。该漏洞首次出现在 NGINX 主线版本 1.25.1(NGINX Plus R30)中。 - OpenSSL 兼容模式中的错误传输模式 – 在此版本之前,如果客户端发送的传输参数有误,OpenSSL 兼容层会引致连接延迟。该漏洞修复能够轻松处理这种行为,具体方法是首先通知用户参数有误,然后关闭连接。
- 修复了对不带原因短语的状态请求头的处理问题 – 根据通用网关接口(CGI)规范,
Status: 404
等“原因短语”为空的状态请求头有效,但在解析过程中会丢失尾随空格,进而导致响应中出现HTTP/1.1 404
状态行。由于缺少尾随空格,这违反了 HTTP 规范。通过该漏洞修复,NGINX 将仅使用这种较短状态请求头行中的状态代码,自己生成状态行,其中包含空格和相应原因短语(如有)。 - 修复了使用 PCRE2 重新加载配置时的内存泄露问题 – 当 NGINX 被配置为在版本 1.21.5 或更高版本中使用 PCRE2 时,就会出现这个问题。
有关从最新版本继承的新变更、特性、漏洞修复及变通方案的完整列表,请参见 NGINX 变更文件。
NGINX JavaScript 模块的变更
NGINX Plus R31 包含 NGINX JavaScript(njs)模块版本 0.8.2 的变更。以下是 njs 自 0.8.0(NGINX Plus R30 版本的一部分)以来的重大变更列表。
特性
- 引入了控制台对象。引入了以下方法:
error()
、info()
、log()
、time()
、timeEnd()
及warn()
。 - 为
http
和stream
引入了js_periodic
指令,允许指定 JS 处理器定期运行。 - 实现了共享字典的
items()
方法。该方法返回所有未过期的键值对。
变更
- 扩展了“fs”模块。添加了
existsSync()
方法。
漏洞修复
- 修复了“xml”模块。修复了
parse()
方法中错误的 XML 异常处理问题。 - 修复了使用全局正则表达式(regexp)和 Unicode 输入的
RegExp.prototype.exec()
问题。 - 修复了共享字典的
size()
和keys()
方法。 - 修复了 0.8.0 中引入的
r.internalRedirect()
的错误异常问题。 - 修复了
Object.getOwnPropertyNames()
中键的错序问题。 - 修复了 Fetch API 中较大 Content-Length 的 HEAD 响应处理问题。
- 修复了共享字典的
items()
方法。
有关所有特性、变更及漏洞修复的完整列表,请参阅 njs 变更日志。
升级或试用 NGINX Plus
如果您是 NGINX Plus 用户,我们强烈建议您尽快升级到 NGINX Plus R31。除了上述所有新特性以外,您还将获得更多修复和改进。升级到最新版本有助于 NGINX 团队在您需要时为您快速提供支持。
如果您还不是 NGINX Plus 用户,我们建议您立即申请试用。您可将其用于安全防护、负载均衡及 API 网关用例,或者用作 Web 服务器 — 采用增强型监控和管理 API 并可获得全面的支持服务。请立即下载 30 天免费试用版。