nftables具名集合实现秒级ip拉黑,需创建带interval标志和timeout的ipv4_addr集合,单条规则引用即可o(1)查表丢包,支持原子增删ip/网段且不中断连接。

用 nftables 具名集合(named set)实现秒级拉黑 IP,关键在于把 IP 当作可动态增删的内核查表项,而不是写死在规则里。只要集合存在、规则引用它,新增一个 IP 就立即生效,整个过程不 reload 规则集、不 flush、不中断任何连接。
创建支持网段和自动过期的集合
恶意 IP 往往混着单地址和 CIDR 网段(比如 192.0.2.100 和 203.0.113.0/24),必须启用 interval 标志,否则网段会被拆成数百个独立条目,内存暴涨、性能崩溃:
-
正确命令:
nft add set inet firewall blacklist { type ipv4_addr \ flags interval \ timeout 10m \ size 100000 } -
timeout 10m表示 IP 加入后 10 分钟自动清理,适合临时封禁;如需永久拉黑,去掉 timeout 或设为很大值(如 1y) -
size 100000是预分配槽位数,防止高频增删时哈希扩容抖动,按预期最大 IP 数设即可
只写一条规则,覆盖全部黑名单
集合本身不拦截流量,必须在链中引用才能起作用。规则只需一条,放在 INPUT 链靠前位置,确保优先匹配:
nft add rule inet firewall input ip saddr @blacklist drop- 这条规则生效后,每个进包都会查 @blacklist 这个哈希表,命中即丢弃,平均耗时几十纳秒
- 不用重复加规则、不用遍历上万条语句,内核直接查表,O(1) 复杂度
运行时秒级添加或删除 IP
所有操作都是原子的,不影响已有连接和规则运行:
- 封单个 IP:
nft add element inet firewall blacklist { 203.0.113.42 } - 封整个网段:
nft add element inet firewall blacklist { 198.51.100.0/24 } - 解封某个 IP:
nft delete element inet firewall blacklist { 203.0.113.42 } - 批量导入(从文件逐行读):
while read ip; do nft add element inet firewall blacklist { $ip }; done
搭配日志与计数器验证效果
加 counter 和 log 可实时确认是否真正拦截成功,且不拖慢主路径:
- 修改原规则为:
nft replace rule inet firewall input handle X ip saddr @blacklist counter log prefix "BLACKLIST_DROP: " drop - 用
nft list counters查看命中次数,dmesg -t | grep BLACKLIST_DROP看日志输出 - 注意:log 动作仅在首次匹配时触发,不会每包打日志,避免刷屏











