nftables用Set实现O(1)匹配,避免逐条规则导致的性能瓶颈;通过hash表存储IP、支持CIDR和timeout自动过期,一条规则即可拦截数万个IP。

用nftables管理数万条恶意IP,关键不在“加多少规则”,而在“怎么不加规则”——集合(Set)就是那个让O(N)匹配变成O(1)查找的核心机制。
为什么必须用Set,而不是逐条写规则
传统方式每封一个IP就写一条ip saddr x.x.x.x drop,到上万条时:规则集体积暴涨、内核遍历耗时线性增长、每次增删都要重载整条链,极易丢包或卡顿。而Set把所有IP存进哈希表或区间树,匹配时只需一次查表,无论100个还是10万个IP,性能几乎不变。
- IPv4地址集合底层用高效哈希结构,插入/查询平均时间复杂度为O(1)
- 启用
flags interval后支持CIDR和IP段(如192.168.1.0/24或10.0.0.1-10.0.0.255),大幅压缩条目数 - 配合
timeout标志还能自动清理过期IP,无需定时脚本手动清理
创建与维护高性能黑名单Set的实操步骤
以IPv4黑名单为例,一条命令完成初始化:
sudo nft add set inet filter blacklist { type ipv4_addr \; flags interval \; timeout 24h \; }
-
inet协议族确保同时兼容IPv4/IPv6流量(若只管IPv4可用ip) -
flags interval启用区间匹配,单条规则可覆盖整个网段 -
timeout 24h让每个加入的IP自动24小时后过期,防误封长期有效
之后添加IP或网段极其轻量:
sudo nft add element inet filter blacklist { 192.168.5.100, 203.0.113.0/24, 198.51.100.10-198.51.100.20 }
注意:批量导入建议用文件+nft -f,避免shell参数过长报错;单次最多支持数千元素,超量请分批。
在规则中调用Set实现毫秒级拦截
创建好Set后,只需一条规则即可生效,不再需要为每个IP单独写规则:
sudo nft add rule inet filter input ip saddr @blacklist drop
- 该规则放在input链靠前位置(建议在established检查之后、服务放行之前)
-
@blacklist是引用语法,不是变量名也不是字符串,不能加引号 - 如果想记录日志再丢弃,可组合使用:
log prefix "BLACKLISTED: " drop
实测:在搭载Intel i5-8400的家用服务器上,含5.2万个独立IP + 380个/24网段的blacklist Set,新建连接匹配延迟稳定在0.01ms以内,CPU占用无可见波动。
自动化封禁闭环:从检测到落库只需三步
真正落地的关键是打通“发现→封禁→验证”链路。推荐一个轻量可靠的工作流:
- 用
fail2ban或自研脚本监听auth.log,提取高频失败IP - 通过
nft add element命令将IP注入blacklist Set(支持重复添加,无副作用) - 用
nft list set inet filter blacklist或--numeric --handle查看实时成员,结合counter统计命中次数验证效果
进阶技巧:可搭配Map做分级处置,例如用map ip saddr : verdict把不同风险等级IP导向不同链(如low-risk→限速,high-risk→立即drop),实现策略精细化。

















