我让Apache和Modsecurity一起工作。我试图通过请求的标题来限制命中率(比如"facebookexternalhit"(。然后返回友好的"429请求太多"one_answers"重试时间:3"。
我知道我可以阅读一个标题文件,比如:
SecRule REQUEST_HEADERS:User-Agent "@pmFromFile ratelimit-bots.txt"
但我在制定规则时遇到了麻烦。
如有任何帮助,我们将不胜感激。非常感谢。
经过两天的研究和了解Modsecurity的工作原理,我终于做到了。仅供参考,我正在使用Apache 2.4.37和Modsecurity 2.9.2这就是我所做的:
在我的自定义文件规则:/etc/modsecurity/modsecurity_custom.conf
中,我添加了以下规则:
# Limit client hits by user agent
SecRule REQUEST_HEADERS:User-Agent "@pm facebookexternalhit"
"id:400009,phase:2,nolog,pass,setvar:global.ratelimit_facebookexternalhit=+1,expirevar:global.ratelimit_facebookexternalhit=3"
SecRule GLOBAL:RATELIMIT_FACEBOOKEXTERNALHIT "@gt 1"
"chain,id:4000010,phase:2,pause:300,deny,status:429,setenv:RATELIMITED,log,msg:'RATELIMITED BOT'"
SecRule REQUEST_HEADERS:User-Agent "@pm facebookexternalhit"
Header always set Retry-After "3" env=RATELIMITED
ErrorDocument 429 "Too Many Requests"
说明:
注意:我希望限制为每3秒1个请求
- 第一条规则将请求头用户代理与"facebookexternalhit"匹配。如果匹配成功,它将在全局集合中创建ratelimit_facebookexternalhit属性,初始值为1(它将随着与用户代理匹配的每次命中而增加该值(。然后,它将此var的过期时间设置为3秒。如果我们收到一个匹配"facebookexternalhit"的新点击,它将加1到ratelimit_facebookexternal hit。如果我们在3秒钟后没有收到与"facebookexternalhit"匹配的点击,ratelimit_facebookexternal hit将消失,此过程将重新启动
- 如果global.ratelimit_clients>1(我们在3秒内收到2个或更多点击(AND用户代理匹配"facebookexternalhit"(这个AND条件很重要,因为否则如果产生匹配,所有请求都将被拒绝(,我们将RATELIMITED设置为1,停止带有429http错误的操作,并在Apache错误日志中记录一条自定义消息:"RATELIMITEDBOT">
- RATELIMITED=1仅用于添加自定义标头"Retry After:3"。在这种情况下,这个var由Facebook的爬网程序(facebookexternalhit(解释,并将在指定的时间内重试操作
- 我们为429错误映射了一个自定义返回消息(如果需要的话(
您可以通过添加@pmf和.data文件来改进此规则,然后初始化全局集合(如initcol:global=%{MATCHED_VAR}
(,这样您就不局限于按规则进行的单个匹配。我没有测试最后一步(这是我现在需要的(。我会更新我的答案,以备不时之需。
更新:
我已经调整了规则,使其能够拥有一个包含我想要评分限制的所有用户代理的文件,因此一个规则可以在多个机器人/爬网程序中使用:
# Limit client hits by user agent
SecRule REQUEST_HEADERS:User-Agent "@pmf data/ratelimit-clients.data"
"id:100008,phase:2,nolog,pass,setuid:%{tx.ua_hash},setvar:user.ratelimit_client=+1,expirevar:user.ratelimit_client=3"
SecRule USER:RATELIMIT_CLIENT "@gt 1"
"chain,id:1000009,phase:2,deny,status:429,setenv:RATELIMITED,log,msg:'RATELIMITED BOT'"
SecRule REQUEST_HEADERS:User-Agent "@pmf data/ratelimit-clients.data"
Header always set Retry-After "3" env=RATELIMITED
ErrorDocument 429 "Too Many Requests"
因此,具有用户代理的文件(每行一个(位于该规则的同一目录下的一个子目录中:/etc/modsecurity/data/ratelimit-clients.data
。然后我们使用@pmf来读取和解析文件(https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x(#pmfromfile(。我们使用用户代理setuid:%{tx.ua_hash}
初始化USER集合(tx.ua_hash在/usr/share/modsecurity-crs/modsecurity_crs_10_setup.conf
的全局范围内(。我们只是使用用户作为集合,而不是全局。仅此而已!
使用"depletevar";,你可以允许更大的突发亮度
# Limit client hits by user agent
SecRule REQUEST_HEADERS:User-Agent "@pmf data/ratelimit-clients.data"
"id:100008,phase:2,nolog,pass,setuid:%{tx.ua_hash},setvar:user.ratelimit_client=+1,deprecatevar:user.ratelimit_client=3/1"
SecRule USER:RATELIMIT_CLIENT "@gt 1"
"chain,id:100009,phase:2,deny,status:429,setenv:RATELIMITED,log,msg:'RATELIMITED BOT'"
SecRule REQUEST_HEADERS:User-Agent "@pmf data/ratelimit-clients.data"
Header always set Retry-After "6" env=RATELIMITED
ErrorDocument 429 "Too Many Requests"