nftables复合表达式通过结构化、可嵌套、可复用的方式整合多条件匹配与多动作执行,单条规则即可完成日志、计数、限速、放行等操作,避免重复解析报文头,并支持集合、命名链跳转及映射动态策略分发。

nftables 的复合表达式是它区别于 iptables 的核心能力之一,不是简单地“多个条件拼在一起”,而是通过结构化、可嵌套、可复用的方式组织匹配逻辑与动作,让一条规则承担过去需要多条规则甚至多个链才能完成的任务。
复合表达式支持多条件组合与多动作执行
一条 nftables 规则可以包含多个表达式(Exprs)和多个语句(Statements),它们按从左到右顺序求值。只要所有表达式都匹配成功,后续所有语句就会依次执行——这正是高效性的来源。
例如,这条规则同时完成日志记录、流量计数、速率限制和放行:
nft add rule inet filter input tcp dport 22 counter log prefix "SSH: " limit rate 5/minute accept
它等价于 iptables 中需分四步实现的操作:加载 xt_LOG、xt_COUNTER、xt_limit 模块,再分别配置日志、计数、限速、跳转,而 nftables 在单条规则中自然融合。
关键点在于:
-
counter和log是独立语句,不终止规则流程 -
limit是带状态的匹配表达式,只在满足速率条件时才让后续accept生效 - 所有操作共享同一匹配上下文(tcp dport 22),避免重复解析报文头
支持嵌套结构与逻辑分组
nftables 允许用花括号 {} 显式分组表达式或语句,提升可读性与控制粒度。比如对多个端口统一施加限速策略:
nft add rule inet filter input tcp dport {22, 80, 443} \
counter \
log prefix "Web/SSH: " \
limit rate 10/second burst 20 packets \
accept
这里 {22, 80, 443} 是一个端口集合表达式,本身就是一个复合结构;而 limit 后的 burst 参数进一步细化了令牌桶行为,这种细粒度控制在 iptables 中需借助额外模块或外部脚本。
更进一步,你可以把一组常用动作封装成命名链,再在主链中调用:
nft add chain inet filter safe_accept { type filter hook input priority 0 \; }
nft add rule inet filter safe_accept counter log prefix "ALLOW: " accept
nft add rule inet filter input ip saddr 192.168.1.0/24 jump safe_accept
jump 是一个跳转语句,它把控制权交给另一条链,但不改变当前数据包的匹配状态——这种链间协作依赖于复合语句的非终结特性(只有 accept/drop/reject 等裁决语句才会终结规则执行)。
利用映射(maps)实现动态策略分发
复合表达式的高阶用法体现在与映射(map)结合时。例如,根据源 IP 自动选择不同的限速策略:
nft add map inet filter rate_map { type ipv4_addr : verdict \; }
nft add element inet filter rate_map { 192.168.1.100 : counter limit rate 1mbit/second accept }
nft add element inet filter rate_map { 10.0.0.0/8 : counter limit rate 100mbit/second accept }
nft add rule inet filter input ip saddr @rate_map
这里 @rate_map 不是一个静态判断,而是一次运行时查表操作,返回的是一个完整 verdict(含 counter + limit + accept)。整个右侧策略是动态绑定的,且查表本身是 O(1) 时间复杂度。
这种能力让 nftables 能支撑 VPS 多租户隔离、API 网关分级限流、IoT 设备差异化策略等真实场景,而无需为每个客户写一堆重复规则。
不复杂但容易忽略











