Apache modsecurity 限制每单位时间每个 uri 的命中

Apache modsecurity restrict hits per uri per unit of time

我正在尝试为 Apache 配置 mod 安全性以限制每单位时间可以访问给定资源的命中次数(比方说,无论哪个 ip,每个资源每分钟 10 次命中地址执行请求)。资源具有“https://myhost/my-resource/my-resource-id

形式的 url 模式
# Limit the requests count by unit of time.
SecRuleEngine On

<LocationMatch "^.*/my-resource/.*">
  # SecAction initcol:ip=%{REMOTE_ADDR},pass,nolog,id:132
  SecAction initcol:uri=%{REQUEST_URI},pass,nolog,id:232
  SecAction "phase:5,deprecatevar:uri.counter=10/60,pass,nolog,id:332"
  SecRule URI:COUNTER "@ge 10" "phase:2,pause:10,deny,status:429,setenv:RATELIMITED,skip:1,nolog,id:432"
  SecAction "phase:2,pass,setvar:uri.counter=+1,nolog,id:532"
  Header always set Retry-After "60" env=RATELIMITED
</LocationMatch>

ErrorDocument 429 "Too Many Requests"

根据我对这段代码的理解,它告诉 mod安全 "create a variable named uri for each request_uri and associate a counter for each, then decrement it of 10 each 60 seconds. If the current's uri counter reach the value of 10, fail with an error code 429, else increment it" 这正是我需要的。

此配置导致 "uri variable not found" 错误,我不明白为什么。

如果我取消注释 1st SecAction 并更改剩余的配置以引用它,它会起作用(returns 10 次快速调用后 429),但显然没有考虑 uri(它失败了任何资源,例如 /my-resource/123 和 /my-resource/456)

有人可以帮忙吗?我所有的尝试都惨遭失败,而且我对 Apache 的一般配置不是很熟悉,所以我想我在这里遗漏了一些重要的概念。

PS:Apache 是 v2.4,mod-安全是 v2.9

谢谢!

有效的配置如下:

# Limit the requests count by unit of time.
SecRuleEngine On

<LocationMatch "^.*/my-resource/.*">
  SecAction initcol:resource=%{REQUEST_URI},pass,nolog,id:132
  SecRule RESOURCE:COUNTER "@ge 10" "phase:3,pause:10,deny,status:429,setenv:RATELIMITED,skip:1,nolog,id:232"
  SecAction "phase:2,setvar:resource.counter=+1,pass,nolog,id:332"
  SecAction "phase:2,deprecatevar:resource.counter=10/60,pass,nolog,id:432"
  Header always set Retry-After "60" env=RATELIMITED
</LocationMatch>

ErrorDocument 429 "Too Many Requests"

ndlr:将集合名称从 "uri" 更改为 "resource" 并稍微调整相位

然后它按预期工作(参见 modsecurity 邮件列表:https://sourceforge.net/p/mod-security/mailman/message/35889575/