用ipset可实现百万级黑名单高效封禁,核心是采用hash:ip或hash:net配合maxelem/hashsize调优、restore批量导入、-m set精准引用、swap原子切换,达成o(1)查表与零丢包更新。

用 ipset 配合防火墙实现百万级黑名单高效封禁,核心是避开 iptables 线性匹配的性能陷阱,转而依赖内核级哈希查表(O(1)),让封禁 100 个 IP 和封禁 100 万个 IP 的开销几乎一致。关键不在“能不能加”,而在“怎么建、怎么引、怎么换、怎么稳”。
选对集合类型和参数,避免运行时溢出
百万级规模必须显式设定容量与结构,否则默认 65536 元素会很快报错 ipset v7.6: Error in line 1: set is full:
- 纯 IPv4 单 IP 封禁:用 hash:ip,例如
ipset create blackv4 hash:ip maxelem 1200000 hashsize 16384 - 含大量 /24、/23 等网段(如扫描器常用):改用 hash:net,更省内存且减少哈希冲突,命令为
ipset create blackv4 hash:net maxelem 1200000 hashsize 8192 - hashsize 建议设为略大于 maxelem 的 2 的幂(如 8192、16384),可降低碰撞率;maxelem 必须 ≥ 实际最大条目数,留 10–20% 余量
批量导入不卡壳,优先用 restore 而非循环 add
逐行执行 ipset add 在 shell 层启动上万次进程,耗时长、易中断、难回滚。正确做法是生成标准 restore 格式文件再一次性加载:
- 准备文本
blacklist.ipset,内容形如:create blackv4 hash:net maxelem 1200000<br>add blackv4 192.168.1.0/24<br>add blackv4 203.0.113.42<br>add blackv4 198.51.100.128/25
- 执行
ipset restore -f blacklist.ipset,秒级完成百万条导入 - 若源数据是纯 IP 列表(每行一个),可用
awk '{print "add blackv4 " $1}' blacklist.txt > blacklist.ipset快速转换
iptables 引用要精准,位置和模块缺一不可
规则写错会导致集合完全不生效,常见失效点:
- 必须加载 -m set 模块:
iptables -I INPUT -m set --match-set blackv4 src -j DROP,漏掉-m set会报错 No chain/target/match by that name - 规则必须插入链首(
-I INPUT),不能追加(-A INPUT);若已有-j ACCEPT在前,后续的 DROP 规则将永远不触发 - 确认 IP 版本匹配:IPv4 集合(
hash:ip或hash:net)无法拦截 IPv6 流量,需另建blackv6 hash:ip6并加对应规则
动态更新零丢包,用 swap 实现原子切换
直接 ipset flush blackv4 && ipset restore -f new.ipset 会在清空瞬间放行全部黑名单 IP,造成安全窗口。安全做法是双集+swap:
- 维护两个同类型集合:
blackv4(线上生效)和blackv4_new(后台构建) - 新名单生成后,执行
ipset swap blackv4 blackv4_new——毫秒级完成,旧集合变空,新集合立即生效 - 立刻执行
ipset destroy blackv4_new释放内存,防止残留空集合长期占用内核资源 - swap 前务必确认两集合类型、family(inet/inet6)完全一致,否则报错 Set cannot be swapped: different types
整套流程跑通后,你面对的是一个可承载百万级条目的、热更新无感知、CPU 开销恒定的黑名单系统。它不依赖外部服务,不增加用户态延迟,纯粹靠内核数据结构兑现性能承诺。











