nftables 的 set 通过哈希或区间树实现 o(1) 查找,支持单 ip 与 cidr 混合(需启用 interval 标志)、自动超时、运行时增删;正确写法为 nft add set inet firewall blacklist { type ipv4_addr \ flags interval \ timeout 24h \ size 262144 },链中仅需一条 nft add rule inet firewall input ip saddr @blacklist drop 即可高效拦截。

必须启用 interval 标志才能混用单 IP 和 CIDR 网段
恶意 IP 列表通常既有 192.0.2.42 这类单地址,也有 203.0.113.0/24 这类网段。若漏掉 interval,nftables 会把每个 /24 拆成 256 个独立条目,内存暴涨、插入变慢、查询降速。
- 错误写法(不支持网段):
nft add set inet firewall blacklist { type ipv4_addr } - 正确写法(支持混合+自动合并相邻段):
nft add set inet firewall blacklist { type ipv4_addr \ flags interval \ timeout 24h \ size 262144 } -
size建议设为预期最大元素数的 2–4 倍(如 10 万条设 262144),避免哈希冲突影响性能
链中只写一条引用规则,所有匹配由内核查集合完成
创建好集合后,防火墙链里无需重复写条件,只需一条规则触发查表动作:
- 先建基础链(默认丢弃):
nft add chain inet firewall input { type filter hook input priority 0 \; policy drop \; } - 再加拦截规则:
nft add rule inet firewall input ip saddr @blacklist drop - 这条规则生效后,每个入包的源 IP 都直接查
@blacklist集合,命中即丢,不走后续规则 - 注意:该规则必须放在链首或至少在
accept类规则之前,否则可能被提前放行
动态增删不中断服务,优先依赖 timeout 自动清理
集合支持运行时修改,适合对接威胁情报或封禁脚本,但要避开“清空再重载”这种危险操作:
- 加单个 IP:
nft add element inet firewall blacklist { 198.51.100.22 } - 加网段:
nft add element inet firewall blacklist { 192.0.2.0/24 } - 批量导入(推荐从文件读):
while read ip; do nft add element inet firewall blacklist { $ip }; done - 不要用
nft flush set inet firewall blacklist—— 清空瞬间所有 IP 全部放行,存在安全窗口 - 更稳妥的做法是设好
timeout(如timeout 1h),让过期条目由内核自动回收,脚本只负责添加新项
需要分级响应时,改用 Map 替代纯 Set
如果不同 IP 要执行不同动作(比如封 10 分钟 vs 永久拉黑),Set 不够用,得升级到 Map:
- 建映射:
nft add map inet firewall ip_action { type ipv4_addr : verdict \; } - 设策略:
nft add element inet firewall ip_action { 192.0.2.100 : drop, 192.0.2.101 : reject with icmp type host-unreachable } - 在链中调用:
nft add rule inet firewall input ip saddr @ip_action - 注意:nft Set 不支持 per-entry timeout,Map 本身也不带时间判断;如需自动过期,得配合用户态脚本定期扫描清理旧条目











