Linux Kernel netfilter 严重漏洞修复:CVE-2026-46244 分析及应急指南
2026 年 6 月 3 日,Linux 内核团队披露了 netfilter 框架中的一个严重漏洞 CVE-2026-46244(CVSS 9.1)。该漏洞允许远程攻击者在无需认证的情况下构造特制 IPv6 数据包绕过 nftables 防火墙规则,影响 Linux 6.2 及以上所有内核版本。本文从漏洞原理、攻击面分析到修复方案,提供完整的应急响应指南。
1. 漏洞背景与威胁评估
2026 年 6 月初,Linux 内核安全团队通过 oss-security 邮件列表披露了一个存在于 netfilter 框架 nft_inner 模块中的高危漏洞,编号 CVE-2026-46244。
1.1 漏洞评分
| 评估维度 | 评分 |
|---|---|
| CVSS 3.1 基础分 | 9.1(CRITICAL) |
| 攻击向量 | 远程网络 |
| 攻击复杂度 | 低 |
| 所需权限 | 无需认证 |
| 影响范围 | 机密性 HIGH + 完整性 HIGH |
| 可利用性 | POC 已公开披露 |
1.2 影响范围
- 受影响内核版本: Linux Kernel 6.2 及以上(含所有稳定分支)
- 受影响配置: 所有使用 nftables 并启用了 nft_inner 表达式的系统
- 不受影响: 仅使用 iptables 的传统系统(未使用 nftables 的场景)
CVE-2026-46244 与普通 IPv6 漏洞不同——它不是协议栈层面的缺陷,而是 netfilter 内层数据包解析引擎 nft_inner 的具体编程错误。这意味着即使系统配置了看似严密的 nftables 规则集,攻击者依然可以构造特制 IPv6 扩展头绕过所有规则。
2. 漏洞根因:nft_inner 解析引擎的偏移量失步
2.1 nft_inner 模块的作用
nft_inner 是 nftables 中用于解析"内层数据包"的表达式引擎。它处理的是隧道封装报文——即一个数据包内部还包裹着另一个数据包(如 VXLAN、GENEVE、IP-in-IP、GRE 等隧道协议)。
当报文到达 nftables 规则集时,nft_inner 负责:
- 剥离外层包头,定位内层数据包的起始位置
- 解析内层数据包的 L2/L3/L4 头部
- 将解析结果(协议类型、传输层偏移、端口号等)暴露给 nftables 规则做匹配决策
2.2 Bug 的精确位置
调用栈路径:
nft_inner_parse_l2l3()
→ ipv6_find_hdr() ← 正确遍历所有 IPv6 扩展头
→ 覆盖 inner_thoff ← 错误地重新赋值
在 nft_inner_parse_l2l3() 函数中,解析内层 IPv6 报文时,代码先调用了 ipv6_find_hdr()——这个函数正确地遍历了所有 IPv6 扩展头(逐跳选项头、路由头、分段头、认证头、ESP 头、目的地选项头),并计算出传输层头部的准确偏移。
但紧接着,这段代码愚蠢地覆盖了计算结果:
/* 正确路径:ipv6_find_hdr() 计算出 nhoff 指向 TCP/UDP 头 */
inner_thoff = nhoff; /* 将正确的偏移保存到 inner_thoff */
/* 错误代码:用 nhoff + sizeof(struct ipv6hdr) 覆盖 */
inner_thoff = nhoff + sizeof(_ip6h); /* 40 字节,仅 IPv6 基本头 */
这就导致:
- l4proto(传输层协议类型):正确——例如
IPPROTO_TCP(6) - inner_thoff(传输层头偏移):错误——指向扩展头而不是 TCP 头

2.3 代码级复现
以下是从 Linux 内核源码中提取的修复前后对比(简化示意):
漏洞代码(Linux 6.2 ~ 6.x-rc,net/netfilter/nft_inner.c):
static int nft_inner_parse_l2l3(struct nft_inner *priv,
struct sk_buff *skb,
u32 *inner_thoff,
u8 *l4proto)
{
// ... 外层解析省略 ...
if (inner_ip.version == 6) {
struct ipv6hdr _ip6h, *ip6h;
unsigned int nhoff = offset;
ip6h = skb_header_pointer(skb, offset, sizeof(_ip6h), &_ip6h);
if (!ip6h)
return -EINVAL;
/* 第 1 步:ipv6_find_hdr 正确遍历所有扩展头 */
nhoff = ipv6_find_hdr(skb, &nhoff, IPPROTO_TCP, NULL, NULL);
if (nhoff < 0)
return -EINVAL;
/* 第 2 步:BUG!用固定值覆盖计算结果 */
*inner_thoff = offset + sizeof(struct ipv6hdr); /* ← 40 bytes 硬编码 */
*l4proto = ip6h->nexthdr;
}
// ...
}
修复代码:
/* 删除上面的覆盖赋值,直接使用 ipv6_find_hdr 的计算结果 */
*inner_thoff = nhoff; /* 保留 ipv6_find_hdr 的真实遍历结果 */
*l4proto = ip6h->nexthdr;
3. 攻击原理:传输层头部伪造
3.1 利用链拆解
攻击者如何利用这个偏移量错误绕过防火墙?完整的攻击链路如下:

3.2 攻击触发条件
要成功利用此漏洞,攻击者需要:
- 构造 IPv6 扩展头: 数据包必须包含至少一个 IPv6 扩展头(如逐跳选项头
Hop-by-Hop Options Header) - nftables 内层匹配: 目标防火墙规则使用了 nft_inner 表达式来匹配内层 IPv6 报文的传输层信息
- nftables 规则依赖: 规则集依赖于对
传输层端口或协议类型的精确匹配来做放行/阻断决策
3.3 实际攻击场景
场景一:K8s 集群的网络安全策略
K8s 集群使用 Calico 或 Cilium(底层基于 nftables/iptables)实现 NetworkPolicy。当 Pod 间通信使用 IPv6 隧道封装时:
- 正常:防火墙检查内层 TCP 端口 3306(MySQL),阻断非授权访问
- 攻击:构造带扩展头的 IPv6 数据包,协议类型被识别为 TCP,但传输层偏移错误导致端口匹配失效,攻击者可以访问本应受保护的数据库端口
场景二:公有云安全组
云环境中,安全组规则依赖 netfilter 实现。当实例间的 VXLAN 隧道使用 IPv6 内层封装时:
- 正常:安全组规则限制 SSH(22)和 HTTP(80)以外端口的入站流量
- 攻击:特制数据包绕过端口过滤,访问 Redis(6379)、MySQL(3306)等内网服务
4. 漏洞检测方法
4.1 检查内核版本
是否需要打补丁,第一步确认内核版本:
# 检查当前内核版本
uname -r
# 输出示例: 6.8.0-31-generic
# 检查是否使用了 nftables
nft list ruleset
# 如果有输出,说明系统正在使用 nftables
4.2 确认是否受影响
为什么需要检查 nftables 配置?因为并非所有使用受影响内核的系统都有攻击面——只有那些在 nftables 规则中使用了 inner 表达式的系统才真正受影响。
# 检查 nftables 规则中是否使用了 inner 表达式
nft list ruleset | grep -i 'inner'
# 有输出 → 需要立即修复
# 无输出 → 攻击面较低,但仍建议更新
# 深入检查:哪些链和规则使用了 inner
nft --debug=all list ruleset 2>&1 | grep -A5 'inner'
4.3 构造测试用例验证
以下脚本可用于验证系统是否存在偏移量失步问题:
#!/bin/bash
# 验证系统是否受 CVE-2026-46244 影响
# 使用方法: sudo ./check_cve_2026_46244.sh
KERNEL_VERSION=$(uname -r | cut -d. -f1,2)
KERNEL_MAJOR=$(echo $KERNEL_VERSION | cut -d. -f1)
KERNEL_MINOR=$(echo $KERNEL_VERSION | cut -d. -f2)
echo "[*] 当前内核版本: $(uname -r)"
# 检查内核版本是否在受影响范围 (≥ 6.2)
if [ "$KERNEL_MAJOR" -gt 6 ] || ([ "$KERNEL_MAJOR" -eq 6 ] && [ "$KERNEL_MINOR" -ge 2 ]); then
echo "[!] 内核版本在受影响范围 (>6.2)"
# 检查 nftables 中是否存在 inner 表达式使用
if nft list ruleset 2>/dev/null | grep -q 'inner'; then
echo "[!!] 严重: nftables 规则中使用了 inner 表达式"
echo "[!!] 系统存在 CVE-2026-46244 攻击面"
exit 2
else
echo "[*] 未检测到 inner 表达式使用"
echo "[*] 攻击面较低,但仍建议升级内核"
exit 1
fi
else
echo "[✓] 内核版本不受影响"
exit 0
fi
4.4 使用内核配置检测
通过查看内核编译配置,确认 nft_inner 模块是否已编译:
# 检查 nft_inner 模块是否加载
lsmod | grep nft_inner
# 检查内核配置
grep CONFIG_NFT_INNER /boot/config-$(uname -r)
# CONFIG_NFT_INNER=y → 编译进内核
# CONFIG_NFT_INNER=m → 作为模块(可卸载)
# CONFIG_NFT_INNER is not set → 未编译(不受影响)
5. 修复方案详解
5.1 方案一:升级内核(推荐)
最彻底的修复方式是升级到已包含补丁的内核版本。补丁由 Linux 内核团队提交,commit ID 为 c161ad9157f5。
Ubuntu/Debian 系列:
# 为什么先更新包索引?确保获取最新的安全仓库列表
sudo apt update
# 查看可用内核版本
apt list --upgradable 2>/dev/null | grep linux-image
# 安装安全更新内核
sudo apt install linux-image-$(uname -r | sed 's/-generic//')-generic
# 如果上游还未打补丁,可以从 canonical kernel PPA 安装
sudo add-apt-repository ppa:canonical-kernel-team/ppa
sudo apt update
sudo apt install linux-generic
# 重启加载新内核
sudo reboot
# 验证新内核版本
uname -r
RHEL/CentOS/AlmaLinux 系列:
# 检查可用内核更新
dnf check-update kernel
# 安装最新内核
sudo dnf update kernel -y
# 重启
sudo reboot
# 确认使用新内核启动
uname -r
通用编译安装(适用于找不到预编译包的情况):
# 为什么需要编译安装?当发行版尚未发布安全更新包时,
# 可以从主线内核直接应用补丁
# 下载包含修复的内核源码
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.tar.xz
tar -xf linux-6.12.tar.xz
cd linux-6.12
# 应用补丁(如果有单独补丁文件)
wget https://lore.kernel.org/netfilter-devel/c161ad9157f5.patch
patch -p1 < c161ad9157f5.patch
# 使用当前内核配置
cp /boot/config-$(uname -r) .config
# 编译安装
make -j$(nproc)
sudo make modules_install
sudo make install
# 更新引导
sudo update-grub
sudo reboot
5.2 方案二:缓解措施(不能立即升级时)
以下缓解措施可以作为临时方案,在无法立刻重启服务器的场景下使用:
方法一:禁用 nft_inner 模块:
# 为什么卸载模块?nft_inner 只在需要解析内层隧道包时才有用,
# 如果系统不需要隧道内层解析,卸载模块即可消除攻击面
# 卸载 nft_inner 模块(需 root)
sudo rmmod nft_inner
# 加入黑名单,防止重启后自动加载
echo "blacklist nft_inner" | sudo tee /etc/modprobe.d/blacklist-nft_inner.conf
# 更新 initramfs(确保重启后生效)
sudo update-initramfs -u
# 验证已卸载
lsmod | grep nft_inner
方法二:通过 sysctl 临时禁用 IPv6 扩展头处理:
# 注意:此方法仅在不需要 IPv6 扩展头的场景下使用
# 可能会影响合法的 IPv6 扩展头流量
# 丢弃带有扩展头的 IPv6 数据包
sudo ip6tables -A INPUT -m ipv6header \
--header hop-by-hop --soft -j DROP
方法三:升级 nftables 规则集临时绕过:
# 为什么修改规则?在无法升级内核的情况下,
# 可以调整 nftables 规则,避免依赖 inner 表达式,
# 改为在更外层匹配
# 原规则(使用 inner 表达式,受影响):
# nft add rule inet filter input ip6 inner ip6 dnat to :80 accept
# 临时替代规则(避免使用 inner 表达式):
# 改为在物理接口层直接匹配外层报文的传输层
nft add rule inet filter input meta l4proto tcp \
tcp dport 80 accept
5.3 修复验证
完成修复后,确认漏洞已消除:
# 1. 确认内核版本已更新
uname -r
# 2. 确认补丁是否已包含
zgrep 'CVE-2026-46244\|nft_inner' /usr/src/linux-headers-$(uname -r)/.config
# 3. 确认 nft_inner 模块状态
lsmod | grep nft_inner
# 4. 测试防火墙规则功能正常
nft list ruleset
# 5. 验证关键业务端口可达性
nc -zv localhost 80
nc -zv localhost 443
6. 漏洞修复时间线与影响面评估
6.1 修复时间线
| 时间 | 事件 |
|---|---|
| 2026-05 月 | 漏洞被安全研究人员发现并报告给 Linux 内核安全团队 |
| 2026-06-01 | 补丁提交到 netfilter-devel 邮件列表审核 |
| 2026-06-03 | CVE-2026-46244 正式公开披露,补丁合入主线 |
| 2026-06-04 | POC 利用代码公开,各发行版开始打包安全更新 |
| 2026-06-05 | NVD 正式发布 CVSS 评分 9.1(CRITICAL) |
6.2 影响面评估

7. 生产环境应急演练
以下是一个完整的应急响应流程,供运维团队在实际生产环境中应对此类漏洞时使用:
阶段一:评估(30 分钟内)
# Step 1: 统计受影响的服务器
ansible all -m shell -a "uname -r | awk -F. '{if (\$1>6 || (\$1==6 && \$2>=2)) print \$0}'" \
-o > affected_hosts.txt
# Step 2: 统计使用 nftables 且有 inner 规则的服务器
ansible all -m shell -a "nft list ruleset 2>/dev/null | grep -q inner && echo 'RISK'" \
-o > risk_hosts.txt
# Step 3: 看线上流量是否包含 IPv6 扩展头
tcpdump -i any 'ip6 and (ip6[0] & 0x0f) > 6' -c 100
阶段二:决策——根据影响范围选择修复策略:
- 高风险: 有 inner 规则 + 公网 IPv6 暴露 → 立即升级内核或卸载模块
- 中风险: 有 inner 规则但仅内网 → 计划内维护窗口升级
- 低风险: 无 inner 规则使用 → 下次常规维护升级
阶段三:执行与验证
# 生产环境隔离升级
kubectl cordon node-01
kubectl drain node-01 --ignore-daemonsets
# 升级内核
sudo apt update && sudo apt install -y linux-generic
sudo reboot
# 节点恢复
kubectl uncordon node-01
# 验证业务
kubectl get pods -o wide | grep node-01
8. 踩坑实录
以下是在实际修复过程中可能遇到的典型问题:
踩坑 1:卸载 nft_inner 后防火墙规则报错
# 表现
sudo rmmod nft_inner
# 错误: rmmod: ERROR: Module nft_inner is in use
# 原因
# 有规则的 nftables 链正在引用 inner 表达式
# 解决:先删除使用了 inner 的规则
# 找到使用 inner 的规则句柄
nft -a list ruleset | grep inner
# 示例输出: ... chain input ... # handle 17
# 删除该规则
nft delete rule inet filter input handle 17
踩坑 2:编译内核时缺少依赖
# 表现
make -j$(nproc)
# 错误: No rule to make target 'debian/certs/signing_key.pem'
# 原因
# 发行版内核开启了模块签名验证
# 解决:生成临时签名密钥
# 临时生成测试用签名密钥
openssl req -new -x509 -newkey rsa:4096 \
-keyout signing_key.pem -out signing_key.pem \
-days 365 -nodes -subj "/CN=kernel-sign/"
踩坑 3:升级内核后容器网络异常
# 表现
dockerd 启动后部分容器无法连外网
# 原因
# 新内核的 netfilter 表结构与旧内核不完全兼容,
# docker 的 iptables/nftables 规则需要重建
# 解决:重启 docker daemon 重新生成规则
# 重启后自动重建网络规则
sudo systemctl restart docker
# 验证容器连通性
docker run --rm alpine ping -c 4 8.8.8.8
9. 长期加固建议
9.1 内核安全更新策略
为什么需要建立自动化的内核更新流程?手动跟踪 CVE 不仅工作量巨大,而且容易遗漏。建议建立以下闭环流程:

9.2 关键配置清单
# 1. 定期更新内核(建议使用 unattended-upgrades 自动安装安全更新)
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
# 2. 监控 netfilter 告警日志
# 添加以下规则到 rsyslog
echo 'kern.warning /var/log/netfilter.log' | sudo tee /etc/rsyslog.d/30-netfilter.conf
sudo systemctl restart rsyslog
# 3. 启用内核 Live Patching(零停机修复)
# Ubuntu Livepatch
sudo ua attach <token>
sudo ua enable livepatch
# 或 KernelCare
# curl -s https://kernelcare.com/installer | sudo bash
# 4. 建立内核版本追踪清单
cat <<'EOF' > /etc/cron.weekly/kernel-audit.sh
#!/bin/bash
# 每周检查内核版本和安全公告
current_kernel=$(uname -r)
latest_kernel=$(apt list --upgradable 2>/dev/null | grep linux-image | head -1 | cut -d' ' -f1)
if [ "$current_kernel" != "$latest_kernel" ]; then
echo "[WARN] 内核需要更新: $current_kernel → $latest_kernel"
fi
EOF
chmod +x /etc/cron.weekly/kernel-audit.sh
10. 总结与关键行动项
CVE-2026-46244 是一个典型的"一行代码引发的安全灾难"——在 nft_inner 解析 IPv6 内层数据包时,错误地将传输层偏移覆盖为固定值 40 字节,导致 nftables 防火墙可以绕过。该漏洞 CVSS 9.1 分,远程可利用,无需认证,建议立即处理。
优先级行动清单
| 优先级 | 行动项 | 预计耗时 | 影响 |
|---|---|---|---|
| 🔴 P0 | 检查受影响服务器清单 | 30 分钟 | 摸清攻击面 |
| 🔴 P0 | 升级内核至修复版本 | 2 小时 | 彻底修复 |
| 🟠 P1 | 卸载 nft_inner 模块(临时缓解) | 10 分钟 | 临时消除攻击面 |
| 🟠 P1 | 修改 nftables 规则避免使用 inner | 1 小时 | 规避漏洞触发条件 |
| 🟡 P2 | 建立自动内核安全更新机制 | 4 小时 | 防患于未然 |
| 🟡 P2 | 添加 netfilter 日志监控 | 30 分钟 | 捕获异常行为 |
👍 如果本文对你有帮助,欢迎点赞、收藏、转发!
💬 你在升级内核时遇到了什么问题?欢迎在评论区贴出你的发行版和内核版本,我会逐一回复提供解决方案!
🔔 关注我,获取第一手 Linux 内核安全更新和技术解析!
✍️ 行文仓促,定有不足之处,欢迎朋友们在评论区批评指正!
- 点赞
- 收藏
- 关注作者
评论(0)