iptables线性匹配万条规则致性能断崖下降;ipset用hash:ip集合实现o(1)查表,需显式设maxelem防溢出,批量导入优先用restore。

为什么不用 iptables -s 直接加万条规则
直接往 iptables 里塞上万条 -s 1.2.3.4 -j DROP 规则,会导致匹配性能断崖式下降——iptables 是线性遍历规则链的,万条规则意味着每次包进来都要平均比对 5000 次。实测在中等负载服务器上,吞吐量可能跌 30% 以上,且 iptables-save 导出文件超百 MB,加载/重载极慢,还容易触发内核 conntrack 表抖动。
用 ipset 创建 hash:ip 类型集合并绑定到 iptables
核心思路是把 IP 列表抽象成一个「集合」,让 iptables 只做一次哈希查表(O(1)),而不是逐条比对。关键在类型选对、参数设稳:
-
ipset create blacklist hash:ip maxelem 100000:必须显式指定maxelem,否则默认仅 65536,万级 IP 可能溢出报错ipset v7.6: Error in line 1: set is full -
ipset add blacklist 192.168.1.100批量添加时,优先用ipset restore而非循环add,避免 shell 启动开销;准备一个blacklist.ipset文件,内容形如:create blacklist hash:ip maxelem 100000<br>add blacklist 1.1.1.1<br>add blacklist 2.2.2.2<br>...
然后执行ipset restore - iptables 引用必须用
-m set --match-set blacklist src,不能漏掉-m set模块,否则报错iptables: No chain/target/match by that name
如何安全更新万级黑名单而不丢包或阻塞流量
直接 ipset flush blacklist 再重装,会在清空瞬间放行所有黑名单 IP;而用 ipset swap 可零停机切换:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 维护两个集合:
blacklist(线上生效)和blacklist_new(后台构建) - 新名单生成后,用
ipset swap blacklist blacklist_new原子切换,毫秒级完成,旧集合自动变成空的blacklist_new供下次复用 - 切完立刻执行
ipset destroy blacklist_new释放内存,否则残留空集合仍占内核资源 - 注意:swap 前确保
blacklist_new已存在且类型一致,否则报错ipset v7.6: Set cannot be swapped: different types
排查 ipset 匹配失效的三个硬检查点
常见现象是 IP 明明在集合里,却没被 drop——往往卡在以下环节:
- iptables 规则位置错误:
-m set --match-set blacklist src必须放在FORWARD或INPUT链靠前位置,若写在-j ACCEPT之后,就永远不执行 - IP 版本不匹配:IPv4 集合无法匹配 IPv6 地址,反之亦然;检查集合创建时是否误用了
hash:ip6却塞入 IPv4,或脚本读取 IP 时混入::ffff:192.168.1.1这类映射地址 - netfilter 模块未加载:
lsmod | grep ip_set应看到ip_set和ip_set_hash_ip;若缺失,手动modprobe ip_set_hash_ip,并写入/etc/modules防重启丢失
万级 IP 黑名单不是堆数量,而是控制哈希桶分布与更新节奏。最容易被忽略的是 maxelem 的预设值和 swap 后忘记 destroy,后者会让内核内存缓慢泄漏,数天后触发 OOM killer 杀进程。










