BLOG | NGINX

隆重推出 NGINX Plus R29

NGINX-Part-of-F5-horiz-black-type-RGB
Prabhat Dixit 缩略图
Prabhat Dixit
Published May 02, 2023
Michael Vernik 缩略图
Michael Vernik
Published May 02, 2023

很高兴宣布推出 NGINX Plus Release 29 (R29) 版本。NGINX Plus 基于 NGINX 开源版构建而成,是唯一一款将软件 Web 服务器、负载均衡器、反向代理、内容缓存和 API 网关集于一身的多合一产品。
NGINX Plus R29 的新增特性包括:

  • 支持 MQTT 协议 — 消息队列遥测传输 (MQTT) 是一种轻量级协议,用于物联网 (IoT) 设备之间通信。NGINX Plus R29 通过 PrereadFilter 模块支持 MQTT 协议,这些模块引入了多个新指令和变量,有助于管理并保护 MQTT 流量。
  • 支持 SAML 身份验证和授权 — 安全防护声明标记语言 (SAML) 是一种成熟的协议,可为 Web 应用提供单点登录 (SSO)。NGINX Plus 现在可以配置为 SAML 服务提供商 (SP),以通过 SAML 身份验证供应商 (IdP) 对用户进行身份验证。
  • 原生 OpenTelemetry — OpenTelemetry (OTel) 是一个框架,它能够以不受厂商限制的方式从远程数据源生成、收集并导出遥测数据(链路追踪、指标及日志)。全新 NGINX OTel 动态模块可为 NGINX Plus HTTP 请求跟踪提供高性能 OTel 实现。
  • 实验性 QUIC+HTTP/3 包 — 支持 QUIC+HTTP/3 的 NGINX Plus R29 预览包现已推出。NGINX Plus R29 QUIC 包可支持 HttpContext 和一系列新指令,以管理 QUIC 连接和 HTTP/3 流量。

重要行为变更

:如果您不是从 NGINX Plus R28 升级至 NGINX Plus R29,请务必查看之前的公告博客中的“重要行为变更”部分,了解当前版本和最新版本之间所有版本的嬗变过程。

软件包代码库的变更

随着 NGINX Plus R29 的发布,旧软件包代码库 plus-pkgs.nginx.com 将立即停用。该代码库自 NGINX Plus R25 以来一直没有更新,强烈建议您使用 NGINX Plus R24 中引入pkgs.nginx.com 软件包代码库。

平台支持的变更

全新操作系统支持:

  • Amazon Linux 2023

不再支持的旧版操作系统:

  • Alpine 3.13,已于 2022 年 11 月 1 日停服

以下旧版操作系统已弃用并计划在 NGINX Plus R30 中移除:

  • Ubuntu 18.04,将于 2023 年 6 月停服
  • Alpine 3.14,将于 2023 年 5 月停服

根据 ModSecurity 生命周期终止公告做出调整

根据 ModSecurity 生命周期终止公告,NGINX Plus R29 不再支持 ModSecurity 软件包。作为使用 ModSecurity 软件包的 NGINX Plus 客户,您很快便可选择参加 ModSecurity 和 NGINX App Protect 之间的折价换购计划。有关该计划的详细信息将很快公布,您可以联系您的 F5 客户代表,了解更多信息。

新增特性详情

支持 MQTT 协议

MQTT(消息队列遥测传输)是一种常用的轻量级发布-订阅消息协议,非常适合通过互联网连接物联网设备和应用(客户端)。它支持客户端围绕特定主题发布消息并订阅其他主题。订阅的客户端会收到围绕该主题发布的所有消息,从而在许多设备和服务之间实现高效的、支持容错的数据交换。

MQTT 架构的核心是 Broker。Broker 是一台服务器,负责跟踪客户端及其订阅的任何主题、处理消息,并将这些消息路由到相应系统。NGINX Plus R29 支持 MQTT 3.1.1MQTT 5.0。它充当了客户端和 Broker 之间的代理,可简化系统架构,卸载任务,并降低成本。

初始 MQTT 特性集支持:

  • MQTT Broker 负载均衡
  • 会话保持(将客户端重新连接到同一 Broker)
  • TLS 卸载
  • 客户端证书身份验证
  • CONNECT 消息解析和重写

MQTT 协议定义了几种消息类型,包括 CONNECT、PUBLISH 和 SUBSCRIBE。NGINX Plus R29 能够主动解析并重写 MQTT CONNECT 消息的部分内容,从而构建以前只能通过自定义脚本创建的配置场景。

MQTT 消息解析和重写必须在 NGINX 配置文件的 Stream 上下文中进行定义,并可通过 ngx_stream_mqtt_preread_module
ngx_stream_mqtt_filter_module 模块实现。

MQTT 示例

通过修改 MQTT 设备发送的默认客户端标识符,NGINX 可以隐藏敏感信息,例如设备的序列号。在第一个示例中,标识符被重写为设备的 IP 地址。

注:不建议在生产环境中使用设备的 IP 地址作为 MQTT 客户端标识符。

stream {      mqtt on;
    server {         listen 1883;         proxy_pass 10.0.0.8:1883;         mqtt_rewrite_buffer_size 16k;         mqtt_set_connect clientid '$remote_addr';     } }

鉴于 MQTT 客户端的短连接行为,因此您不能仅依靠设备的主机名或 IP 地址来与负载均衡的 Broker 建立会话保持。在本例中,设备的 MQTT 客户端标识符作为哈希键,用于持久连接到负载均衡集群中的各个 MQTT broker:

stream {      mqtt_preread on;
    upstream brokers{         zone tcp_mem 64k;         hash $mqtt_preread_clientid consistent;
        server 10.0.0.7:1883; # mqtt broker 1         server 10.0.0.8:1883; # mqtt broker 2         server 10.0.0.9:1883; # mqtt broker 3     }
    server {         listen 1883;         proxy_pass brokers;         proxy_connect_timeout 1s;     } }

后续步骤

NGINX Plus 中 MQTT 的后续开发可能包括对其他 MQTT 消息类型进行解析,并能够更深入地解析 CONNECT 消息以启用以下功能:

  • 额外的身份验证和访问控制机制
  • 通过对频繁通信的客户端进行速率限制来保护 Broker
  • 消息遥测和连接指标

欢迎您就所看重的特性给我们反馈,请发送邮件至 contactme_nginxapac@f5.com 告诉我们您的想法。

支持 SAML 身份验证和授权

SAML(Security Assertion Markup Language,安全防护声明标记语言)是一套开放的联合标准,允许身份验证供应商 (IdP) 对访问资源的用户进行身份验证(确保最终用户身份的真实性),并将这些身份验证信息及用户对该资源的访问权限传递给服务提供商 (SP) 进行授权。

SAML 作为一套成熟的身份数据安全交换标准,已被广泛用于在 IdP 和 SP 之间交换身份验证和授权信息。

企业和政府机构选择采用 SAML 的主要原因如下:

  • 高效管理大量身份信息
  • 为客户和员工提供一致、统一的增强型身份安全防护
  • 通过标准化的身份管理流程来提高运营效率
  • 高效处理法规遵从性问题

 
SAML 还提供了诸多优势:

  • 更好的用户体验:凭借其 SSO 集成和单点身份验证(由 IdP 完成),SAML 支持用户进行一次身份验证即可访问所有互联服务。这有助于提升用户体验,并节省时间,因为用户不必再记住不同应用的多个凭证。
  • 更高的安全防护:根据组织的安全防护和身份验证策略,用户可以在 SP 界面(SP 发起的 SSO)或直接在 IdP 界面(IdP 发起的 SSO)使用 SSO 身份验证方案进行登录。这能够减少因潜在的弱密码和/或重复密码而引发的安全防护风险。
  • 更低的管理成本:SAML 可帮助组织将身份管理工作交给可信的 IdP,从而减少帐户信息维护成本及相关费用。
  • 标准化的协议:SAML 的设计原则是让安全防护(尽可能)独立于应用逻辑。它是一种标准化协议,得到了几乎所有 IdP 和访问管理系统的支持。该协议将安全防护框架从平台架构和特定厂商实现中抽象出来,提供了稳健的安全防护和可靠的系统间集成。

SAML 的当前参考实现使用 SAML 2.0,并采用 NGINX JavaScript (njs) 框架构建而成。在此实现中,NGINX Plus 充当 SAML SP,与 SAML IdP 共同完成 SSO 设置。当前实现还依赖于键值存储,后者是 NGINX Plus 中的一项特性,因此除非作进一步修改,否则该实现不适合 NGINX 开源版。

NGINX Plus 中的 SAML 支持在 GitHub 上提供参考实现。代码库提供了一个示例配置,其中包含有关特定用例的安装、配置及微调说明。

原生 OpenTelemetry

OpenTelemetry (OTel) 是一种可用于监控、跟踪、排除故障及优化应用的技术和标准。其工作原理是从已部署应用堆栈中的代理、应用或其他服务等各种来源收集遥测数据。

作为协议感知型反向代理和负载均衡器,NGINX 是启动遥测调用来跟踪应用请求和响应的理想位置。虽然第三方 OTel 模块已经使用了很长时间,但现在我们很高兴地宣布 NGINX Plus 的一个新动态模块将提供对 OTel 的原生支持。

这个新模块 ngx_otel_module 可使用 nginx-plus-module-otel 包进行安装,相比第三方模块做了一些重要改进,包括:

  • 更高性能 — 当启用链路追踪功能时,大多数 OTel 实现会将请求处理的性能降低 50%。我们的全新原生模块能够将这种性能影响限制在 10-15% 左右。
  • 轻松配置 — 可直接在 NGINX 配置文件中完成遥测数据收集的设置和配置。
  • 完全动态的基于变量的采样 — 可通过 cookie/令牌跟踪特定会话,并通过 NGINX Plus API键值存储模块动态控制模块。

有关 OTel 动态模块的更多详细信息,请参阅 NGINX 文档

OTel 链路追踪示例

以下是 NGINX 直接服务的一个应用的基本 OTel 链路追踪示例:

load_module modules/ngx_otel_module.so;
events {}
http {     otel_exporter {         endpoint localhost:4317;     }  
    server {         listen 127.0.0.1:8080;         
        otel_trace on;         otel_span_name app1;     } }

在下面的示例中,我们仅在对父 span 进行采样时才会从传入请求继承链路追踪上下文并记录 span。我们还将链路追踪上下文和采样决策传播到上游服务器。

load_module modules/ngx_otel_module.so;
http {     server {         location / {             otel_trace $otel_parent_sampled;             otel_trace_context propagate;             proxy_pass http://backend;         }     } }

在此基于比率的示例中,根据一定比例的流量配置链路追踪(本例中为 10%):

http {      # 跟踪 10% 的请求
      split_clients "$otel_trace_id" $ratio_sampler {
          10%     on;
          *       off;
      }
    # 或者我们可以跟踪 10% 的用户会话
    split_clients "$cookie_sessionid" $session_sampler {         10%     on;         *       off;     }
    server {         location / {             otel_trace $ratio_sampler;             otel_trace_context inject;
            proxy_pass http://backend;         }     } }

在此 API 控制的示例中,通过 /api 端点控制键值存储来启用链路追踪:

http {      keyval "otel.trace" $trace_switch zone=name;
    server {         location / {             otel_trace $trace_switch;             otel_trace_context inject;             proxy_pass http://backend;         }
        location /api {             api write=on;         }      } }

实验性 QUIC+HTTP/3 包

发布 NGINX 开源版的预览版二进制包后,我们很高兴地宣布推出 NGINX Plus R29 的实验性 QUIC 包。它支持使用 NGINX Plus 测试并评估 HTTP/3。

借助一个新的底层协议堆栈,HTTP/3 将 UDP 和 QUIC 引入传输层。QUIC 是一种加密传输协议,旨在通过提供连接复用和解决队头阻塞等问题来改进 TCP。它重新实现并增强了 HTTP/1.1 和 HTTP/2 的一些 TCP 功能,包括连接建立、拥塞控制及可靠交付。QUIC 还将 TLS 作为一个整体构件,而不像 HTTP/1.1 和 HTTP/2 那样将 TLS 作为一个单独的层。这意味着 HTTP/3 消息本身就很安全,因为它们默认通过加密连接发送请求。

通常,对于安全通信和加密功能,NGINX Plus 依靠 OpenSSL,以利用操作系统自带的 SSL/TLS 库。但由于截至本文撰写时,OpenSSL 不支持 QUIC 的 TLS 接口,因此需要第三方库来提供 HTTP/3 所需的 TLS 功能。

为了解决这一问题,我们为 QUIC 开发了一个 OpenSSL 兼容层,这样就无需构建和交付第三方 TLS 库,例如 Quictls、BoringSSL 和 LibreSSL。这有助于管理 NGINX 中的端到端 QUIC+HTTP/3 体验,既无需自定义 TLS 实现,也不必依赖第三方库的进度表和路线图。

:OpenSSL 兼容层包含在实验性 NGINX Plus QUIC+HTTP/3 包中,需要使用 OpenSSL 1.1.1 或更高版本来提供 TLSv1.3(这是 QUIC 协议所要求的)。它尚未实现 0-RTT。

QUIC+HTTP/3 示例配置

下面我们来看看 NGINX Plus 中 QUIC+HTTP/3 的示例配置:

http {      log_format quic '$remote_addr - $remote_user [$time_local]'
      '"$request" $status $body_bytes_sent '
      '"$http_referer" "$http_user_agent" "$http3"';
    access_log logs/access.log quic;
    server {         # 为了提高兼容性,建议         # 对 quic 和 https 使用同一端口         listen 8443 quic reuseport;         listen 8443 ssl;
        ssl_certificate     certs/example.com.crt;         ssl_certificate_key certs/example.com.key;
        location / {             # 需要浏览器将其定向到 quic 端口             add_header Alt-Svc 'h3=":8443"; ma=86400';         }     } }

类似于我们的 HTTP/2 的实现,当 NGINX Plus 作为代理时,QUIC+HTTP/3 连接在客户端建立,并在连接到后端和上游服务时转换为 HTTP/1.1。

实验性 NGINX Plus QUIC+HTTP/3 包可以从单独的代码库中获取,并可通过现有 NGINX Plus 证书和密钥访问。实验性 QUIC 包的安装类似于标准 NGINX Plus 安装。请确保使用 QUIC 代码库,如安装步骤所示。

您可以参阅“针对 QUIC+HTTP/3 的 NGINX 配置”一节,详细了解如何针对 QUIC+HTTP/3 配置 NGINX。如欲了解有关所有新指令和变量的信息,请参阅 nginx-quic README 的“配置”部分。

后续步骤

近期,我们计划将 QUIC+HTTP/3 代码合并到 NGINX 主线分支。然后,支持 QUIC+HTTP/3 的最新版 NGINX 主线将被合并到下一 NGINX Plus 版本中。预计今年晚些时候将正式发布 NGINX Plus 提供 QUIC+HTTP/3 支持的公告。

NGINX Plus R29 的其他增强功能

OpenID Connect 变更

OpenID Connect (OIDC) 支持是在 NGINX Plus R15 中引入的,然后在后续版本中得到了显著增强。NGINX Plus R29 将继续增强 OIDC,并增添了以下特性。

支持访问令牌

访问令牌用于基于令牌的身份验证,以允许 OIDC 客户端代表用户访问受保护的资源。NGINX Plus 在用户成功进行身份验证并授权访问后会收到一个访问令牌,然后将其存储到键值存储中。对于发送到下游应用的每个请求,NGINX Plus 可通过 HTTP Authorization 请求头将该令牌作为的 Bearer 令牌进行传递。

:NGINX Plus 不会验证每个请求的访问令牌的有效性(与 ID 令牌一样),也无法知道访问令牌是否已经过期。如果访问令牌的生命周期小于 ID 令牌的生命周期,那么您必须使用 proxy_intercept_errors on 指令。这将拦截并重定向对 NGINX 的 401 Unauthorized 响应,并更新访问令牌。

有关 NGINX Plus 支持 OpenID Connect 和 JSON Web 令牌 (JWT) 验证的更多信息,请参阅《借助 OpenID Connect 和 NGINX Plus 对访问当前应用的用户进行身份验证》。

在 OIDC 身份验证端点中添加参数

一些身份验证供应商(例如 Keycloak)允许向身份验证请求添加额外的查询字符串参数,以启用附加功能。 例如,Keycloak 允许通过向身份验证请求添加 kc_idp_hint 参数来指定默认 IdP。借助此增强特性,用户可为 OIDC 授权端点指定其他参数。

Prometheus-njs 模块中的扩展 SSL 计数器

在 NGINX Plus R28 中,我们为面向客户端和服务器端连接的 HTTP 和 Stream 模块中的握手错误和证书验证失败提供了额外的 SSL 计数器支持。我们的 Prometheus-njs 模块不仅能够将 NGINX Plus 指标转换为 Prometheus 数据格式,而且现在还支持这些计数器。

新的 internal_redirect 指令

新的 internal_redirect 指令和模块允许在检查 request 处理限制、connection 处理限制及 access 限制后进行内部重定向。

以下是 internal_redirect 配置示例:

http {      limit_req_zone $jwt_claim_sub zone=jwt_sub:10m rate=1r/s; 
    server {         location / {             auth_jwt "realm";             auth_jwt_key_file key.jwk;
            internal_redirect @rate_limited;         }
        location @rate_limited {             internal;             limit_req zone=jwt_sub burst=10;
         proxy_pass http://backend;         }     } }

在上例中,JWT 身份验证在 location 块执行,如果令牌有效,则请求将传递给内部内容处理器 @rate_limited,其中根据 sub 声明值应用请求速率限制。这在 JWT 中进行,直至请求传递到上游服务。

此特定配置能够防止拒绝服务 (DoS) 攻击,即攻击者发送大量包含可读 JWT 的请求,以特定用户作为 sub 字段。大量请求不会通过身份验证,但将计入速率限制。通过在将请求传递给内容处理器之前对 JWT 进行身份验证,您可以确保仅有效请求才计入速率限制。

从 NGINX 开源版继承的变更

NGINX Plus R29 基于 NGINX 开源版 1.23.4,继承了自 NGINX Plus R28 发布以来(NGINX 1.23.3 到 1.23.4)的功能变更和漏洞修复。

变更

  • TLSv1.3 协议现在默认启用,并且是以下指令的默认值:
  • NGINX 现在会在监听套接字的协议参数被重新定义时发出警告。
  • 如果客户端使用了管线,NGINX 现在会关闭有延迟的连接。
  • 下列错误的日志级别已经从 crit 降至 info:数据长度太长、长度太短、旧版本错误、无共享签名算法、摘要长度错误、缺少 sigalgs 扩展、加密长度太长、长度错误、密钥更新错误、混合握手和非握手数据、ccs 接收较早、ccs 和 finished 之间的数据、数据包长度太长、警报提醒太多、记录太少以及在 ccs SSL 错误之前获得 finished。

特性

  • Ngx_http_gzip_static_module 现在支持字节范围。

漏洞修复

  • 修复了 listen 指令中的端口范围不可用的问题。
  • 修复了在配置中使用了超过 255 个字符的前缀位置时可能会选错位置来处理请求的问题。
  • 修复了 ngx_http_autoindex_modulengx_http_dav_module 及 include 指令不支持 Windows 下文件名中非 ASCII 字符的问题。
  • 修复了使用 HTTP/2 和 error_page 指令来重定向代码为 400 的错误时有时会发生的套接字泄露问题。
  • 修复了有关记录到 syslog 错误的消息,这些消息不包含记录到 syslog 时出现错误的信息。
  • 修复了代理 -r 中对拦截的客户端读取事件的处理。
  • 修复了在读取带有大量 TLV 的 PROXY 协议版本 2 请求头时有时会发生的错误。
  • 修复了使用 SSI 处理其他模块创建的子请求时 worker 进程中有时会发生的分段错误。
  • 修复了如果使用 SSL 连接到后端,NGINX 在无缓冲代理期间可能会占用 CPU 的问题。

变通方案

  • 在使用 zlib-ng 时,日志中会显示 zip filter failed to use pre-allocated memory(zip 过滤器无法使用预分配内存)警报。
  • listen 指令中使用的主机名解析为多个地址时,NGINX 现在会忽略这些地址中的重复内容。

有关从这些版本继承的新特性、变更、漏洞修复及变通方案的完整列表,请参见变更文件。

NGINX JavaScript 模块的变更

NGINX Plus R29 包含从 NGINX JavaScript (njs) 模块版本 0.7.9 到 0.7.12 的变更。njs 中添加了多个卓越特性,包括:

  • 扩展的 Fetch API 支持
  • 扩展的 Web Crypto API
  • XML 文档支持
  • XML 文档解析
  • 用于修改 XML 文档的 XMLNode API
  • Zlib 模块压缩支持

有关 njs 版本 0.7.9 到 0.7.12 的所有特性、变更及漏洞修复的完整列表,请参阅 njs 变更日志

扩展的 Fetch API 支持

在 Fetch API 中添加了 Headers()Request()Response() 构造函数及其他增强函数:

async function makeRequest(uri, headers) {      let h = new Headers(headers);
      h.delete("bar");
      h.append("foo", "xxx");
      let r = new Request(uri, {headers: h});
      return await ngx.fetch(r);
  }

扩展的 Web Crypto API

Web Crypto API 已扩展为支持 JSON Web Key (JWK) 格式,importKey() 现在接受 JWK 格式的密钥作为输入:

async function importSigningJWK(jwk) {     return await crypto.subtle.importKey('jwk', jwk,
                                          {name: "RSASSA-PKCS1-v1_5"},
                                          true, ['sign']);
  }

njs 0.7.10 还增加了 generateKey()exportKey() 方法。generateKey() 方法允许您为对称算法生成新密钥,或者为公钥算法生成密钥对。exportKey() 方法将 CryptoKey 对象作为输入,并以外部可移植格式返回密钥。它支持 JWK 格式,可将密钥作为 JSON 对象导出。

更多详情,请参考 Web Crypto API

XML 文档支持

njs 0.7.10 中添加了 XML 模块,可为处理 XML 文档提供原生支持。

XML 文档解析

您现在可以解析 XML 文档的字符串或缓冲区,然后返回一个 XMLDoc 代表已解析 XML 文档的包装器对象:

const xml = require("xml");  let data = `<note><to b="bar" a= "foo">Tove</to><from>Jani</from></note>`;
  let doc = xml.parse(data);
   
console.log(doc.note.to.$text) /* 'Tove' */ console.log(doc.note.to.$attr$b) /* 'bar' */ console.log(doc.note.$tags[1].$text) /* 'Jani' */

用于修改 XML 文档的 XMLNode API

在 njs 0.7.11 中添加了 XMLNode API,用于修改 XML 文档:

Const xml = require("xml");  let data = `<note><to b="bar" a="foo">Tove</to><from>Jani</from></note>`;
  let doc = xml.parse(data);
   
doc.$root.to.$attr$b = 'bar2'; doc.$root.to.setAttribute('c', 'baz'); delete doc.$root.to.$attr$a;  
console.log(xml.serializeToString(doc.$root.to)) /* '<to b="bar2" c="baz">Tove</to>' */  
doc.$root.to.removeAllAttributes(); doc.$root.from.$text = 'Jani2';  
console.log(xml.serializeToString(doc)) /* '<note><to>Tove</to><from>Jani2</from></note>' */  
doc.$root.to.$tags = [xml.parse(`<a/>`), xml.parse(`<b/>`)]; doc.$root.to.addChild(xml.parse(`<a/>`));
console.log(xml.serializeToString(doc.$root.to)) /* '<to><a></a><b></b><a></a></to>' */  
doc.$root.to.removeChildren('a');  
console.log(xml.serializeToString(doc.$root.to)) /* '<to><b></b></to>' */

如欲了解有关所有 XML 相关增强特性的更多详细信息,请参阅 XML 文档

Zlib 模块压缩支持

zlib 模块已添加到 njs 0.7.12 中,可使用 deflate 和 inflate 算法提供压缩功能。

Const zlib = require('zlib');  zlib.deflateRawSync('αβγ').toString('base64')
  /* "O7fx3KzzmwE=" */
   
zlib.inflateRawSync(Buffer.from('O7fx3KzzmwE=', 'base64')).toString() /* "αβγ" */

如欲了解有关 zlib 的更多详细信息,请参阅 zlib 文件

升级或试用 NGINX Plus

如果您是 NGINX Plus 用户,我们强烈建议您尽快升级到 NGINX Plus R29。除了上述所有新特性以外,您还将获得更多修复和改进。升级到最新版本有助于 NGINX 团队在您需要时为您快速提供支持。

如果您还不是 NGINX Plus 用户,我们建议您立即申请试用 —它具备强大的安全防护,可充当负载均衡器、API 网关或者具备增强的监控和管理 API 的 Web 服务器,并且 NGINX 团队将提供支持服务。请立即下载 30 天免费试用版


"This blog post may reference products that are no longer available and/or no longer supported. For the most current information about available F5 NGINX products and solutions, explore our NGINX product family. NGINX is now part of F5. All previous NGINX.com links will redirect to similar NGINX content on F5.com."