lua+redis动态封禁是防cc攻击最实用方式:请求进access_by_lua_block阶段即查redis黑名单,毫秒级响应并自动解封;支持ip频次统计、ua/路径特征识别及降级兜底,无需reload。

直接用 Lua 脚本在 Nginx 请求处理阶段做实时判断,配合 Redis 存储和过期 IP,是目前防 CC 攻击最实用、响应最快的方式。它不依赖重启或 reload,封禁毫秒级生效,还能自动解封,避免误伤。
核心逻辑:请求进来先查 Redis 黑名单
每次请求到达时,Lua 脚本读取客户端真实 IP(注意处理 X-Forwarded-For 多层代理),拼接成 key(如 block:192.168.5.23),向 Redis 发起 GET 查询。如果返回非空值,直接调用 ngx.exit(403) 拒绝访问。
这个过程发生在 access_by_lua_block 阶段,早于后端转发,开销极小;Redis 用内存操作,单次查询通常低于 0.2ms。
自动封禁:超频即拉黑,支持自定义阈值
除了查黑名单,脚本还能统计单位时间内的请求次数。常见做法是:
- 用 IP + 时间窗口(如 60 秒)作为 Redis key,比如 req:192.168.5.23:2026090415
- 每次请求执行 INCR,再用 EXPIRE 设置过期(避免手动清理)
- 若计数值超过设定上限(如 100 次/分钟),立即写入黑名单 key,并设 TTL(如 300 秒)
这样攻击者刚刷满阈值,下一秒就进黑名单,且 5 分钟后自动释放,无需人工干预。
增强识别:不止看频率,还可叠加 UA 和路径特征
单纯限频容易被低速轮询绕过。可在 Lua 中补充轻量判断:
- 检查 ngx.var.http_user_agent 是否为空、含 “python-requests”、“curl” 或无浏览器特征
- 对高频访问但路径固定(如 /api/user?id=1、/api/user?id=2…)的请求打标记
- 若同一 IP 在 10 秒内命中多个敏感路径(/login、/register、/admin),直接触发封禁
这些规则写在 Lua 里,修改后 reload 即可生效,比改 Nginx 配置快得多。
部署要点:别漏掉连接复用和错误兜底
生产环境必须注意两点:
- 使用 redis:set_keepalive() 复用连接,避免短连接风暴压垮 Redis
- Redis 不可用时,不能让所有请求失败——应加 fallback 逻辑,例如记录到共享字典(lua_shared_dict),降级为本地限频
- 封禁动作要加日志(ngx.log(ngx.WARN, "Blocked IP:", ip)),方便后续关联分析
整个流程不依赖外部服务重启,也不污染主配置,适合高并发、常受 CC 干扰的 API 接口层。











