You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SecRuleEngine中deprecatevar指令不生效的限流问题咨询

SecRuleEngine中deprecatevar指令不生效的限流问题咨询

问题描述

我尝试用SecRuleEngine实现限流:设置5次请求后返回429状态码,同时希望通过deprecatevar每10秒将计数减1,但现在遇到的问题是触发429后,后续请求立刻又返回200,限流逻辑无法持续生效。我的配置如下:

SecRuleEngine On
<Location "/">
SecAction "id:9001,phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},setvar:ip.requests=0"
SecAction "id:9002,phase:2,nolog,pass,setvar:ip.requests=+1"
SecRule IP:REQUESTS "@gt 5" "id:9003,phase:2,deny,status:429,setenv:RATELIMITED"
SecAction "id:9004,phase:4,nolog,pass,deprecatevar:ip.requests=1/10"
</Location>

这看起来是个很基础的例子,我肯定哪里漏了?


问题分析与解决方案

你遇到的核心问题是计数初始化逻辑错误:原来的phase:1动作会在每次请求进来时都强制把ip.requests设为0,这意味着之前累积的计数会被直接清空,每次请求的实际计数都是0+1=1。哪怕触发过一次429,下一次请求进来时计数又被重置为0,自然会立刻回到200状态。

我们需要修改初始化逻辑,只在ip.requests变量不存在的时候才将其设为0,这样才能保留累积的计数,让deprecatevar正常工作。修正后的配置如下:

SecRuleEngine On
<Location "/">
    # 初始化IP集合,仅当requests变量未设置时才初始化为0
    SecAction "id:9001,phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},chain"
    SecRule IP:REQUESTS "@!isset" "setvar:ip.requests=0"
    
    # 每次请求将计数+1
    SecAction "id:9002,phase:2,nolog,pass,setvar:ip.requests=+1"
    
    # 计数超过5则返回429拒绝请求
    SecRule IP:REQUESTS "@gt 5" "id:9003,phase:2,deny,status:429,setenv:RATELIMITED"
    
    # 每10秒将计数减1
    SecAction "id:9004,phase:4,nolog,pass,deprecatevar:ip.requests=1/10"
</Location>

额外注意点

  • deprecatevar:ip.requests=1/10的语法是正确的,表示每10秒将计数减少1,这个逻辑本身没问题,前提是计数能被正确保留。
  • 如果你的服务器是多进程模式(比如Apache的MPM prefork/worker),默认的内存存储会导致不同进程间的计数不共享,可能出现限流逻辑不一致的情况。这种情况下可以考虑使用共享存储来统一计数,但这是进阶场景,先解决初始化问题就能满足基础需求。

备注:内容来源于stack exchange,提问作者Rob Sedgwick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 08:39:44