# Rules from ID: 77000001-77999999 are reserved for none permanent blocking rules
# Rules from ID: 78000001-78999999 are reserved for permanent blocking rules
# If used more than 1000 ids, then add it to modsec.ignore on salt!


# **Rate-limit specific bots by User-Agent (1 request per second per domain)**

# Rule 1: Increment counter for the bot (if User-Agent matches our list), with 1-second expiration.
SecRule REQUEST_HEADERS:User-Agent "@pmFromFile /HostingGroup/Modsec/ratelimit-bots.data" \
  "id:77000001,\
   phase:2,\
   nolog,\
   pass,\
   t:lowercase,\
   setuid:%{lowercase:request_headers.host}-%{tx.ua_hash},\
   setvar:user.rate_limit_counter=+1,\
   expirevar:user.rate_limit_counter=1"

# Rule 2: Check counter, and if above 1, send 429 Too Many Requests (rate exceeded).
SecRule USER:RATE_LIMIT_COUNTER "@gt 1" \
  "id:77000002,\
   phase:2,\
   deny,status:429,\
   log,msg:'Too Many Requests - rate limit exceeded for %{REQUEST_HEADERS.Host} (%{REQUEST_HEADERS.User-Agent})',\
   setenv:RATELIMITED,\
   chain"
   SecRule REQUEST_HEADERS:User-Agent "@pmFromFile /HostingGroup/Modsec/ratelimit-bots.data" "t:lowercase"

# When a request is blocked by the above rule, send a Retry-After header (1 second) to tell the bot when to retry.
Header always set Retry-After "1" env=RATELIMITED

# Define a friendly error response for 429 (optional – otherwise default 429 page is used)
ErrorDocument 429 "Too Many Requests - you are being rate-limited. Please slow down."



#SecRule REQUEST_URI "@contains evil" \
    "id:77000003,phase:1,deny,status:403,msg:'[HostingGroup] Blocked evil keyword in URI'"

SecRule REQUEST_URI "@rx (?i)evil" \
    "id:77000003,phase:2,deny,status:403,log,msg:'[HostingGroup] Blocked evil keyword in URI'"

SecRule REQUEST_HEADERS:User-Agent "@rx (?i)(nikto|sqlmap|acunetix|fuzz|nmap|python-requests|libwww-perl)" \
    "id:77000004,phase:1,deny,status:403,log,auditlog,msg:'[HostingGroup] Blocked bad User-Agent'"





