Table of Contents
fail2ban examples
Port 80 ban
Create new jail file in /etc/fail2ban/jail.d/test.local
[bottest] enabled = true maxretry = 4 findtime = 60s bantime = 60s action = iptables[name=bloKKKED, port=http] logpath = %(nginx_access_log)s
This will create a bottest
jail and will use a filter defined in /etc/fail2ban/filter.d/bottest.local. Example of regex matching default nginx log:
[Definition] failregex = ^<HOST> \- \S+ \[\] \"(GET|POST|HEAD) .+$ ignoreregex = datepattern = ^[^\[]*\[({DATE})
<HOST> is mandatory and has to match the IP address. Adapt regex to your logging format and lines you need to match.
action is defined already in /etc/fail2ban/action.d/iptables.conf, and logpath is defined in /etc/fail2ban/paths-common.conf
Restart fail2ban:
systemctl restart fail2ban.service
This will now ban http request for 60 seconds from any client if it tries to access the site on port 80 more than 4 times within 60s. It will create a new iptables chain named f2b-bloKKKED. Truncated iptables -nvL
output:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 73 66036 f2b-bloKKKED tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 ... Chain f2b-bloKKKED (1 references) pkts bytes target prot opt in out source destination 4 5864 REJECT all -- * * 10.21.21.1 0.0.0.0/0 reject-with icmp-port-unreachable 35 17374 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
If you are using shorewall the above chain will be deleted on shorewall restart. Consider using the shorewall action instead of iptables then.
Testing
regex
Use fail2ban-regex
to check if its matching the regex. Here is an example of match
$ fail2ban-regex /var/log/nginx/access.log bottest.local Running tests ============= Use failregex filter file : bottest, basedir: /etc/fail2ban Use datepattern : {^LN-BEG} : Default Detectors Use log file : /var/log/nginx/access.log Use encoding : UTF-8 Results ======= Failregex: 42 total |- #) [# of hits] regular expression | 1) [42] ^<HOST> \- \S+ \[\] \"(GET|POST|HEAD) .+$ `- Ignoreregex: 0 total Date template hits: |- [# of hits] date format | [42] {^LN-BEG}Day(?P<_sep>[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)? `- Lines: 42 lines, 0 ignored, 42 matched, 0 missed [processed in 0.00 sec]
nginx access.log
10.21.21.1 - - [27/Dec/2022:11:57:15 +0100] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" 10.21.21.1 - - [27/Dec/2022:11:57:15 +0100] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0"
dry run
Use action dummy.conf
from action.d/ directory to see what would be banned. E.g.
[bottest] enabled = true maxretry = 4 findtime = 60s bantime = 60s action = dummy #action = iptables[name=bloKKKED, port=http] logpath = %(nginx_access_log)s
Then cat /var/run/fail2ban/fail2ban.dummy
to see what IPs would be banned.
Troubleshooting
You can check the logfile of fail2ban in /var/log/fail2ban.log. To get a detailed log ouput restart the fail2ban with this command
fail2ban-client --loglevel DEBUG start
then check the log file again.
Timezone issue
If you have a warning similar to
2022-12-27 11:11:57,573 fail2ban.filter [17192]: WARNING [bottest] Simulate NOW in operation since found time has too large deviation None ~ 1672135917.573329 +/- 60 2022-12-27 11:11:57,573 fail2ban.filter [17192]: WARNING [bottest] Please check jail has possibly a timezone issue. Line with odd timestamp: 10.21.21.1 - - [27/Dec/2022:11:11:57 +0100] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0"
check your filter's dateformat line it could be incorrectly matching the log lines.
Not banning after action change
If you changed the action to be used in jail, for example from iptables to shorewall it might not work even after restart, workaround is to (re)move the sqlite database and restart e.g.
mv /var/lib/fail2ban/fail2ban.sqlite3 /tmp/ && systemctl restart fail2ban
Tested on
- fail2ban 0.11.2
- Debian 11 Bullseye