nftables 规则加载成功但流量不匹配的 hook / priority 问题

老磊吖_7362

老磊吖_7362

2026-01-29

557人浏览

原创

最常见原因是规则挂载的 hook 和 priority 与数据包实际经过的网络栈路径不一致:每条规则仅在指定 hook(如 input、forward)和 priority 位置生效,且仅对对应方向及协议栈阶段的包可见。

nftables 规则加载成功但流量不匹配的 hook / priority 问题

为什么 nftables 规则加载成功却完全不匹配流量

最常见原因是规则挂载的 hook 和 priority 与实际数据包经过的网络栈路径不一致。nftables 不是“全局生效”,每条规则只在指定 hook(如 input、forward、prerouting)和优先级位置生效,且仅对对应方向、协议栈阶段的包可见。

典型误判场景:

  • 在 input hook 写规则想拦截外部访问本机的 TCP 连接,但目标端口已被 conntrack 或早期 netfilter 模块(如 nf_nat)提前处理或跳过
  • 在 forward 中加规则,但容器或 bridge 流量根本没走 host 的 forward 链(例如使用 host.docker.internal 或 IPv6 SLAAC 场景)
  • 用 prerouting 做 DNAT,但规则 priority 太高(如 -300),被 nf_conntrack(默认 priority -200)之后才执行,导致连接跟踪已建立,DNAT 失效

nft list ruleset 看不到你的规则?检查 hook 和 priority 是否被覆盖

nft list ruleset 输出中,每条 chain 都明确标注了 type filter hook input priority 0 这类信息。如果规则“加载成功”但没出现在输出里,大概率是:你重复声明了同名 chain,后加载的覆盖了前一个;或者用了错误的 family(inet vs ip vs ip6),导致规则落在另一个 namespace 下。

实操建议:

  • 用 nft list ruleset -a 查看 handle 编号,确认规则是否真被插入到目标 chain 底部
  • 检查 chain 定义是否带 type filter hook input priority 0,而不是漏写 priority——省略时默认为 0,但很多内核模块(如 nf_tables_ipv4)注册的内置 chain 是 priority -200,0 反而排在它们之后
  • 避免混用 inet(双栈)和 ip(IPv4 only)family:IPv6 流量不会匹配 ip family 的 input chain,即使规则语法完全一样

抓包验证 packet path:哪个 hook 实际收到了这个包

光看规则列表不够,必须确认数据包到底走到哪一级。推荐用 tcpdump + nft monitor trace 联合定位:

Docker Encyclopedia
Docker Encyclopedia

Docker 文档优先工作流:针对 Docker 特定问题、故障排除、命令规划、镜像/构建、容器/运行时操作及 Compose 等

下载
  • 先用 tcpdump -i any port 80 确认包确实到达 host(排除路由、网卡、offload 问题)
  • 再开一个终端运行 nft monitor trace,然后发测试请求——你会看到每条匹配的规则 handle、hook 名称、priority 数值,甚至跳转 chain 的完整路径
  • 若 trace 输出里完全没出现你的规则 handle,说明包没走到那个 hook,或在更早的 priority 被 accept/drop 终止了

注意:nft monitor trace 默认只显示被规则显式 trace 的包,需先给 chain 加 meta nftrace set 1 才能开启全量追踪(临时调试可用,线上慎用)。

priority 数值越小真的越早执行?别被直觉骗了

priority 是按数值升序执行的:-300 比 -200 更早,0 比 100 更早。但关键陷阱在于——不同 hook 的 priority 空间是独立的,且内核模块注册的内置 chain 有固定优先级,比如:

  • nf_conntrack:prerouting priority -200,output priority -200
  • nf_nat:prerouting priority -100,output priority -100
  • 你自己定义的 filter chain 若设为 priority 0,在 prerouting 中就排在 nat 之后,此时做 DNAT 已无效

所以不是“随便设个负数就行”,而是要查清依赖模块的 priority(cat /proc/net/nf_tables_hooks 或翻内核文档),再决定你的规则该插在哪一档。比如做早期包标记,用 priority -300;做最终过滤,用 priority 100 更安全。

真正容易被忽略的是:同一 priority 下多条规则的执行顺序,取决于它们插入的先后(handle 递增),而不是你在 nft 命令里写的顺序。批量加载时务必用 nft -f 并确保 chain 创建和 rule 插入在同一个事务里。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

6387

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2668

6

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

6387

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2668

6

点击input框没有光标怎么办
点击input框没有光标怎么办

点击input框没有光标的解决办法:1、确认输入框焦点;2、清除浏览器缓存;3、更新浏览器;4、使用JavaScript;5、检查硬件设备;6、检查输入框属性;7、调试JavaScript代码;8、检查页面其他元素;9、考虑浏览器兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.24

894

4

k8s和docker区别
k8s和docker区别

k8s和docker区别有抽象层次不同、管理范围不同、功能不同、应用程序生命周期管理不同、缩放能力不同、高可用性等等区别。本专题为大家提供k8s和docker区别相关的各种文章、以及下载和课程。

2023.07.24

765

4

docker进入容器的方法有哪些
docker进入容器的方法有哪些

docker进入容器的方法:1. Docker exec;2. Docker attach;3. Docker run --interactive --tty;4. Docker ps -a;5. 使用 Docker Compose。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.08

6199

6

docker容器无法访问外部网络怎么办
docker容器无法访问外部网络怎么办

docker 容器无法访问外部网络的原因和解决方法:配置 nat 端口映射以将容器端口映射到主机端口。根据主机兼容性选择正确的网络驱动(如 host 或 overlay)。允许容器端口通过主机的防火墙。配置容器的正确 dns 服务器。选择正确的容器网络模式。排除主机网络问题,如防火墙或连接问题。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.08

7297

6

docker镜像有什么用
docker镜像有什么用

docker 镜像是预构建的软件组件,用途广泛,包括:应用程序部署:简化部署,提高移植性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.08

2873

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpMyAdmin 安装文档
phpMyAdmin 安装文档

共0课时 | 0人学习

Docker 官方文档
Docker 官方文档

共0课时 | 0人学习

宝塔 Docker 模块使用手册
宝塔 Docker 模块使用手册

共0课时 | 0人学习