Modsecurity和Apache:如何按表头限制访问速率?

uujelgoq  于 2022-11-16  发布在  Apache
关注(0)|答案(2)|浏览(101)

我同时使用Apache和Modsecurity,我试图通过请求的头部(如“facebookexternalhit”)来限制命中率,然后返回友好的“429 Too Many Requests”和“Retry-After:3英寸。
我知道我可以读取一个文件的标题,如:
SecRule REQUEST_HEADERS:User-Agent "@pmFromFile ratelimit-bots.txt"
但我在建立规则时遇到了麻烦。
任何帮助都将不胜感激。谢谢。

w3nuxt5m

w3nuxt5m1#

经过两天的研究和了解Modsecurity是如何工作的,我终于做到了。FYI我使用的是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个请求。*

1.第一个规则将请求标头用户代理与“facebookexternalhit”进行匹配。如果匹配成功,它将在global集合中创建ratelimit_facebookexternalhit属性,初始值为1(它将随着每次匹配用户代理的命中而递增该值)。然后,它将这个变量的有效期设置为3秒。如果我们收到一个匹配“facebookexternalhit”的新点击,它将为ratelimit_facebookexternalhit加1。如果我们在3秒后没有收到匹配“facebookexternalhit”的点击,ratelimit_facebookexternalhit将消失,并且此进程将重新启动。
1.如果global.ratelimit_clients〉1(我们在3秒内收到2个或更多的点击)AND用户代理匹配“facebookexternalhit”(这个AND条件很重要,因为否则如果产生匹配,所有请求都将被拒绝),我们设置RATELIMITED=1,停止操作并显示429 http错误,并在Apache错误日志中记录一条自定义消息:“有限比例BOT”。
1.设置RATELIMITED=1只是为了添加自定义标题“Retry-After:3”。在这种情况下,该var由Facebook的爬虫(facebookexternalhit)解释,并将在指定的时间内重试操作。
1.我们为429错误Map一个自定义返回消息(如果需要)。
你可以通过添加@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)#pmmromfile)。我们使用用户代理初始化USER集合:setuid:%{tx.ua_hash}tx.ua_hash/usr/share/modsecurity-crs/modsecurity_crs_10_setup.conf中的全局范围内)。并且我们只是使用user作为集合而不是global。仅此而已!

643ylb08

643ylb082#

使用“deprecatevar”可能更好,并且可以允许稍大的突发延迟

# 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"

相关问题