解决 Nftables 与 Docker 规则冲突的关键是通过 chain priority 主动重构执行路径:策略一抢占前端(如 priority -400),策略二隔离 docker0 流量,策略三寻找空闲 priority 兼容共存,并须经链加载、规则入核、内核无冲突三步验证。

解决 nftables 与 Docker 原生规则的“死锁”,关键不是调高或压低某个 priority 数值硬碰硬,而是用 chain priority 主动重构执行路径,把 Docker 的规则“请出去”或“让开道”。Docker 默认依赖 iptables 工具链注入规则(如 DOCKER、DOCKER-USER 链),而 nftables 无法覆盖它们——priority 不是万能胶,但它是调度器:让你决定哪段逻辑先说话、在哪条路上拦人。
策略一:在 input/forward hook 最前端设防(抢占控制权)
不和 Docker 规则争位置,而是比它更早拦截或放行。Docker 的 filter 规则通常落在 priority 0 或正数区间(如 100),而内核预留给连接跟踪的是 -200,raw 是 -450。你可以用更低值提前接管:
- 创建早于所有 Docker 规则的链:
nft add chain inet filter early_input { type filter hook input priority -400 \; policy drop \; } - 在此链中明确放行可信来源(如管理网段)、丢弃扫描包,避免后续规则被干扰
- 同样对 forward hook 做:
nft add chain inet filter early_forward { type filter hook forward priority -400 \; },专用于容器入向流量初筛
策略二:为 docker0 流量单独建链(物理隔离)
Docker 容器间通信走 docker0 桥接接口,其转发路径本就特殊。与其在主 filter 链里和 Docker 规则混战,不如划出专属车道:
- 禁用 Docker 自动操作 iptables:
{ "iptables": false, "ip6tables": false }写入/etc/docker/daemon.json并重启 Docker - 新建独立链处理桥接转发:
nft add chain inet filter docker_forward { type filter hook forward priority 100 \; } - 加规则只匹配桥接流量:
nft add rule inet filter docker_forward iifname "docker0" oifname != "docker0" accept - 这样,主机自身流量走主链,容器通信走 docker_forward,互不触发、互不覆盖
策略三:避开已占位 priority,做“安静共存者”
若你不想动 Docker 行为,也不愿接管全部网络,可选择兼容路线——查清当前占用,再找空档落子:
- 运行
nft list chains,看 input hook 下已有哪些 priority(比如 -200、0、150) - 选一个未被使用的值,如 -250 或 50,新建链:
nft add chain inet filter custom_input { type filter hook input priority 50 \; } - 把自定义策略(如限速、地域封禁)写进这个链,不碰 Docker 的 0 和 100 区间
- 配合
nft monitor trace发包验证:确保测试流量确实进入该链,而非被更高优先级规则提前终结
必须做的三步验证(缺一不可)
加了 chain 不等于生效。真正起作用要逐层确认:
-
查链是否加载:
nft list chain inet filter early_input,输出中必须含hook input priority -400 -
查规则是否入内核:
nft list ruleset -a -n,看是否有对应 handle 和计数器(counter)递增 -
查内核有无拒绝:
dmesg | tail -10 | grep nf_tables,出现File exists即 priority 冲突(重复创建),需删旧链重试


















