升级目标:修复安全漏洞 + 移除不兼容第三方模块 + 迁移至官方内置会话保持
一、升级背景
| 项目 | 详情 |
|---|---|
| 触发原因 | 近期漏洞扫描发现 Nginx 存在高危安全漏洞 |
| 漏洞编号 | CVE-2026-42945 |
| 漏洞描述 | ngx_http_rewrite_module 堆内存缓冲区溢出,可导致任意代码执行 |
| 修复版本 | Nginx 1.30.1(2026-05-13 发布) |
| 整改要求 | 局方要求限期完成升级整改 |
⚠️ 本次升级为安全合规性升级,必须在规定时间窗口内完成。
二、当前环境
1.概述
| 项目 | 详情 |
|---|---|
| 当前版本 | Nginx 1.22.0 |
| 目标版本 | Nginx 1.30.1(主线稳定版) |
| 操作系统 | 统信 UOS 20(UEL 20) / 银河麒麟 V10(KylinOS 10) |
| CPU 架构 | aarch64(ARM64) |
| 安装路径 | /usr/local/nginx |
2.模块变更总览
| 变更类型 | 模块/功能 | 处理方式 |
|---|---|---|
| ❌ 移除 | nginx-sticky-module-ng(第三方会话保持模块) |
不再编译,改用官方内置功能替代 |
| ❌ 移除 | nginx_upstream_check_module-0.4.0(主动健康检查) |
不兼容 1.30.1,已移除 |
| ✅ 新增 | Nginx 官方内置 sticky cookie(1.29.6+ 原生支持) |
无需额外模块,开箱即用 |
3.当前 upstream 配置示例(升级前)
nginx
upstream api {
sticky name=nginx-sticky expires=5m path=/;
server 10.48.9.106:9190;
}
4.升级后 upstream 配置示例
nginx
upstream api {
sticky cookie nginx-sticky expires=5m path=/;
server 10.48.9.106:9190;
}
关键变化 :语法从
sticky name=<cookie名>改为sticky cookie <cookie名>,其余参数保持不变。Cookie 名称仍使用nginx-sticky,确保客户端已有的 Cookie 在切换后仍然兼容。
三、漏洞说明
CVE-2026-42945 --- ngx_http_rewrite_module 堆内存缓冲区溢出漏洞,攻击者可通过精心构造的请求触发堆溢出,导致 远程代码执行(RCE)。该漏洞影响范围广、危害等级高,已被纳入本次漏洞扫描的高危告警清单。
| 属性 | 信息 |
|---|---|
| 影响模块 | ngx_http_rewrite_module(rewrite / if / return 等指令所在模块) |
| 漏洞类型 | 堆缓冲区溢出(Heap Buffer Overflow) |
| 危害等级 | 高危 |
| 修复方案 | 升级至 Nginx 1.30.1 或更高版本 |
四、Sticky 会话保持迁移说明
1.为什么移除第三方模块?
Nginx 从 1.29.6 版本开始 ,官方在主线条目中原生支持了 sticky cookie 指令,功能与第三方 nginx-sticky-module-ng 完全对等,且具有以下优势:
| 对比项 | 第三方 nginx-sticky-module-ng |
官方内置 sticky cookie |
|---|---|---|
| 维护主体 | 社区维护,更新不及时 | Nginx 官方团队维护 |
| 版本兼容性 | 大版本升级经常需要打补丁 | 随 Nginx 主线同步更新 |
| 编译依赖 | 需要 git clone + --add-module= 编译 |
零额外依赖,原生支持 |
| 功能完整性 | 基础 Cookie 粘滞 | 支持 expires / path / domain / secure / httponly 等 |
| 未来风险 | 可能因 API 变更导致编译失败 | 官方长期向后兼容保障 |
2.配置语法对照表
| 配置项 | 旧语法(第三方模块) | 新语法(官方内置) |
|---|---|---|
| 指令格式 | sticky name=<name> |
sticky cookie <name> |
| Cookie 名称 | name=nginx-sticky |
直接跟在 sticky cookie 后面 |
| 过期时间 | expires=5m ✅ 保持不变 |
expires=5m ✅ 保持不变 |
| 生效路径 | path=/ ✅ 保持不变 |
path=/ ✅ 保持不变 |
| 完整示例 | sticky name=nginx-sticky expires=5m path=/; |
sticky cookie nginx-sticky expires=5m path=/; |
3.迁移注意事项
- Cookie 名称保持一致 :新配置中 Cookie 名仍为
nginx-sticky,客户端浏览器中的旧 Cookie 可无缝衔接,不会导致会话丢失 - 仅改语法不改逻辑 :
expires、path、domain等参数含义和用法完全一致 - 配置修改时机 :在替换二进制并 reload 之前 ,先修改
nginx.conf中的 upstream 配置
五、升级步骤
1.备份
bash
cd /usr/local/nginx
# 备份整个安装目录
cp -r /usr/local/nginx /usr/local/nginx.1.22.0.bak
# 备份配置文件(单独备份,方便对比)
cp -r conf/ conf.bak.$(date +%Y%m%d)
# 保存当前编译参数(用于对比确认)
/usr/local/nginx/sbin/nginx -V > /tmp/nginx_old_params_$(hostname).txt
2.修改 upstream 配置(⚠️ 必须在替换二进制前完成)
因为新版本的 sticky 语法变了,需要在升级前先把配置文件改成新语法。
操作 :编辑 /usr/local/nginx/conf/nginx.conf,将所有 upstream 块中的 sticky 语法做如下替换:
diff
upstream api {
- sticky name=nginx-sticky expires=5m path=/;
+ sticky cookie nginx-sticky expires=5m path=/;
server 10.48.9.106:9190;
}
如果有多个 upstream 块使用了 sticky,逐一修改即可。其他配置项(server、weight、max_fails 等)不需要变动。
同时检查并删除所有 check 相关指令(属于已移除的 nginx_upstream_check_module):
bash
# 检查是否还有 check 指令残留
grep -rn "check" /usr/local/nginx/conf/
# 如果有,注释或删除对应行
3.安装编译依赖
bash
yum install -y gcc gcc-c++ make pcre-devel zlib-devel openssl-devel wget tar git unzip
4.下载并编译 Nginx 1.30.1(纯官方编译,无第三方模块)
bash
cd /data/software/
# ---- 3a. 下载 Nginx ----
wget https://nginx.org/download/nginx-1.30.1.tar.gz
tar zxf nginx-1.30.1.tar.gz
# ---- 3b. 编译(注意:不再需要 --add-module 编译第三方模块)----
cd nginx-1.30.1
./configure \
--prefix=/usr/local/nginx \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_sub_module \
--with-http_v2_module \
--http-client-body-temp-path=/usr/local/nginx/temp/client_body_temp/ \
--http-proxy-temp-path=/usr/local/nginx/temp/proxy_temp/ \
--http-fastcgi-temp-path=/usr/local/nginx/temp/fastcgi_temp/ \
--http-uwsgi-temp-path=/usr/local/nginx/temp/uwsgi_temp/ \
--http-scgi-temp-path=/usr/local/nginx/temp/scgi_temp/ \
--with-stream \
--with-cc-opt="-O2 -march=armv8-a"
make -j$(nproc)
编译参数变更说明(相比当前环境):
| 参数 | 变更 |
|---|---|
--add-module=../nginx-sticky-module-ng |
❌ 删除 --- sticky 功能改为官方内置,无需第三方模块 |
--add-module=...check_module... |
❌ 删除 --- 主动健康检查模块不兼容,已移除 |
-march=armv8-a |
✅ 保持不变 --- ARM64 指令集优化 |
bash
# 编译后预检
./objs/nginx -V # 确认编译参数正确(不应包含 --add-module=...sticky)
./objs/nginx -t # 测试配置文件语法(注意:此时还没替换二进制)

5.替换二进制升级
bash
# 备份旧版本二进制
mv /usr/local/nginx/sbin/nginx{,_old}
# 拷贝新版本二进制
cp /data/software/nginx-1.30.1/objs/nginx /usr/local/nginx/sbin/
# 配置语法检查 + 平滑 reload
/usr/local/nginx/sbin/nginx -t && /usr/local/nginx/sbin/nginx -s reload

6.验证
bash
# 版本确认
/usr/local/nginx/sbin/nginx -V
# 进程状态
ps aux | grep nginx
# 确认 sticky 模块已加载(官方内置方式,不会出现 --add-module=sticky)
/usr/local/nginx/sbin/nginx -V 2>&1 | grep -i sticky
# 注意:官方内置的 sticky 不会以 module 形式出现在 configure 参数中
# 正确的验证方式是看配置能否正常加载且业务访问正常(见第6步)

7.验证 Sticky 会话保持功能
bash
# 测试方法:连续发送多次请求,观察响应头中 Set-Cookie 和路由一致性
curl -v -I http://你的域名/api/tTag/queryTag 2>/dev/null | grep -i "set-cookie\|route"
# 预期结果:
# 1. 首次请求返回 Set-Cookie: nginx-sticky=xxxx; Path=/
# 2. 携带该 Cookie 后续请求始终打到同一台 backend
# 3. 清除 Cookie 后重新分配
验证要点 :Cookie 名称应为
nginx-sticky,与旧版保持一致。如果名称变了,说明配置有误需检查。
六、回滚方案
bash
# 1. 停止当前 Nginx
/usr/local/nginx/sbin/nginx -s stop
# 2. 恢复旧版二进制(第4步备份的 _old 文件)
cp /usr/local/nginx/sbin/nginx_old /usr/local/nginx/sbin/nginx
# 3. 恢复旧版配置(将 sticky 语法改回旧格式)
# 编辑 nginx.conf:
# sticky cookie nginx-sticky ... → sticky name=nginx-sticky ...
vim /usr/local/nginx/conf/nginx.conf
# 4. 启动并检查
/usr/local/nginx/sbin/nginx -t && /usr/local/nginx/sbin/nginx
# 5. 确认版本回退成功
/usr/local/nginx/sbin/nginx -v
echo "✅ 已回滚到 1.22.0"
回滚需要恢复 二进制文件 + 配置文件两项。因为新旧版的 sticky 语法不同,回滚时必须把配置也改回去。
七、注意事项
- 路径特殊 :Nginx 安装在
/usr/local/nginx,所有命令需用绝对路径 - Sticky 语法变更 :升级后使用
sticky cookie <name>而非sticky name=<name>,这是最容易出错的地方,务必仔细核对 - Check 模块已移除 :upstream 中不能出现
check相关指令,编译前必须清理干净 - OpenSSL FIPS:保持原有 OpenSSL 1.1.1k FIPS 不变
- ARM 架构 :编译参数已添加
-march=armv8-a优化,不要遗漏 - Cookie 兼容 :新旧配置的 Cookie 名称均为
nginx-sticky,确保升级过程中用户会话不中断 - 灰度建议:先在一台机器上升级验证,观察流量和日志无异常后再批量推进
- 时间窗口:本次为局方要求的合规性升级,请在规定的整改时间窗内完成