Guides
fail2ban for Apache
fail2ban ships nine Apache filters. Here is what each one catches, which log it reads on Debian/Ubuntu (apache2) and RHEL/Fedora (httpd), the Apache settings a few of them silently depend on, and a 404 filter for scanners.
To protect Apache with fail2ban, enable the stock Apache jails in /etc/fail2ban/jail.local — at minimum apache-auth, apache-badbots, apache-noscript and apache-overflows — with backend = auto, then run sudo fail2ban-client reload. fail2ban reads /var/log/apache2/*error.log on Debian and Ubuntu and /var/log/httpd/*error_log on Fedora and RHEL automatically. For 404 scanners, add the custom filter at the end of this page.
[apache-auth]
enabled = true
backend = auto
[apache-badbots]
enabled = true
backend = auto
[apache-noscript]
enabled = true
backend = auto
[apache-overflows]
enabled = true
backend = auto
[apache-shellshock]
enabled = true
backend = autosudo fail2ban-client reload
sudo fail2ban-client statusbackend = auto matters on Ubuntu 24.04, whose package sets backend = systemd for every jail; with that backend fail2ban ignores logpath and Apache's log files are never read.
Apache log paths: apache2 vs httpd#
The jails don't hard-code paths. They use variables from the distribution's paths-*.conf:
| Variable | Debian / Ubuntu (apache2) |
Fedora / RHEL / Rocky / Alma (httpd) |
|---|---|---|
apache_error_log |
/var/log/apache2/*error.log |
/var/log/httpd/*error_log |
apache_access_log |
/var/log/apache2/*access.log |
/var/log/httpd/*access_log |
The globs pick up per-site logs such as example.com-error.log — but only files that exist when the jail starts. If a vhost logs somewhere else, add it:
[apache-auth]
enabled = true
backend = auto
logpath = %(apache_error_log)s
/srv/www/example.com/logs/error.logCheck what a running jail actually reads with sudo fail2ban-client get apache-auth logpath.
Every stock Apache jail#
| Jail | Log | jail.conf defaults | Catches |
|---|---|---|---|
apache-auth |
error | maxretry 5 | Basic/Digest auth failures, unknown users, "denied by server configuration" |
apache-badbots |
access | maxretry = 1, bantime = 48h |
User agents of known spam/e-mail harvesting bots |
apache-noscript |
error | maxretry 5 | Requests for scripts that don't exist (.php, .asp, .exe, .pl, cgi-bin), incl. PHP-FPM "Primary script unknown" |
apache-overflows |
error | maxretry = 2 |
Overlong URIs, invalid methods and URIs, bad characters |
apache-nohome |
error | maxretry = 2 |
Probes for ~user home directories |
apache-botsearch |
error | maxretry = 2 |
Probes for phpMyAdmin, webmail, wp-login.php, cgi-bin that don't exist |
apache-fakegooglebot |
access | maxretry = 1 |
Clients claiming to be Googlebot whose IP doesn't resolve to Google |
apache-modsecurity |
error | maxretry = 2 |
Requests ModSecurity denied with a 4xx/5xx code |
apache-shellshock |
error | maxretry = 1 |
Shellshock (CVE-2014-6271) header attacks against CGI |
All of them use port = http,https.
apache-auth#
Catches Apache 2.4 authentication errors such as:
[Sun Oct 25 18:36:10.123456 2026] [auth_basic:error] [pid 2345] [client 203.0.113.42:51234] AH01618: user admin not found: /private/
[Sun Oct 25 18:36:12.654321 2026] [auth_basic:error] [pid 2345] [client 203.0.113.42:51234] AH01617: user admin: authentication failure for "/private/": Password Mismatchmode = aggressive also counts mod_evasive's "denied by server configuration" messages, which the normal mode skips.
apache-noscript and apache-overflows#
Bots constantly request /wp-login.php, /xmlrpc.php or /shell.php on sites that have none of them. With PHP-FPM, Apache logs these as:
[Sun Oct 25 18:36:10.123456 2026] [proxy_fcgi:error] [pid 2345] [client 203.0.113.42:51234] AH01071: Got error 'Primary script unknown'apache-noscript counts these. Don't enable it on a PHP site where users can post links to missing scripts (forums, wikis): their visitors would be banned. apache-overflows is safe almost everywhere — normal browsers never send Invalid URI or overlong requests.
apache-botsearch and apache-nohome need LogLevel info#
Both filters match AH00128: File does not exist, which Apache 2.4 logs at info level. With the default LogLevel warn these lines never appear and the jails stay at zero. Raise the level for the core module only:
LogLevel warn core:infoapache-botsearch also assumes your document root is directly under /var/www/ (webroot = /var/www/). On Debian, Ubuntu and RHEL the default root is /var/www/html/, so pass the real one:
[apache-botsearch]
enabled = true
backend = auto
filter = apache-botsearch[webroot="/var/www/html/"]We confirmed with fail2ban-regex that a File does not exist: /var/www/html/phpmyadmin line is missed with the default webroot and matched with this one.
apache-fakegooglebot#
This jail matches every access-log line whose user agent contains Googlebot, then runs an ignorecommand script that does a reverse and forward DNS check. Real Googlebot addresses are ignored; impostors get banned on the first request. It costs one DNS lookup per Googlebot request, so enable it only if fake crawlers are a real problem for you.
apache-modsecurity and apache-shellshock#
apache-modsecurity turns ModSecurity's per-request denials into firewall bans: after two blocked requests the client can't reach the server at all. It only makes sense if mod_security2 is installed with a rule set such as the OWASP CRS. apache-shellshock bans clients sending Shellshock payloads to CGI scripts; on a patched server it mostly cleans up noise.
Ban Apache 404 floods with a custom filter#
There's no stock 404 filter. This one reads the combined access-log format (and Debian's vhost_combined used for other_vhosts_access.log), with the status codes chosen per jail:
[Definition]
failregex = ^(?:\S+:\d+ )?<HOST> \S+ \S+ \[\] "[A-Z]+ [^"]*" (?:<codes>)\s
ignoreregex = "(?:GET|HEAD) /(?:favicon\.ico|robots\.txt|apple-touch-icon\S*\.png)\s
datepattern = ^[^\[]*\[({DATE})
{^LN-BEG}
[Init]
codes = 404[apache-404]
enabled = true
backend = auto
filter = apache-4xx
logpath = %(apache_access_log)s
port = http,https
findtime = 10m
maxretry = 20
bantime = 1h
[apache-403]
enabled = true
backend = auto
filter = apache-4xx[codes="401|403"]
logpath = %(apache_access_log)s
port = http,https
maxretry = 10Matching lines look like:
203.0.113.42 - - [25/Oct/2026:18:36:10 +0000] "GET /.env HTTP/1.1" 404 196 "-" "curl/8.5.0"
example.com:443 203.0.113.42 - - [25/Oct/2026:18:36:10 +0000] "GET /.git/config HTTP/1.1" 404 196 "-" "curl/8.5.0"A high maxretry matters: one missing image on a popular page produces 404s for every visitor. For login brute force on WordPress specifically, see the WordPress guide; for writing filters for other formats, see writing a custom filter.
Apache behind a proxy or CDN#
Behind a load balancer, reverse proxy or Cloudflare, Apache logs the proxy's address and fail2ban would ban the proxy. Use mod_remoteip so Apache logs the client:
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.0.0.5sudo a2enmod remoteip && sudo a2enconf remoteip && sudo systemctl reload apache2Error-log lines then show the client in [client …]. For the access log, use %a instead of %h in your LogFormat lines. For public proxy ranges (Cloudflare) the directive is RemoteIPTrustedProxy; the Cloudflare guide has the full setup.
Test the Apache jails#
# Debian/Ubuntu
sudo fail2ban-regex /var/log/apache2/error.log apache-auth
sudo fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/apache-4xx.conf
# RHEL/Fedora
sudo fail2ban-regex /var/log/httpd/error_log apache-noscriptThen check the running jail and its files:
sudo fail2ban-client status apache-auth
sudo fail2ban-client get apache-404 logpathTo provoke apache-auth, request a password-protected path with a bad password from a second machine (curl -u admin:wrong https://example.com/private/) five times and look for Ban in /var/log/fail2ban.log. The same ideas for nginx are in the nginx guide.
Built-in filter reference: apache-auth, apache-badbots, apache-botsearch and more#
The built-in filters this guide uses, exactly as fail2ban 1.1.1 ships them — with the log lines they match and a link to test them. Looking for something else? See HAProxy, lighttpd, Squid and the other web server, proxy and web-app filters, or the full filter library.
apache-auth Apache HTTP Server
The apache-auth filter catches failed HTTP Basic/Digest authentication and denied access in the Apache error log. File: /etc/fail2ban/filter.d/apache-auth.conf; jail [apache-auth]; log on Debian/Ubuntu: /var/log/apache2/*error.log.
Log lines it bans (from fail2ban's test suite):
[Thu Jul 11 01:21:41 2013] [error] [client 194.228.20.113] user not found: /[Thu Jul 11 01:21:43 2013] [error] [client 194.228.20.113] user dsfasdf not found: /[Thu Jul 11 01:21:44 2013] [error] [client 2001:db8::80da:af6b:8b2c] user test-ipv6 not found: /
Show the failregex fail2ban compiles (11 lines)
^\[\]\s\[(:?error|(?!evasive)\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\] (?:AH\d+: )?<F-CONTENT>.+</F-CONTENT>$^client (?:denied by server configuration|used wrong authentication scheme)\b
^user (?!`)<F-USER>(?:\S*|.*?)</F-USER> (?:auth(?:oriz|entic)ation failure|not found|denied by provider)\b
^Authorization of user <F-USER>(?:\S*|.*?)</F-USER> to access .*? failed\b
^([A-Z]\w+: )?user <F-USER>(?:\S*|.*?)</F-USER>: password mismatch\b
^([A-Z]\w+: )?user `<F-USER>(?:[^']*|.*?)</F-USER>' in realm `.+' (auth(?:oriz|entic)ation failure|not found|denied by provider)\b
^([A-Z]\w+: )?invalid nonce .* received - length is not\b
^([A-Z]\w+: )?realm mismatch - got `(?:[^']*|.*?)' but expected\b
^([A-Z]\w+: )?unknown algorithm `(?:[^']*|.*?)' received\b
^invalid qop `(?:[^']*|.*?)' received\b
^([A-Z]\w+: )?invalid nonce .*? received - user attempted time travel\b
^(?:No h|H)ostname \S+ provided via SNI(?:, but no hostname provided| and hostname \S+ provided| for a name based virtual host)\bTest apache-auth in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*error.log apache-auth · source
apache-badbots Apache HTTP Server
The apache-badbots filter bans known spam bots and e-mail harvesters by their User-Agent in the access log. File: /etc/fail2ban/filter.d/apache-badbots.conf; jail [apache-badbots]; log on Debian/Ubuntu: /var/log/apache2/*access.log.
Log lines it bans (from fail2ban's test suite):
1.2.3.4 - - [05/Mar/2007:14:39:21 +0100] "POST /123.html/trackback/ HTTP/1.0" 301 459 "http://www.mydomain.tld/123.html/trackback" "TrackBack/1.02"1.2.3.4 - - [05/Mar/2007:14:40:21 +0100] "GET /123.html/trackback/ HTTP/1.0" 301 459 "http://www.mydomain.tld/123.html/trackback" "TrackBack/1.02"1.2.3.4 - - [05/Mar/2007:14:41:21 +0100] "HEAD /123.html/trackback/ HTTP/1.0" 301 459 "http://www.mydomain.tld/123.html/trackback" "TrackBack/1.02"
Show the failregex fail2ban compiles (1 line)
^\s*(?:[\w]+[\w\-\.]*\s+)?<ADDR> [^"]*"[A-Z]{3,10} [^"]+" \d+ \d+ "[^"]+" "[^"]*(?:Atomic_Email_Hunter/4\.0|atSpider/1\.0|autoemailspider|bwh3_user_agent|China Local Browse 2\.6|ContactBot/0\.2|ContentSmartz|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailSpider|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Guestbook Auto Submitter|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 \+http\://letscrawl\.com/|Lincoln State Web Browser|LMQueueBot/0\.2|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|MVAClient|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/3\.0 \(compatible; scan4mail \(advanced version\) http\://www\.peterspages\.net/?scan4mail\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|NameOfAgent \(CMS Spider\)|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|ShablastBot 1\.0|snap\.com beta crawler v0|Snapbot/1\.0|Snapbot/1\.0 \(Snap Shots, \+http\://www\.snap\.com\)|sogou develop spider|Sogou Orion spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sogou spider|Sogou web spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|VadixBot|WebVulnCrawl\.unknown/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00|EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider|(?:Mozilla/\d+\.\d+ )?Jorgee)"$Test apache-badbots in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*access.log apache-badbots · source
apache-botsearch Apache HTTP Server
The apache-botsearch filter bans scanners probing for admin pages and scripts that don't exist (phpMyAdmin, wp-login and similar). File: /etc/fail2ban/filter.d/apache-botsearch.conf; jail [apache-botsearch]; log on Debian/Ubuntu: /var/log/apache2/*error.log.
Log lines it bans (from fail2ban's test suite):
[Tue Jul 22 06:48:30 2008] [error] [client 198.51.100.86] script not found or unable to stat: /var/www/wp-login.php[Mon Dec 23 09:49:10 2013] [error] [client 115.249.248.145] File does not exist: /var/www/pma[Mon Dec 23 09:49:10 2013] [error] [client 115.249.248.145] File does not exist: /var/www/phpmyadmin
Show the failregex fail2ban compiles (2 lines)
^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\] (?:AH\d+: )?<F-CONTENT>.+</F-CONTENT>$^(?:File does not exist|script not found or unable to stat): /var/www/\/?(roundcube|(ext)?mail|horde|(v-?)?webmail|(typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin)|wp-(login|signup|admin)\.php|cgi-bin|mysqladmin)[^,]*(, referer: \S+)?\s*$
^script '/var/www/\/?(roundcube|(ext)?mail|horde|(v-?)?webmail|(typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin)|wp-(login|signup|admin)\.php|cgi-bin|mysqladmin)[^,]*' not found or unable to stat(, referer: \S+)?\s*$Test apache-botsearch in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*error.log apache-botsearch · source
apache-fakegooglebot Apache HTTP Server
The apache-fakegooglebot filter bans clients that claim to be Googlebot but fail a reverse-DNS check. File: /etc/fail2ban/filter.d/apache-fakegooglebot.conf; jail [apache-fakegooglebot]; log on Debian/Ubuntu: /var/log/apache2/*access.log.
Log lines it bans (from fail2ban's test suite):
66.249.66.1 - - - [31/Jan/2015:14:29:44 ] fail2ban.org "GET / HTTP/1.1" 200 814 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" + 293 1149 546www.sitename.com 192.0.2.222 - - [18/Aug/2024:21:08:39 +0100] "GET / HTTP/1.1" 403 332 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
Show the failregex fail2ban compiles (1 line)
^\s*(?:[\w]+[\w\-\.]*\s+)?<ADDR> [^"]*"[A-Z]{3,10} /\S* [^"]*" \d+ \d+ "[^"]*" "[^"]*\bGooglebot/[^"]*"Test apache-fakegooglebot in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*access.log apache-fakegooglebot · source
apache-modsecurity Apache + ModSecurity
The apache-modsecurity filter bans clients whose requests were blocked by ModSecurity rules. File: /etc/fail2ban/filter.d/apache-modsecurity.conf; jail [apache-modsecurity]; log on Debian/Ubuntu: /var/log/apache2/*error.log.
Log lines it bans (from fail2ban's test suite):
[Mon Dec 23 13:12:31 2013] [error] [client 173.255.225.101] ModSecurity: [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_21_protocol_anomalies.conf"] [line "47"] [id "960015"] [rev "1"] [msg "Request Missing an Accept Header"] [severity "NOTICE"] [ver "OWASP_CRS/2.2.8"] [maturity "9[Sat Dec 28 09:18:05 2013] [error] [client 32.65.254.69] ModSecurity: [file "/etc/httpd/modsecurity.d/10_asl_rules.conf"] [line "635"] [id "340069"] [rev "4"] [msg "Atomicorp.com UNSUPPORTED DELAYED Rules: Web vulnerability scanner"] [severity "CRITICAL"] Access denied with code 403 (phase 2). Patte[Sat Sep 28 09:18:06 2018] [error] [client 192.0.2.1:55555] [client 192.0.2.1] ModSecurity: [file "/etc/httpd/modsecurity.d/10_asl_rules.conf"] [line "635"] [id "340069"] [rev "4"] [msg "Atomicorp.com UNSUPPORTED DELAYED Rules: Web vulnerability scanner"] [severity "CRITICAL"] Access denied with cod
Show the failregex fail2ban compiles (1 line)
^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\](?: \[client [^\]]+\])? ModSecurity:\s+(?:\[(?:\w+ \"[^\"]*\"|[^\]]*)\]\s*)*Access denied with code [45]\d\dTest apache-modsecurity in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*error.log apache-modsecurity · source
apache-nohome Apache HTTP Server
The apache-nohome filter bans requests for user home directories (~user) that don't exist. File: /etc/fail2ban/filter.d/apache-nohome.conf; jail [apache-nohome]; log on Debian/Ubuntu: /var/log/apache2/*error.log.
Log lines it bans (from fail2ban's test suite):
[Sat Jun 01 11:23:08 2013] [error] [client 1.2.3.4] File does not exist: /xxx/~[Thu Jun 27 11:55:44.569531 2013] [core:info] [pid 4101:tid 2992634688] [client 192.0.2.12:46652] AH00128: File does not exist: /xxx/~
Show the failregex fail2ban compiles (1 line)
^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\] (AH00128: )?File does not exist: .*/~.*Test apache-nohome in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*error.log apache-nohome · source
apache-noscript Apache HTTP Server
The apache-noscript filter bans clients requesting scripts (php, asp, cgi, perl) that don't exist on the server. File: /etc/fail2ban/filter.d/apache-noscript.conf; jail [apache-noscript]; log on Debian/Ubuntu: /var/log/apache2/*error.log.
Log lines it bans (from fail2ban's test suite):
[Sun Jun 09 07:57:47 2013] [error] [client 192.0.43.10] script '/usr/lib/cgi-bin/gitweb.cgiwp-login.php' not found or unable to stat[Tue Jul 22 06:48:30 2008] [error] [client 198.51.100.86] File does not exist: /home/southern/public_html/azenv.php[Tue Jul 22 06:48:30 2008] [error] [client 198.51.100.86] script not found or unable to stat: /home/e-smith/files/ibays/Primary/cgi-bin/php
Show the failregex fail2ban compiles (2 lines)
^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\] (?:AH0(?:01(?:28|30)|1(?:264|071)|2811): )?(?=(?:[Ff]ile|[Ss]cript|[Gg]ot error|stderr from) )<F-CONTENT>.+</F-CONTENT>$^(?:(?:[Ff]ile does not exist|[Ss]cript not found or unable to stat): /\S*(?:php(?:[45]|[.-]cgi)?|\.asp|\.exe|\.pl|\bcgi-bin/)\b|[Gg]ot error '[Pp]rimary script unknown\b)
^(?:stderr from |script (?P<_q>'))/\S*(?:php(?:[45]|[.-]cgi)?|\.asp|\.exe|\.pl|\bcgi-bin/)\S*(?(_q)'|) (?:script )?(?:does not exist|not found or unable to stat)Test apache-noscript in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*error.log apache-noscript · source
apache-overflows Apache HTTP Server
The apache-overflows filter bans clients sending overlong or malformed request URIs. File: /etc/fail2ban/filter.d/apache-overflows.conf; jail [apache-overflows]; log on Debian/Ubuntu: /var/log/apache2/*error.log.
Log lines it bans (from fail2ban's test suite):
[Tue Mar 16 15:39:29 2010] [error] [client 58.179.109.179] Invalid URI in request \xf9h\xa9\xf3\x88\x8cXKj \xbf-l*4\x87n\xe4\xfe\xd4\x1d\x06\x8c\xf8m\\rS\xf6n\xeb\x8[Mon Mar 15 15:44:47 2010] [error] [client 121.222.2.133] Invalid URI in request n\xed*\xbe*\xab\xefd\x80\xb5\xae\xf6\x01\x10M?\xf2\xce\x13\x9c\xd7\xa0N\xa7\xdb%0\xde\xe0\xfc\xd2\xa0\xfe\xe9w\xee\xc4`v\x9b[{\x0c:\xcb\x93\xc6\xa0\x93\x9c`l\\\x8d\xc9[Sat Mar 15 16:04:06.105212 2010] [core:error] [pid 17408] [client 192.0.2.1:55280] AH00126: Invalid URI in request GET /static/../../../a/../../../../etc/passwd HTTP/1.1
Show the failregex fail2ban compiles (1 line)
^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\] (?:(?:AH(?:001[23][456]|10244): )?[Ii]nvalid (method|URI)\b|(?:AH00565: )?request failed: URI too long \(longer than \d+\)|request failed: erroneous characters after protocol string:|(?:AH00566: )?request failed: invalid characters in URI\b)Test apache-overflows in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*error.log apache-overflows · source
apache-shellshock Apache HTTP Server
The apache-shellshock filter bans requests that try to exploit the Bash Shellshock bug through CGI headers. File: /etc/fail2ban/filter.d/apache-shellshock.conf; jail [apache-shellshock]; log on Debian/Ubuntu: /var/log/apache2/*error.log.
Log lines it bans (from fail2ban's test suite):
[Thu Sep 25 09:27:18.813902 2014] [cgi:error] [pid 16860] [client 89.207.132.76:59635] AH01215: /bin/bash: warning: HTTP_TEST: ignoring function definition attempt[Thu Sep 25 09:29:56.141832 2014] [cgi:error] [pid 16864] [client 162.247.73.206:41273] AH01215: /bin/bash: error importing function definition for `HTTP_TEST'
Show the failregex fail2ban compiles (2 lines)
^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\] (AH01215: )?/bin/([bd]a)?sh: <F-CONTENT>.+</F-CONTENT>$^warning: HTTP_[^:]+: ignoring function definition attempt(, referer: \S+)?\s*$
^error importing function definition for `HTTP_[^']+'(, referer: \S+)?\s*$Test apache-shellshock in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*error.log apache-shellshock · source
apache-pass Apache HTTP Server
The apache-pass filter port-knocking helper: records clients that request a secret URL so another jail can allow them. File: /etc/fail2ban/filter.d/apache-pass.conf; jail [pass2allow-ftp]; log on Debian/Ubuntu: /var/log/apache2/*access.log.
Log lines it bans (from fail2ban's test suite):
192.0.2.12 - user1 [27/Jun/2013:11:55:44] "GET /knocking/ HTTP/1.1" 200 266 "http://domain.net/hello-world/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:40.0) Gecko/20100101 Firefox/40.0"
Show the failregex fail2ban compiles (1 line)
^<HOST> - \w+ \[\] "GET /knocking/ HTTP/1\.[01]" 200 \d+ ".*" "[^-].*"$Test apache-pass in the browser or on the server: sudo fail2ban-regex /var/log/apache2/*access.log apache-pass · source
FAQ#
Which Apache filters does fail2ban include?#
fail2ban 1.1.1 ships apache-auth, apache-badbots, apache-botsearch, apache-fakegooglebot, apache-modsecurity, apache-nohome, apache-noscript, apache-overflows and apache-shellshock, each with a disabled jail of the same name in jail.conf. There's also apache-pass, used by the pass2allow-ftp port-knocking example jail.
How do I ban Apache 404 errors with fail2ban?#
Create a filter matching status 404 in the access log, such as failregex = ^<HOST> \S+ \S+ \[\] "[A-Z]+ [^"]*" 404\s, and a jail with logpath = %(apache_access_log)s, maxretry = 20 and findtime = 10m. Ignore favicon.ico and robots.txt so ordinary browsers aren't counted.
Why is apache-botsearch not banning anything?#
Apache 2.4 logs File does not exist at info level, so with LogLevel warn the lines never reach the error log. Set LogLevel warn core:info. Also pass your real document root, e.g. filter = apache-botsearch[webroot="/var/www/html/"], because the filter defaults to /var/www/.
Does fail2ban work with httpd on RHEL and Rocky Linux?#
Yes. The Fedora/EPEL package uses paths-fedora.conf, which points the Apache jails at /var/log/httpd/*error_log and *access_log. Enable the jails in jail.local as on Debian; with fail2ban-firewalld installed, bans are applied through firewalld.
Where are the Apache logs fail2ban reads?#
On Debian and Ubuntu: /var/log/apache2/*error.log and /var/log/apache2/*access.log. On Fedora, RHEL, Rocky and AlmaLinux: /var/log/httpd/*error_log and /var/log/httpd/*access_log. Vhosts logging elsewhere need extra logpath lines in the jail.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.