oss

规则尚未变短,iptables 迁移已经成功

8 条来源 1 条一手来源 已翻译 2026年7月25号

正文
2016 年的一场 nftables 研习会上,Pablo Neira Ayuso 面带微笑,佩戴头戴式麦克风和 NLUUG 姓名牌。

2016 年 NLUUG 春季大会期间,Pablo Neira Ayuso 出席一场注重实践的 nftables 研习会。理解这类迁移,应当把它视为在线系统上的策略作业,依据来自实际加载的规则和真实穿行的数据包,搜索替换无法代替这项工作。图片由 NLUUG 提供,CC BY 3.0,未经修改,取自 Wikimedia Commons。[8]

替换 iptables 时,学习大括号该写在哪里只占风险的一小部分。真正危险的是,等到迁移后才发现,已经转换的规则从来没有涵盖整套防火墙。

一台运行多年的主机上,规则可以来自启动脚本、发行版服务、容器引擎、VPN,也可以由管理员直接在命令行写入。有些命令已经借助兼容层调用 nf_tables 内核后端,表面仍沿用熟悉的 iptables 语法。因此,生成的 nftables 文件即使语法正确,运行结果仍会出错:它会重复另一套管理程序的工作,漏掉仅在运行时出现的规则,也会在下一次服务重新加载时被覆盖。

安全迁移包含两个有意分开的目标。第一步是在唯一且名称明确的所有者之下保持行为一致。等到切换过程可以观察,也能回退,团队再启用原生 nftables 的能力,例如 IPv4/IPv6 共用链、集合、映射以及规则集的原子更新。转换是一座桥,精简则属于后续工程。[1][5]

题图拍摄于 2016 年,Pablo Neira Ayuso 正在一场研习会上讲解 nftables 实践。这样的现场很贴合本文:防火墙迁移是一项动手处理系统的工作,决定性证据来自内核实际加载的规则,以及真正穿过这些规则的数据包。[7][8]

转换语法之前,先冻结所有权

先建立一份所有权台账,新配置文件留到后面。记录 iptables -Vip6tables -V,让清单明确写出所用后端,避免依赖假设。保存 iptables-saveip6tables-savenft list ruleset 的输出;如果主机处于混用状态或后端不明,还要分别保存 iptables-legacy-save / ip6tables-legacy-saveiptables-nft-save / ip6tables-nft-save 所显示的内容。如果本次也纳入 ipsetebtablesarptables,要一并记录它们的状态。[1][6] 随后找出所有能够改变最终结果的进程,检查服务单元、网络上线钩子、配置管理角色、容器或集群网络、VPN 生命周期脚本,以及人工维护的恢复脚本。逐项记录重启后、网络接口变化后、应用部署后由哪个组件掌握权威状态。

这一步可以防止最常见的类别错误:把后端当成所有者。一台主机可以运行 firewalld,内核则用 nftables 保存由此生成的策略;若再让一套手写的 nftables.service 规则集并行管理相同钩子,所有权就会发生重叠。Debian 当前的说明把这些层次讲得很清楚:nftables 是其默认防火墙框架;已安装的 iptables 命令通过 iptables-nft 使用 nf_tables 后端;希望由系统代管底层脚本的管理员可以考虑集成于系统的 firewalld 包装层。文档同时建议,只有理解其中相互作用的运维人员才考虑混用 nftables 与旧式规则管理界面。[6]

同样的道理也适用于这两项服务之外的组件。若编排系统负责 pod 转发,或 VPN 负责标记和路由链,可以保留原有所有权,并设计一个写入文档的集成点,也可以有计划地转移所有权。若只把当前运行时输出复制到静态文件,这项依赖依然存在。

切换开始之前,台账应当回答四个问题:

  1. 哪个程序创建每一张表或每一条链?
  2. 哪个事件会重新加载或修改它?
  3. 哪些流量依赖它,其中是否包括 IPv6 与转发流量?
  4. 替换失败时,由哪一种单一方式恢复访问?

只要答案仍有缺口,迁移就还没进入处理语法的阶段。

把转换稿当作行为一致的脚手架

Netfilter 项目提供两条实用路线。iptables-translateip6tables-translate 用于转换单条命令,iptables-restore-translateip6tables-restore-translate 则把保存的规则集转换为 nft -f 能够读取的输入。[1] 第一版原生草稿适合由这些工具建立,因为相比凭记忆手工改写,它们能保留更多顺序和策略细节。

工具转换只生成草稿,行为仍须验证。迁移指南展示了一种情况:遇到不受支持的转换时,结果会成为注释行,无法作为有效策略执行。另一方面,当前 nft 手册警告,xt 语句表明该规则由 xtables 兼容界面创建,nftables 自身无法恢复这类语句。[1][2] 因而,每一条转换注释、兼容语句、扩展、自定义 target 和警告都对应一项测试义务,需要逐一核验。

第一版草稿应当有意保持朴素。保留基础链钩子、优先级、默认策略、连接跟踪条件、NAT 方向、接口匹配、日志速率限制和规则顺序。即使 IPv4 与 IPv6 两份文件重复,也要保留各自的行为。若一次迁移同时处理转换、去重、重命名和策略变更,一旦某类流量中断,便很难找到清楚的解释。

还要区分 iptables-nftiptables-legacy。前者用 xtables 语法操作 nftables 后端,后者使用较早的 x_tables 子系统。Netfilter 迁移指南提醒,旧式子系统与 nftables 子系统同时运行会带来意外结果。[1] 兼容路线可以减少过渡期内应用程序的中断,但这项依赖要有明确名称和期限。否则,两套命令语言会继续描述同一份内核策略,运维人员也始终无法确认哪一个界面具有权威地位。

让文件同时成为事务与回退工件

原生 nftables 适合以文件为单位操作。命令 nft -c -f candidate.nft 只检查文件中的命令,不会应用它们;nft -f candidate.nft 则提交整串命令并加以应用。[2] 就整套规则集而言,nftables 可以原子加载替换规则,数据包不会在命令执行期间遇到一套只建到一半的防火墙。[3]

能否成为完整替换,取决于文件内容。一个只含 add 命令的文件,会在当前状态之上不断累加项目。nftables 操作指南给出了覆盖整个命名空间的备份方式:写入 flush ruleset,附上列出的规则集,再用 nft -f 原子加载文件。[3] 只有当该工件独占整个命名空间中的 nftables 策略时,才能使用这种全局清空操作;flush ruleset 会删除每一张 nftables 表和每一个项目,其中也包括其他管理程序写入的内容。如果所有权经过设计而由多方共享,事务应当只删除和重建该工件拥有的表或协议族。

可以据此安排一次受约束的切换:

原子性保护的是两套规则集之间的转换过程;新规则集是否准确表达了预期策略,仍要另行验证。即使 SSH 锁定完全以原子方式发生,它仍是一场锁定事故。

测试以行为为准,文字相似放在一边

行为一致测试套件应按流量编写,而不是按链编写。最低限度要覆盖本地入站、本地出站、路由转发、已建立连接、新连接、各个实际使用方向上的 NAT、回环流量、管理访问、DNS 和两个 IP 协议族。标记、策略路由、隧道、网桥或容器网络等服务也要加入专门用例。每条获准流量旁边都应设置一条相近的拒绝流量,防止意外放宽的接受规则被误认为测试成功。

计数器很有用,但 nftables 不会为每条规则隐式附加计数器;计数器属于显式的有状态项目或语句。[5] 在观察期内,把它们放到转换后的决策点上。向新旧策略送入相同测试流量,比较各项策略结果对应的增量,同时要考虑后台流量存在后,计数器无法逐字节吻合。

遇到难以确认的链路,nftables 还有一种效力更强的工具。可以用范围狭窄的规则为选定数据包设置 meta nftrace,再由 nft monitor trace 按跟踪标识符报告它们走过的链路。[7] 跟踪范围应限定在测试地址、端口或接口。若无差别地打开跟踪,证据会迅速泛滥,反而更难解读。

进入正式环境的门槛取决于行为:金丝雀主机在重启后仍然工作;预定的所有者能重建同一套策略;重要的获准与拒绝链路表现正确;计数器和跟踪结果能够解释这些表现;回退流程也经过演练。“转换后的文件成功加载”只满足其中一个条件。

行为一致之后,再着手精简

原生规则集稳定运行后,nftables 才开始回报迁移成本。inet 协议族表允许 IPv4 和 IPv6 数据包穿过同一组基础链,必要时仍可用特定协议族的表达式加以区分。[4] 由此,真正共用的策略——已建立连接、双栈服务端口、接口分界——可以写成同一套规则,同时保留 IPv4 与 IPv6 规则之间真实存在的差异。

集合把大量近乎相同的重复规则换成带类型的值集。映射把键与值关联起来,verdict map(裁决映射)还可以把键直接关联到一项决定或一条链。Netfilter 文档把这种通用的集合与映射设施,以及区间和拼接,列为 nftables 与 iptables 的主要差异之一。[5] 收益超出了行数减少本身。“办公网络”“已发布服务”和“目的地址转换”等策略内容会成为有名称的数据,可以与控制流分开审阅。

每次只做一项语义改动。先合并双栈过滤链路,测试,然后停下。再把一组重复地址规则改成集合,测试,然后停下。接着把一项 NAT 选择移入映射,测试,然后停下。说明所有权和意图的注释应当保留;简短语法若缺少维护脉络,只会把含混之处压缩得更紧。

调整基础链钩子和优先级时尤其需要克制。nftables 允许运维人员选择链在数据包处理流程中的进入位置及优先级,当多个子系统共存时,这项能力十分强大。[2] 与此同时,一次看似无害的重组也会改变某条规则是在连接跟踪、NAT 或另一管理程序的链之前运行,还是在其后运行。优先级变化应当按数据包链路变化处理,规格高于格式调整。

识别哪些系统不适合直接转向 nftables

当团队拥有一套复杂的主机或网络防火墙,需要明确控制钩子和优先级,可以从集合或映射中获益,并且能像测试代码一样测试数据包链路时,直接使用 nftables 很合适。如果迁移后无人负责 Linux 网络,较高层的管理程序已经能够安全表达所需策略,或者设备及集群平台承诺接管底层规则集,直接管理 nftables 的做法就不合适。

小团队尤其要如实衡量这项运维取舍。原生语法可以让大型规则集更连贯,但审阅、预演、控制台访问、监控和值班人员的知识储备仍需团队另行准备。如果集成于系统的 firewalld 包装层已经覆盖实际需求,继续由这个较高层组件掌握所有权,会更易维护。[6] 如果平台持续改写主机网络,合适的迁移方式是更新平台支持的配置,仍由平台管理底层规则。

故障信号很明确:切换以后,运维人员仍然交替使用 iptablesnft;多项服务仍可重建彼此重叠的链;没人能说明重启后究竟由哪个文件取得最终控制权。此时语法已经变化,控制问题仍原样存在。

当唯一所有者能够重建、观察、测试和回退防火墙时,iptables 到 nftables 的迁移才算完成。更短的规则集可以留到以后。第一个发布目标是行为一致。

来源

  1. Netfilter Project,“Moving from iptables to nftables”——单条命令与完整规则集转换、iptables-nft 兼容后端、不受支持的表达式警告,以及混用 legacy 与 nftables 子系统的风险。
  2. Netfilter Project,nft(8) 手册——文件输入、仅检查校验、规则集检查、兼容语句、表达式、映射和裁决行为。
  3. Netfilter Project,“Operations at ruleset level”——完整规则集列示、显式清空、备份构造和基于文件的原子恢复。
  4. Netfilter Project,“Nftables families”——ipip6inetarpbridgenetdev 协议族的范围,其中包括 inet 表中的双栈共用链路。
  5. Netfilter Project,“Main differences with iptables”——显式计数器、双栈管理、动态更新、集合、映射、区间和拼接。
  6. Debian Project,“nftables”——关于 nftables 作为默认框架、iptables-nft 兼容层、firewalld 作为较高层所有者、启动配置以及避免混用规则管理界面的独立下游说明。
  7. Netfilter Project,“Ruleset debug/tracing”——限定范围地启用 nftrace,并用 nft monitor trace 检查数据包链路。
  8. NLUUG,“Pablo Neira Ayuso — Getting a Practical Grasp of nftables”(2016 年 5 月 26 日),Wikimedia Commons——文章题图所用研习会档案照片的出处及活动背景。
Previous Apache 的发布投票把信任写进程序

Recommended In oss

Matched by subject and format