我们很高兴地宣布,NGINX Plus Release 26(R26)现已发布。NGINX Plus基于NGINX Open Source构建,是一款集软件Web服务器、负载均衡器、反向代理、内容缓存和API网关于一体的解决方案。
NGINX Plus R26 的新增和增强功能包括:
- 通过缓存JSON Web密钥集加快JWT验证,在过去几个版本持续增强JSON Web令牌(JWT)支持的基础上,我们引入了JSON Web密钥集(JWKS)的内存缓存,可显著降低JWT验证的开销。
- 强化的TLS握手:如果客户端通过ALPN提议的通信协议与待建立会话的NGINX配置上下文不匹配,NGINX Plus将拒绝TLS握手(例如,向
http{}上下文中的虚拟服务器提议使用IMAP电子邮件协议)。 - NGINX JavaScript 模块增强功能:现在支持使用
async和await关键字及Promise对象的异步函数,并已实现用于加密操作(例如生成随机数或加密 Cookie)的 WebCrypto API。
本次版本还新增了对IBM System Z (s390x)架构的支持、独立关闭TCP连接各方向的功能,以及对Perl兼容正则表达式(PCRE)库第2版的支持。
重要行为变更
NGINX JavaScript模块不再支持js_include
正如发布NGINX Plus R23时所宣布的,NGINX JavaScript模块的0.4.0版本使用js_import指令取代了js_include指令。js_include指令当时已弃用,自此版本起不再受支持。
升级到NGINX Plus R26之前,请将NGINX配置文件中的js_include替换为js_import,并在JavaScript文件中为NGINX配置所引用的函数添加export语句。请按以下步骤操作:
- 编辑NGINX配置文件。例如,将以下内容:
js_set $foo myFunction;- 更改为:
js_set $foo module_name.myFunction;- 将
js_include替换为js_import,并记下隐式的module_name(传递给该指令的JavaScript文件名参数,不含.js扩展名)。 - 在每个引用JavaScript函数的指令中,在函数名称前添加module_name。函数名称是这些指令的第一个参数;对于
js_set[HTTP][Stream]指令,函数名称是第二个参数。
- 编辑定义了NGINX配置文件中所引用函数的JavaScript(module_name.js)文件。在每个文件中添加如下所示的
export语句,并列出所引用的函数。
export default { myFunction, otherFunction }- The
export语句可以出现在.js文件中的任何位置,但通常放在函数的正上方或文件末尾。
Cookie-Flag模块已弃用
第三方Cookie‑Flag模块已在NGINX Plus R23中弃用,并且正如当时所公告的那样,自此版本起,该模块已无法再从NGINX模块存储库中获取。
升级到NGINX Plus R26之前,请编辑NGINX配置,将所有出现的“set_cookie_flag”指令(在已弃用的模块中定义)替换为内置的“proxy_cookie_flags”指令。
TLS协商不再支持NPN协议
NGINX建立TLS和HTTP/2连接的方式已更新。在NGINX与客户端(通常为浏览器)进行TLS握手时,双方会协商该握手所建立的会话要使用的通信协议(多数情况下,协商会将会话从HTTP 1.x升级到HTTP/2)。TLS的下一协议协商(NPN)扩展是最早用于此目的的方法,但NPN现已被视为过时,并由应用层协议协商(ALPN)扩展取代。该扩展发布为RFC 7301。
NGINX Plus R26不再支持NPN,因此客户端现在必须仅使用ALPN。
此外,我们扩展并强化了ALPN实现,详情请参阅“强化TLS握手”。
旧版NGINX Plus软件仓库不再更新
在NGINX Plus R24发布时,所有NGINX软件的程序包存储库均进行了重组,因此NGINX Plus的安装流程也随之发生变化。
安装或升级NGINX Plus时,操作系统的软件包管理器(apt、yum或同等工具)将配置为使用NGINX Plus软件仓库。
如果要在已配置为使用旧版plus-pkgs.nginx.com软件仓库的现有系统(运行NGINX Plus R23或更早版本)上升级到NGINX Plus R26,则必须更新软件包管理器,使其指向新的pkgs.nginx.com/plus软件仓库。请参阅F5知识库中的说明。
如果是首次安装NGINX Plus R26,请参阅《安装NGINX Plus》中的《NGINX Plus管理指南》。
旧存储库中不提供NGINX Plus R26,该存储库将不再接收更新。
NGINX Plus API的OpenAPI规范访问方式变更
NGINX Plus软件包不再包含NGINX Plus API的YAML格式OpenAPI规范和Swagger UI。现在可在NGINX Plus管理指南中访问这些内容。
平台支持变更
新增支持的操作系统和架构:
- Alpine Linux 3.15(x86_64,arm64)
- 采用CentOS 8.1+、RHEL 8.1+和Ubuntu 20.04的IBM Z Platform (s390x);请参阅IBM Z s390x架构支持
已移除旧版操作系统:
- Alpine Linux 3.11(支持的最低版本为3.12)
已弃用并计划在NGINX Plus R27中移除的旧版操作系统和架构:
- Power8架构(ppc64le)
- CentOS 8.1+
- Alpine Linux 3.12
新功能详解
通过缓存JSON Web密钥集加快JWT验证
验证JSON Web Token时,NGINX使用JSON Web Key Set(JWKS)验证令牌签名或解密令牌。JWKS既可以存储在配置文件中,也可以通过HTTP请求从外部服务获取。此外,在内存中缓存JWKS还有以下几项优势:
- 显著降低CPU使用率
- 降低请求延迟
- 简化JWT验证,因为在缓存过程中,JWKS密钥会从JSON转换为针对加密操作优化的二进制格式
要在内存中缓存JWKS,请添加新的auth_jwt_key_cache指令,并指定每个密钥集的过期时间(本例中为3小时):
正在加载代码示例…
从外部服务器获取JWK时,还建议配置标准的内容缓存,并添加proxy_cache_use_stale指令。该指令会让NGINX Plus在后台刷新已过期的JWKS期间继续提供该JWKS。
正在加载代码示例…
除JWKS缓存外,内容缓存还具有两方面的优势:
- 韧性:即使JWKS已过期,仍可从缓存中检索。当JWKS提供方暂时不可用时,这可以提高韧性,但代价是安全风险增加。
- 对授权服务器的影响:缓存的JWKS过期后,对授权服务器的影响会因JWKS缓存是单独使用还是与内容缓存结合使用而有所不同:
- 仅使用JWKS缓存时,所有传入的授权请求都会转发到授权服务器,直至缓存中重新填充已过期JWKS的新版本。如果授权服务器响应缓慢,针对JWKS的重复HTTP请求可能会突然增加。这些额外负载可能会使授权服务不堪重负,导致问题进一步恶化。
- 启用内容缓存并允许提供已过期的JWKS后,只有一个JWKS请求会转发到身份验证服务器,后续请求将进入队列,直到内容缓存填充完毕,NGINX能够处理这些请求。这样可以降低身份验证服务的负载,从而减少资源消耗。
强化TLS握手安全性
针对TLS的攻击(例如ALPACA)日益增多。为持续主动防御漏洞利用,我们已强化NGINX对TLS连接的处理。
应用层协议协商(ALPN)是TLS握手的一项可选扩展,客户端和服务器可在TLS握手期间使用该扩展,为握手所建立的加密会话选择要使用的第7层协议。ALPN最常见的用例是协商将浏览器与Web服务器或应用服务器之间的会话从HTTP/1.x升级到HTTP/2。

如果客户端通过ALPN提议的协议与正在建立的会话所对应的NGINX配置上下文不匹配,NGINX Plus现在会拒绝TLS握手。例如,在http{}上下文中定义的虚拟服务器需要HTTP的ALPN协议ID,而在mail{}上下文中定义的虚拟服务器则需要SMTP、POP或IMAP的协议ID。
NGINX Plus R26 引入了$ssl_alpn_protocol[HTTP][Stream]变量,用于捕获协商后的协议。(在$ssl_preread_alpn_protocols变量于stream{}上下文中随NGINX Plus R15引入,仍用于捕获客户端在握手期间通告的所有协议列表。)
此代码片段定义了alpn日志格式,该格式使用$ssl_alpn_protocol,将协议写入访问日志条目的alpn=字段。
正在加载代码示例…
新的“ssl_alpn”指令在“stream{}”上下文中定义NGINX Plus接受的协议。省略该指令后,NGINX Plus将考虑客户端提供的所有协议。
正在加载代码示例…
NGINX JavaScript模块增强功能
NGINX Plus R26集成了0.7.2版NGINX JavaScript模块(njs),并包含两项增强功能:
- 增强了对异步函数的支持,支持ECMAScript 6中引入的
async和await关键字以及Promise对象 - WebCrypto API的实现
注意:本节假定您了解用于异步操作和加密操作的JavaScript结构。对代码片段的完整分析不在本博客的讨论范围内。
[编辑注:本节所述用例只是NGINX JavaScript模块众多用例中的一部分。有关完整列表,请参阅《NGINX JavaScript模块用例》。]
增强对异步函数的支持
在PHP等许多常用脚本语言中,命令和函数会同步执行。也就是说,脚本调用函数后会暂停(停止执行),直到该函数返回结果。
JavaScript也可以异步运行:异步调用函数时,脚本会继续执行,而不会等待函数返回结果。
请看以下示例脚本:
正在加载代码示例…
它返回空响应,因为njs运行时不会等待定义的超时期限结束(如果等待,输出将为b,a):
$ curl http://127.0.0.1/
$ 要获得预期结果,正确处理异步操作显然至关重要。JavaScript提供了多种处理方式,但在常见的NGINX用例中,通常只需封装异步函数,使执行流程同步即可。这时就需要使用Promise对象以及async和await关键字。
ECMAScript 6(JavasScript的ECMA‑262语言规范第6版)将Promise对象定义为异步函数的返回类型。该对象有以下3种状态之一:
- 已兑现,操作已成功完成
- rejected,操作失败
- pending,初始状态(既未兑现,也未拒绝)
使用关键字async定义JavaScript函数,会将该函数的返回类型设置为Promise。编写处理Promise对象的njs函数时,async和await关键字非常重要。
请看以下示例:
正在加载代码示例…
The fs.readFile函数(第12行)返回一个Promise。该函数封装在自定义async函数中,以确保仅当文件名为fs.readFile()时才调用user.text。由于使用了await关键字,封装函数会等待Promise完成,然后返回数据。
将fs.readFile()封装在另一个函数中,可以更轻松地捕获错误;async函数中的任何异常都会将Promise的状态设置为rejected。另一种方法是将第 9 行替换为返回已拒绝Promise的语句:
正在加载代码示例…
也可以直接使用Promise对象。在以下示例中,Promise.resolve函数分别为p1和p2返回一个Promise。Promise.all函数会等待p1和p2对应的Promise均得到解析,然后再返回结果。
正在加载代码示例…
现在,curl命令的输出符合预期(请注意,由于超时值较短,b会先返回):
$ curl http://127.0.0.1/b,a
$ 使用WebCrypto API实现新的加密功能
NGINX JavaScript现在可通过WebCrypto API使用增强的加密功能。njs的常见加密用例包括:
- 为会话ID生成安全随机数
- 加密和解密消息、数据及Cookie
- 使用对称和非对称加密算法创建或验证数字签名
以下njs代码会生成一个随机数:
正在加载代码示例…
以下NGINX Plus配置会调用njs代码:
正在加载代码示例…
该函数会输出一个随机数,如下所示:
$ curl 127.0.0.123225320050,3668407277,1101267190,2061939102,2687933029,2361833213,32543985,4162087386WebCrypto中的getRandomValues函数非常适合用于初步了解安全随机数和WebCrypto。该函数的实现相当简单,并且会直接返回结果,而不是返回Promise。
不过,其他一些计算量更大的WebCrypto加密函数采用异步方式运行。例如,有关сrypto.subtle.digest()的文档指出:
为给定数据生成摘要。参数包括要使用的摘要算法标识符和要生成摘要的数据。返回一个Promise,该 Promise 将以生成的摘要兑现。
因此,直接调用“сrypto.subtle.digest()”并不能保证下一步可以获取其结果,除非将其封装在“async”函数中。这里使用关键字“async”和“await”将其封装在函数中,以确保函数返回前,结果已赋给hash变量:
正在加载代码示例…
此NGINX Plus配置中的js_set指令会将$hosthash变量的值设置为setReturnValue函数返回的值(该函数封装在host_hash函数中):
正在加载代码示例…
以下示例对主机名“example.com”进行哈希处理。
$ curl -H "Host: example.com" 127.0.0.1#
e8e624a82179b53b78364ae14d14d63dfeccd843b026bc8d959ffe0c39fc4ded1f4dcf4c8ebe871e657a12db6f11c3af87c9a1d4f2b096ba3deb56596f06b6f4NGINX Plus R26 的其他增强功能
支持IBM Z(s390x)架构
随着现代应用不断拓展到各种数字环境,NGINX等关键支撑组件也需要随之部署。因此,我们很高兴地宣布,NGINX Plus现已支持采用CentOS 8.1+、RHEL 8.1+和Ubuntu 20.04的IBM Z (s390x)架构。希望利用现有大型机资源托管现代应用的组织,现在可以部署NGINX和NGINX Plus,将其用作基于软件的Web服务器、负载均衡器、反向代理、内容缓存和API网关。
Stream模块支持TCP半关闭
新的proxy_half_close指令支持独立关闭TCP连接的各个方向,从而提高stream{}上下文中的效率。
PCRE2库支持
旧版NGINX Plus使用Perl兼容正则表达式(PCRE)库(版本1)来评估NGINX配置中使用的正则表达式。这个重要的开源项目最近已终止维护,并由PCRE2取代。NGINX Plus使用PCRE2构建,但同时支持使用PCRE和PCRE2构建的动态模块,具体取决于底层操作系统提供的版本。无需更改配置。
升级或试用 NGINX Plus
如果您正在运行NGINX Plus,我们强烈建议尽快升级到NGINX Plus R26。升级后还可获得多项其他修复和改进,并有助于NGINX在您需要提交支持工单时提供帮助。
如果您尚未体验过NGINX Plus,建议立即试用。它可用于安全防护、负载均衡和API网关,也可作为获得全面支持的Web服务器,并提供增强的监控和管理API。立即开始30天免费试用。
关于作者
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。

