如何用ModSecurity实现基于时间逻辑的User-Agent无条件自动解封?
问题分析与解决方案
核心问题原因
现有规则里的SecRule 13576461每次收到目标UA的请求时,都会执行setvar:resource.blocked=+1_%{REQUEST_HEADERS.Host}和expirevar:resource.blocked=3600_%{REQUEST_HEADERS.Host}——这意味着封禁期间每来一次请求,blocked变量的过期时间就会被重置为1小时后,自然无法实现“不管有没有请求,到期自动解封”的要求。
修正后的规则
# 初始化针对UA+Host的资源集合 SecAction "id:13576460, phase:1, nolog, pass, initcol:resource=%{REQUEST_HEADERS.User-Agent}_%{REQUEST_HEADERS.Host}" # 仅统计请求次数,不每次更新封禁标记 SecRule REQUEST_HEADERS:User-Agent "@contains facebookexternalhit" \ "id:13576461,\ phase:2,\ t:none,\ setvar:resource.counter=+1_%{REQUEST_HEADERS.Host},\ expirevar:resource.counter=300_%{REQUEST_HEADERS.Host},\ nolog" # 当请求次数超过10次时,仅在未封禁状态下设置封禁标记并固定过期时间 SecRule RESOURCE:counter "@gt 10" \ "id:13576463,\ phase:2,\ t:none,\ setvar:resource.blocked=1_%{REQUEST_HEADERS.Host},\ expirevar:resource.blocked=3600_%{REQUEST_HEADERS.Host},\ nolog,\ pass" # 判断是否处于封禁状态,是则返回429 SecRule RESOURCE:blocked "@eq 1" \ "id:13576462,\ phase:2,\ t:none,\ deny,\ status:429,\ log,\ msg:'Excessive requests from user agent'"
规则说明
- 请求统计逻辑:
SecRule 13576461只负责递增请求计数器counter,并设置5分钟的过期时间——5分钟内无请求则计数器自动清零,符合“5分钟内超10次触发封禁”的要求。 - 封禁触发逻辑:新增的
SecRule 13576463只在counter超过10次时,设置blocked变量为1,并固定3600秒的过期时间。这里不会每次请求都更新blocked的过期时间,所以哪怕封禁期间有请求,blocked的过期时间也不会被延长,到点自动失效。 - 封禁判断逻辑:
SecRule 13576462只检查blocked是否为1,是则返回429,逻辑简洁清晰。
这样就能实现:5分钟内超10次请求触发1小时封禁,无论期间是否有请求,1小时后自动解封,解封后重新进入请求统计循环。
内容的提问来源于stack exchange,提问作者Konstantinos K.
相关产品推荐
相关产品推荐

