☰
nftables vs iptables:原理拆解与实测性能对比
2026/10/7 5:04:36 网站建设 项目流程

最近被问得最多的一个问题:nftables 到底比 iptables 快在哪?有没有实测数据能参考?老实说,网上聊 nftables 的文章不少,但大部分停留在“新框架、效率高”这种感性描述上,真正给出可复现测试方案和趋势结论的很少。正好我这半年一直在把线上防火墙往 nftables 迁,也做了几轮对比测试,今天就把性能优势的来源、压测思路和几组参考数据一次讲清楚。

先说结论:nftables 的性能不是靠某个“魔法开关”,而是靠执行模型和数据结构的重构。它把防火墙规则集从一条条“链表记录”变成一份“可编译、可索引的规则程序”,再配合内核里哈希表、红黑树等结构做大集合匹配。这套设计在规则少时和 iptables 拉不开差距,规则一多、更新一频繁,差距就非常明显。适合谁看?正在规划从 iptables 迁移的网络工程师、被多规则场景性能折腾过的安全运维,还有想在生产环境验证“别人说 nft 快”的 Linux 玩家。

1. nftables 性能优势的本质:从“遍历链表”到“可编译的规则集”

1.1 iptables 的执行模型与真正的瓶颈

iptables 是 netfilter 框架的老牌用户态工具,内核里每个表(filter、nat、mangle、raw)都由若干条链组成,每条链本质上是线性链表。数据包进入 hook 点后,从链头开始逐条匹配,直到第一条命中的规则产生动作(drop、accept、jump 到自定义链等)。

这个模型在规则量少的时候完全够用,几十条规则,平均匹配几次就结束了,CPU 开销可以忽略。但规则一旦堆到几百上千条,流量又大(尤其是 64 字节小包场景),问题就来了:每个包都要从链头重新走一遍规则,平均匹配次数随着规则数量线性上涨,CPU 大量消耗在 ruleset 遍历和分支预测失败上。

更麻烦的是 iptables 的多表穿行。一个包在转发路径上,raw、mangle、nat、filter 都可能被分别检查,自定义链之间还要跳转(jump/goto)。规则放的位置稍不注意,平均查找路径就会被拉长。你可以把 iptables 想象成一条长走廊,保安从 1 号房间开始一间一间查,直到找着对应的门牌。平时人少无所谓,但 DDoS 流量像马拉松一样涌进来时,保安直接在走廊上跑死。

1.2 nftables 的设计:规则集即程序

nftables 从设计之初就走了一条不同的路:把链、规则、表达式整体编译成内核可执行对象。它不再要求每条规则都从链表头开始,而是允许你把匹配条件结构化——能用集合(set)用集合,能用映射(map)用映射,内核里的哈希表或红黑树来做查找,复杂度接近 O(1)。

即便你不用集合和映射,nftables 的规则执行路径也比 iptables 更紧凑。规则内部采用表达式组合,verdict(跳转/接受/丢弃)处理的指令密度比“逐条 iptables 规则”要精炼,一个包在规则集里经过的条件判断次数更少。再加上 nftables 是单一框架,IPv4、IPv6、ARP、bridge 共用一套内部结构,而不是像 iptables 那样每个协议族维护一套独立的表,存储和更新的开销也低一截。

提示:很多人误以为“nftables 快是因为 netfilter 框架本身变了”,其实 netfilter hook 体系还在,conntrack 也还是那个 conntrack。真正的变化在规则集的数据组织和查找方式。

2. 五个最能体现 nftables 性能优势的场景

2.1 大中型规则集:从线性搜索到哈希查找

这是 nftables 和 iptables 差距最直观的场景。生产环境里,出口防火墙上千条黑名单、IDC 安全网关做正则式源 IP/端口过滤,这些都不罕见。iptables 在这种规则量下,每新增一条规则,所有新连接的平均匹配成本都会增加一点。

nftables 的大集合查找几乎是“一条规则”完成判断。比如动态封禁一批 IP:

nft add table inet myfilter nft add set inet myfilter blacklist { type ipv4_addr\; flags timeout\; timeout 1h\; } nft add element inet myfilter blacklist { 1.2.3.4, 5.6.7.8 } nft insert rule inet myfilter forward ip saddr @blacklist drop

上面这条规则的意思是:只要源 IP 落在@blacklist集合里,直接 drop。后续加 IP 只需要nft add element,数据面查找走哈希表,不用改动规则本身。我线上压测的感觉是,规则量超过 500 条以后,iptables 的 PPS 下降趋势已经肉眼可见;到了 3000 条以上,同等规则语义下 nftables 的包处理能力能高出 iptables 好几倍,规则量越大优势越明显。

2.2 动态更新与批量事务:从“抖动窗口”到“原子生效”

生产防火墙最怕的不是规则多,而是改规则的那一瞬间。老运维应该都经历过:用 iptables 逐条-A添加规则时,要么先 flush 整条链再重灌,要么一条一条往上加,中间要么出现短暂无保护窗口,要么出现规则集半更新状态。对安全设备来说,这个窗口是致命的。

nftables 支持事务式提交,所有规则变更可以放到一个文件或一次 netlink 消息里,要么全部生效,要么全部回滚。例如:

cat /etc/nftables.update.conf add element inet fw blocked { 203.0.113.5 } delete element inet fw blocked { 198.51.100.2 } nft -f /etc/nftables.update.conf

我实测过动态封禁/解封场景:批量更新 5 万条黑名单元素时,iptables 逐条执行要好几分钟,期间 CPU 持续走高;nftables 用事务式文件提交,几秒内完成,数据面没有出现明显丢包和抖动。iptables-restore 虽然能缓解一部分问题,但它本质上是先清空再导入,仍然存在原子性缺口和回滚缺失。对依赖 API 自动化下发的安全平台来说,这个差距直接决定了可用性。

2.3 集合与映射:一条规则替代一百条规则

iptables 里很多场景需要展开成多条规则:不同 IP 走不同动作、不同端口段做不同策略、黑白名单混合……规则越多,链越长,性能越差。nftables 的映射(map)机制可以把“判断”变成“查表”。

举个例子,按目的 IP 走不同策略:

nft add table ip fw nft add chain ip fw forward { type filter hook forward priority 0\; } nft add map ip fw policy { type ipv4_addr : verdict\; } nft add element ip fw policy { 192.0.2.10 : drop, 198.51.100.0/24 : accept } nft add rule ip fw forward ip daddr vmap @policy

这里vmap @policy的意思是:拿目的 IP 去查 verdict map,查到谁就直接执行对应的动作。该拒绝的拒绝,该放行的放行,全部在哈希表里完成,不再逐条比对。我见过有人把几百条 iptables 白名单策略用一张 nftables map 重写,规则文件从几百行缩到几十行,线上 CPU 占用反而降了。这就是“少规则、高信息密度”带来的缓存友好性——规则集越小,CPU cache 命中率越高,包处理越快。

2.4 多核与软中断协同

防火墙吃 CPU,主要不是吃在规则引擎本身,而是吃在软中断收包、conntrack 哈希表查询和规则匹配三件事上。前两件事 iptables 和 nftables 都要做,差异不大;区别在规则匹配路径。

iptables 的规则更新会引入全局锁串行化,尤其在频繁增删规则时,多个 CPU 核心会互相等待。nftables 的规则集在数据面以只读方式被各核心共享,更新走事务机制,匹配路径上的锁开销更小。配合网卡多队列、RSS(Receive Side Scaling)、IRQ affinity 设置,每个核心独立处理自己的队列,扩展性明显更好。

我在双路服务器上做过并发压测:多个线程同时往防火墙里灌规则,iptables 偶发 CPU 飙升和软中断不平衡,nftables 的表现要平滑得多。多核场景下,nftables 的吞吐扩展曲线更接近线性,iptables 则容易出现平台期。

2.5 与 conntrack/NAT/限速组合的复合场景

现实中的防火墙不会只有过滤规则,还有状态跟踪、NAT 映射、限速、日志。iptables 做全套策略,经常要在 raw、mangle、nat、filter 多张表里来回穿行,一个连接被检查很多次。nftables 可以把状态判断和地址/方向判断组织在同一个链里,结构化完成。

比如一个比较完整的 forward 链,需要判断连接状态、匹配源地址集合、执行 NAT 映射、决定最终动作,用 nftables 可以在同一条链内按优先级组织不同表达式,减少多次跳转带来的额外开销。这也是很多人提到“防火墙关闭有影响吗”时容易忽略的点:很多时候瓶颈根本不在规则引擎,而在 conntrack 表满和软中断压力上,关闭防火墙不但不解决问题,还白白丢掉安全防护。

3. 实测数据参考:一套可复现的 nftables vs iptables 对比方案

3.1 测试环境怎么搭

网上流传的“nftables 比 iptables 快几倍”大多没有交代环境和规则集设计,参考价值有限。我自己做对比测试时,环境是这样搭的:

项目配置
CPUIntel Xeon E-2278G 8C16T,隔离 4 个核给软中断
内存32GB
网卡Intel X710-DA2 双口 10GbE,开启多队列
内核6.1 LTS,nf_tables 模块默认开启
发包工具TRex / pktgen,固定 64 字节小包
流量模型随机目的端口/随机目的 IP,模拟五元组差异

关键点:对比必须在同一台机器、同一个内核版本下进行,否则内核参数差异会污染结果。建议先把 iptables 的规则集准备好,用iptables-restore一次性挂载测试一轮;再把这套规则等价翻译成 nftables 原生语法,用nft -f挂载测试另一轮。

3.2 规则集怎么设计才公平

公平对比的核心是“规则语义等价”。我建议分三档规则量:10 条、1000 条、10000 条。规则内容统一为五元组匹配(源 IP、目的 IP、协议、源端口、目的端口),最后一个匹配规则写 drop,这样每个包都要走到链尾附近,能充分暴露查找路径长度差异。

注意,公平对比不应该让 iptables 使用 ipset。ipset 是独立于 iptables 的扩展工具,虽然它也用哈希集合,但它不代表 iptables 原生规则集性能。我们要对比的是“两者作为防火墙框架本身的规则集组织能力”。如果你的 iptables 命令实际指向的是 iptables-nft 兼容层,那它本质上已经在用 nf_tables 后端了,但因为你写的是 iptables 语法,享受不到原生 set/map 的数据结构优势,性能也会打折。这个后面细说。

3.3 我看过的实测数据和自己的样本

公开资料里,Open vSwitch 社区、Red Hat 博客和一些海外网络工程博客都发布过 nftables 与 iptables 的基准测试,可以用 “nf_tables iptables benchmark” 这类关键词搜到。大家的方向性结论高度一致,我这里也给出自己测试机上的一组趋势数据:

场景iptablesnftables说明
10 条规则,64B 小包接近网卡上限接近网卡上限规则集短时线性遍历不构成瓶颈
1000 条规则,64B 小包明显下降,CPU 成瓶颈下降幅度小,接近线速集合/映射查找优势充分体现
10000 条规则,64B 小包断崖式下跌仍可维持可用水平差距可达一个数量级
50000 条规则热替换逐条添加需分钟级事务式提交秒级内完成动态更新场景差异最大

强调一下:上面这些数字只代表我所在测试机的趋势,不要直接拿去当基准。硬件、内核、规则内容不同,绝对 PPS 会差很多。但方向性结论是稳定成立的:规则量越大,nftables 的查找优势越明显;更新越频繁,nftables 的事务优势越突出;大包场景两者都能线速时,差异反而不重要。

3.4 为什么小包测试最考验防火墙

64 字节小包是网络设备的“照妖镜”。小包意味着单位时间里包的个数更多,规则匹配次数更多,CPU 成为瓶颈。1518 字节大包更容易打到线速,因为每个包承载的数据量大,CPU 有更多时间去查规则。很多人看到“防火墙跑满万兆”就觉得性能没问题,实际上可能只是他的业务流量是大包为主。真正要评估防火墙极限,必须用小包测试。

另一个容易被忽略的指标是“规则更新耗时”和“更新期间是否丢包”。我用脚本循环执行封禁/解封 IP 时,iptables 版本偶尔会出现规则集半更新状态,CPU 使用率明显波动;nftables 版本用事务批量提交,数据面平滑无丢包。这个体感差异比单纯看 PPS 更关键——生产环境里,防火墙规则更新频率高不高,直接影响业务可用性。

4. 迁移与调优:把 nftables 的性能吃透的实操要点

4.1 先分清原生 nftables 与 iptables-nft 兼容层

很多发行版默认的iptables命令已经指向 iptables-nft 兼容层,只是把 iptables 语法翻译成 nf_tables 后端执行。执行iptables -V,如果输出带nf_tables字样,那说明你已经在用 nf_tables 内核框架了。

但兼容层为了保持 iptables 语义,只能沿用“逐条规则、线性链”的表达方式,用不上原生 nftables 的 set、map、vmap、事务式批量提交这些关键武器。你要测 nftables 的真实性能,或者想在线上享受 nftables 的红利,就得写原生 nft 语法,用nft命令直接操作。兼容层只能作为迁移过渡,不能当性能解。

4.2 集合与映射的类型选型决定生死

nftables 的 set 不是只有一种实现。类型声明会直接影响数据面查找效率和内存占用:

  • 默认集合对小规模固定元素表现很好。
  • flags interval用于 CIDR 聚合,内核用区间树存储,适合“10.0.0.0/8、192.168.0.0/16”这类大量网段合并的场景。
  • flags timeout用于动态过期元素,适合封禁名单。
  • dynamic与timeout配合,可以做到“首次见包自动加入集合并计时”,相当于用户态 CT 自动封禁的基础。

我在生产里踩过的坑是:把所有 IP 都丢进一个没声明类型的大集合,某些特定查找模式会退化。正确做法是,先想清楚集合的访问模式——是固定黑名单,还是频繁增删的临时封禁,还是网段聚合,然后选对应 flags。选错了,性能可能还不如 iptables。

4.3 链的层次与优先级设计

nftables 的链既可以挂到 netfilter 标准 hook(prerouting、input、forward、output、postrouting),也可以做普通链供其他规则跳转。每个挂 hook 的链都有 priority 数字,数字越小越先执行。比如 conntrack 相关处理通常在那里,filter 链默认 priority 0。

实操建议:不要为了“结构清晰”搞太多普通链跳来跳去,每次 jump 都有额外开销。能用集合、映射在一个判断里解决问题的,就不要拆成两层链。尤其避免“filter 链跳自定义链、自定义链里再跳另一个自定义链”的三层跳转结构。规则集确实需要分文件分表管理,但运行时执行路径要尽量扁平。

4.4 内核参数和网卡队列的配合不能少

nftables 再快,也快不过网卡收包瓶颈。测试和生产环境都先确认网卡多队列打开没有:

ethtool -l eth0 ethtool -L eth0 combined 8

配合 RSS 让不同队列把不同五元组哈希到不同 CPU,软中断就能并行处理。还可以检查nf_conntrack_max和nf_conntrack_buckets,conntrack 哈希表太小会导致连接追踪成为瓶颈,表现就是“防火墙规则看似不多,但 CPU 全在 softirq 里打转”。很多人以为关掉防火墙能提升性能,实际排查下来往往发现是 conntrack 表满,或者网卡队列没开。先调这些,比关防火墙靠谱得多。

4.5 规则集管理上的性能卫生

日常运维里,nft list ruleset在规则很多时是个昂贵的操作,全量输出全套规则并格式化,几百条还好,几万条的时候会明显吃掉 CPU。生产环境不要在高流量时段反复执行全量 list,需要看规则就按表按链过滤查询。

批量更新前先做语法检查:

nft -c -f /etc/nftables.conf

-c是 check 模式,只检查不提交,能在真正生效前发现语法或引用错误,避免事务提交到一半失败触发的回滚流程。这个习惯和我前面说的事务机制配合起来,线上规则变更的风险能低很多。

5. 常见问题与排查技巧实录

5.1 问题速查表

现象大概率原因快速定位方法
nftables 性能没比 iptables 好多少用了 iptables-nft 兼容层 / 没用到 set 和 map / 规则本身就几条iptables -V看后端,检查规则集结构
动态封禁后 CPU 持续走高set 没声明 timeout,元素只增不减nft list set查看集合元素数量,确认 flags
规则集很大但查询依然慢集合类型选错,比如固定 IP 段应走 interval查看 set 定义,按访问模式重选 flags
防火墙规则改动期间丢包还在用逐条增删方式,没用事务改用nft -f批量提交,或把多条命令写入一个事务
小包流量 CPU 满载、大包正常规则匹配是瓶颈,需要看规则集规模和结构用小包压测,逐条检查规则平均匹配路径
多核扩展性不好网卡未开多队列,或软中断绑核不合理ethtool -l和/proc/irq/核对

5.2 我踩过/见过的几个坑

第一个坑:在旧内核上用新特性。nftables 基础功能内核 3.13 就有了,但 set、map 的高级特性、interval 集合、带 timeout 的动态集合,依赖的内核版本更高。我见过有人把生产环境内核停在 4.x,然后上了flags interval的集合,触发奇怪的性能问题。先查内核版本和发行版 nftables 版本再选特性。

第二个坑:动态集合的 timeout 和垃圾回收间隔。flags timeout的集合支持元素自动过期,但 GC 运行有间隔,如果你频繁加元素又不清理,集合会在短时间内膨胀,哈希表负载升高,查询变慢。合理的做法是设置合理的 timeout,并定期手动清理不再需要的元素区块。

第三个坑:把“能用一条 map 解决的事写成几百条规则”。这个坑更多来自习惯——从 iptables 迁过来的人,第一反应还是“一个动作一条规则”。nftables 的 map/vmap 机制其实更像路由表,按 key 查结果。你越早习惯用“查表”思路写规则,越能体会到性能红利。写每条规则前都先问一句:这个判断条件能不能塞进集合或映射?

5.3 从老框架迁移的一个实用技巧

迁移时别一次性从 iptables 全量重写规则。建议先梳理线上规则,给每条 iptables 规则标注“用途”和“命中率”,然后把高命中率、高频检查的规则优先迁到 nftables 的 set/map 结构里。低频规则可以暂时留在兼容层里过渡。这样既控制风险,又能把 nftables 的收益用在刀刃上。迁移完成后,再用nft list ruleset和之前的 iptables 规则做差异核对,确认语义一致。

我在实际运维中的体会是,nftables 真正改变的不只是性能数字,而是心态。以前改防火墙规则像在做高风险外科手术,现在事务式提交加自动回滚,规则变更变成了日常操作。最后再分享一个小技巧:如果你要频繁检查某条规则是否生效,别用nft list ruleset | grep,直接nft get element查集合里的具体元素,代价小一个量级。这是我最近用下来体验最明显的一个细节。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询