
最近被问得最多的一个问题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 的大集合查找几乎是“一条规则”完成判断。比如动态封禁一批 IPnft 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 的规则集在数据面以只读方式被各核心共享更新走事务机制匹配路径上的锁开销更小。配合网卡多队列、RSSReceive 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 LTSnf_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 标准 hookprerouting、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_bucketsconntrack 哈希表太小会导致连接追踪成为瓶颈表现就是“防火墙规则看似不多但 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查集合里的具体元素代价小一个量级。这是我最近用下来体验最明显的一个细节。