帮助中心 >  技术知识库 >  云服务器 >  服务器教程 >  动态黑名单实现毫秒级封禁与零 Reload 抖动

动态黑名单实现毫秒级封禁与零 Reload 抖动

2026-08-04 17:08:12 183

动态黑名单实现毫秒级封禁与零 Reload 抖动

在公有云部署高流量 Web 服务时,遭遇 CC 攻击或凭证爆破需秒级封禁恶意源 IP。传统 Nginx 基于 deny 192.0.2.0/24; 的静态配置,每次封禁均需 nginx -s reload。云主机上频繁 reload 会触发 master 重新 fork worker,旧 worker 停留优雅退出期,短连接突增时引发 worker_connections 翻倍占用与 TCP TIME_WAIT 堆积,造成 P99 延迟毛刺与内存拷贝开销。

解决思路其一为内核层 ipset 动态拦截。相较于直接操纵 iptables 链式规则(超千条规则遍历导致软中断飙升),ipset 基于哈希表,查找复杂度为 O(1):

ipset create blacklist hash:ip timeout 3600

iptables -I INPUT -m set --match-set blacklist src -j DROP

当威胁情报平台或自研风控捕获恶意 IP,直接通过 ipset 添加,无需触动任何用户态进程:

ipset add blacklist 192.0.2.66 timeout 1800

K8s 集群节点上,利用 DaemonSet 运行 ipset 同步器,将外部 API 的恶意 IP 推送至宿主机 set。需注意云环境常启用 conntrack,若攻击已建立连接,需一并清除会话避免残留通道:

conntrack -D -s 192.0.2.66

若业务必须基于七层特征在 Nginx 层封禁,且前端云 LB 已透传 X-Forwarded-For,采用 OpenResty 动态字典实现完全零 Reload。在 nginx.conf 定义共享内存并在 http 块还原真实客户端 IP:

lua_shared_dict ip_blacklist 50m;

real_ip_header X-Forwarded-For;

real_ip_recursive on;

set_real_ip_from 10.0.0.0/8;

编写 Lua 脚本定时从 Redis 或威胁情报接口拉取最新恶意 IP 段,存入共享字典。处理请求阶段直接拦截:

local ip = ngx.var.remote_addr

local blacklist = ngx.shared.ip_blacklist

if blacklist:get(ip) then

    ngx.log(ngx.ERR, "blocked malicious ip: ", ip)

    return ngx.exit(444)

end

为避免 Lua 每次请求都查远端 Redis 造成 RT 升高,采用 ngx.timer.every 后台轮询更新,请求阶段仅内存哈希读取。实测在 16 核云主机上,百万级 IP 字典查找耗时低于 0.1ms,且配置变更对线上长连接零感知。

面对云上弹性伸缩组,新扩容实例若依靠启动脚本拉取全量黑名单,存在分钟级窗口期失防。进阶做法是利用 nftables 原生集合与云元数据结合。较新内核(5.x+)推荐使用 nftables 替代 iptables + ipset 组合,原生支持带超时的集合与字典类型,规避 iptables 规则链表化带来的线性匹配损耗:

nft add table inet filter

nft add set inet filter blacklist { type ipv4_addr \\; flags timeout \\; }

nft add rule inet filter input ip saddr @blacklist drop

动态封禁只需一条命令且支持自动过期:

nft add element inet filter blacklist { 192.0.2.66 timeout 1h }

对于需封禁整个 CIDR 段的场景,将 set 类型改为 type ipv4_addr . inet_service 可针对特定端口精细化限杀,例如仅封禁恶意 IP 对 3306 的暴破而放行其对 443 的回源,减少误杀正常爬虫。

 


提交成功!非常感谢您的反馈,我们会继续努力做到更好!

这条文档是否有帮助解决问题?

非常抱歉未能帮助到您。为了给您提供更好的服务,我们很需要您进一步的反馈信息:

在文档使用中是否遇到以下问题: