ipset管理百万级黑名单的关键是查得快、换得稳、不丢包:用hash:ip或hash:net配合合理maxelem/hashsize参数,通过restore批量导入和swap原子切换实现高性能与零丢包。

用 ipset 管理百万级黑名单,核心不是“加得进去”,而是“查得快、换得稳、不丢包”。它绕开 iptables 线性匹配(O(n))的瓶颈,靠内核哈希表实现接近 O(1) 的查找——封 100 个 IP 和封 100 万个 IP,对性能影响几乎一样。
选对集合类型和关键参数
类型和参数设错,轻则查不到、重则直接报错或内存暴增。
- 纯 IPv4 地址列表 → 用 hash:ip:内存低、插入快。命令示例:
ipset create blackv4 hash:ip maxelem 1200000 hashsize 16384 - 含大量网段(如 /24、/23 扫描器常用)→ 必须用 hash:net:原生支持 CIDR,
hash:ip对192.168.1.0/24会直接报错 -
maxelem 必须显式设置:默认仅 65536,超限报
Set is full;建议按峰值上浮 10–20%,比如预估 100 万条就设为1200000 -
hashsize 建议设为略大于
maxelem的 2 的幂(如 8192、16384、65536),能显著减少哈希冲突,提升命中率
批量导入不卡壳,只用 restore
别用 shell 循环逐行 ipset add——每行启动一次进程,10 万次调用可能耗几分钟,还易中断失败。
- 生成标准
restore文件(例如blacklist.ipset),内容格式如下:
add blackv4 192.168.1.0/24
add blackv4 203.0.113.42
add blackv4 198.51.100.128/25
- 执行:
ipset restore -f blacklist.ipset,百万条秒级完成 - 原始是纯 IP 文本?用这句一键转:
awk '{print "add blackv4 " $1}' blacklist.txt > blacklist.ipset - 导入前确保集合未被 iptables 引用,否则会失败;可先临时删规则:
iptables -D INPUT -m set --match-set blackv4 src -j DROP
iptables 规则必须写准、放对位置
集合建好了,但规则一错,整个黑名单就等于没生效。
- 必须加载 -m set 模块:漏掉就报
No chain/target/match by that name - 规则必须用 -I INPUT 插入链首,不能用
-A追加;若前面已有-j ACCEPT,后续DROP永远不会触发 - 完整命令示例:
iptables -I INPUT -m set --match-set blackv4 src -j DROP - IPv4 集合(
hash:ip/hash:net)不拦截 IPv6 流量;需另建blackv6 hash:ip6并加独立规则 - 检查日志中是否混有
::ffff:192.168.1.1这类 IPv4 映射地址,要先清洗再导入
动态更新零丢包,靠 swap 原子切换
直接 ipset flush 再重加,会在清空瞬间放行所有黑名单 IP,形成明显安全窗口。
- 正确做法是双集+swap:
后台构建新名单 → 存为blackv4_new.ipset→ipset restore -f blackv4_new.ipset
然后原子切换:ipset swap blackv4 blackv4_new(毫秒完成,无放行窗口) - 立刻清理旧集:
ipset destroy blackv4_new,否则残留空集仍占内核内存 - 两个集合类型、参数(
hashsize、maxelem)必须完全一致,否则swap报错Set cannot be swapped: different types











