# Fail2Ban filter: generic vulnerability/secrets-scanner burst detection, # adapted for Apache's vhost-first "fail2ban" LogFormat (see # apache-notes/apache-logformat.md). # # Install as: /etc/fail2ban/filter.d/apache-vhost-scan-burst.conf # # Origin: testing/allegra.log (atelierallegra.com, 2026-09-15) captured a # single IP (34.26.89.33) firing ~210 requests in ~2 seconds at one vhost, # rotating a fake "AI crawler" User-Agent on every request (GPTBot, # ClaudeBot, PerplexityBot, Googlebot, CCBot, DeepSeekBot, Baiduspider, # GrokBot, etc.) to make each hit look like a distinct legitimate crawler. # Paths probed were generic secrets/vuln targets (/.env, /actuator, # /debug/pprof, /proc/self/cgroup, /graphql/console, ...), not any one # specific exploit - roughly 200x404, 9x403, 9x400 in that one burst. This # is deliberately NOT a payload-signature filter (unlike apache-vhost- # wp-probe's path list) - it flags the volume/timing pattern instead, so it # also catches the next tool that scans for different paths with the same # rotate-the-UA trick. # # 401 is intentionally excluded from the 4xx count: it means "this URL # exists and needs auth", which is a different (credential-guessing) # pattern than the "throw everything, see what isn't a 404" scan this # filter targets. Add it back later if that turns out to be wrong. # # Expected log line (same vhost-first format as apache-vhost-wp-probe.conf): # # [15/Sep/2026:11:52:27 -0500] atelierallegra.com:443 34.26.89.33 - - "GET /.env?raw HTTP/1.1" 404 2050 "-" "Mozilla/5.0 ... GPTBot/1.3 ..." # |<------ stripped by datepattern ------>| |vhost:port| || # # NOTE: fail2ban removes the timestamp it matched from the line *before* # applying failregex - datepattern below anchors and consumes the whole # bracketed timestamp so failregex begins at the vhost field. [Definition] datepattern = ^\[%%d/%%b/%%Y:%%H:%%M:%%S %%z\] # 4(?!01)\d\d matches any 4xx status except 401 (400, 402-499). failregex = ^\s*\S+ \S+ \S+ "[A-Z]+ [^"]*" 4(?!01)\d\d \d+ ignoreregex =