窗口期 IP 限流

基于可疑事件窗口计数的分布式 IP 限流,只限制可疑行为,不影响正常请求频率。 IP 只作为同一来源的行为聚合键,不作为可信身份或白名单依据。

核心思路

可疑事件(规则命中 / 空 UA / 低版本浏览器 / 404 等)
    ↓ 调用 RecordEventAsync 计数
窗口内事件数 ≥ MaxEvents
    ↓
封禁 IP BlockMinutes 分钟,封禁期内所有请求延迟 BlockDelaySeconds 后返回 429
  • 正常请求不做任何计数,不限制频率
  • 事件记录存在 FusionCache(L1 内存 + L2 Redis),多服务器共享封禁状态
  • 事件更新使用分布式锁串行化,避免并发请求丢失窗口计数
  • 缓存键格式:RateLimit:Window:{IP},如 RateLimit:Window:192.168.1.100

配置

配置节 RateLimit所有字段可选,未配置时使用默认值

{
  "RateLimit": {
    "WindowMinutes": 5,
    "MaxEvents": 3,
    "BlockMinutes": 30,
    "BlockDelaySeconds": 2
  }
}
字段默认值说明
WindowMinutes5统计窗口(分钟),窗口过期后计数清零
MaxEvents3单个窗口内的事件数阈值,达到即封禁
BlockMinutes30封禁时长(分钟)
BlockDelaySeconds2封禁期内每个请求的延迟响应(秒),增加攻击成本

使用

// 注册服务(绑定 RateLimit 配置节)
services.AddIpRateLimit(configuration);

// 管线中添加中间件
// 注意:必须放在 UseAuthentication 之后,已登录用户才能正常放行
app.UseIpRateLimit();

事件来源

RecordEventAsync(ip, reason) 由以下组件调用:

组件事件
BotProtectionMiddleware拦截规则命中、空 UA、低版本浏览器
AuthStatusPageMiddleware(Auth)404 请求
RejectBotsMiddleware(Web)黑名单命中、404 请求

已登录用户、开发环境、IgnoreRequestPrefix 忽略前缀的请求不参与限流。

故障降级

限流服务访问缓存(Redis)失败时自动放行请求并记录警告日志, 避免限流组件故障导致全站不可用。

机器人拦截

规则判定由 Dpz.Core.Infrastructure.BotProtection 提供, 检测项按应用开关(见 BotProtectionOptions):

  • Web:拦截规则 + 空 UA + 低版本浏览器(需先 UseDetection
  • Auth:仅拦截规则(认证客户端复杂,不做 UA/浏览器判定)
评论加载中...