Find and ban recidive subnets using fail2ban.
This project was forked and modified by mjpcomp on 2021-03-30 from the original - this modification allows for using firewalld, along with ipset net:hash containers, to perform the blocking (if you're using Virtualmin, this will make sense). Currently, the code this was forked from was only designed to pull /24 networks, so, it remains as is.
Fail2ban is perfect to ban single hosts that cause authentication errors or try some other bad stuff on your server. But watching the fail2ban.log I discovered that some attackers use ip ranges. Some ip's are found by fail2ban but not banned, because the attack is distributed from a complete subnet. Fail2ban by now is not able to discover and ban those subnets. There is an issue for that #927 and a python solution fail2ban-subnet. But both did't satisfy my needs, so this little project is born.
There is a shell script, that starts an awk script which scans the fail2ban.log file. The shell script should be started on a regular basis (e.g. cronjob). Every ip where fail2ban said "Found" is remembered by the awk script. If the /24 subnet of that ip has too many "Founds", then the subnet is written in the fail2ban-subnet.log file. Now fail2ban itself has a jail and filter configuration to watch this log file and will ban and unban the subnet according to your configuration.
- fail2ban installed and working (tested with v0.10.2)
- gawk installed
- Copy the scripts
fail2ban-subnet.awk
andfail2ban-subnet-starter.sh
to a location of your choice (edit the sh file to make sure the path to the awk is correct) - Ensure the
fail2ban-subnet-starter.sh
is executable (chmod +x ...
) - Copy
firewallcmd-ipset-subnet.local
to/etc/fail2ban/action.d/
- Copy
recidive-subnet.local
to/etc/fail2ban/filter.d
- Add the filter definition in
jail.local
to your/etc/fail2ban/jail.local
(at the very end) - Configure settings in
fail2ban-subnet-starter.sh
- Configure settings in
/etc/fail2ban/jail.local
(esp. bantime) - Call your
fail2ban-subnet-starter.sh
(for the first and the last time by hand - if you don't, and don't have the fail2ban-subnet file yet, the fail2ban service will fail to start) - Restart fail2ban (depends on your unix distro)
- Add
fail2ban-subnet-starter.sh
to your cron to be started regularly (e.g. every hour)
findtime
- Time period in seconds
- A subnet is banned if it generated more than
maxips
"Found" messages with different ip's in the lastfindtime
seconds - My setting: 5 days
findtime=$((5*24*60*60))
excluded_jails
- String with jailnames separated with <space>
- The jailnames given in
excluded_jails
will not be checked - My setting: exclude recidive and recidive-subnet (myself)
excluded_jails="recidive recidive-subnet"
maxips
maxips
is the number of maximum different ips from a /24 subnet with a "Found" in the fail2ban logfile before the subnet gets banned.- smaller numbers make the tool more "aggressive".
- In my opinion this should be not smaller than 3
- My setting:
maxips=5
logfilename
- The path and the name of the fail2ban logfile
- My setting:
logfilename=/var/log/fail2ban.log
outputfile
- File path and name where to log the found subnet
- Should correspond to the parameter
logpath
in the[recidive-subnet]
jail definition injail.local
- My setting:
outputfile=/var/log/fail2ban-subnet.log
awkscript
- File path and name where you stored the awk script
fail2ban-subnet.awk
- My setting:
awkscript=/usr/local/include/fail2ban-subnet/fail2ban-subnet.awk
- File path and name where you stored the awk script
Fail2ban recommends to not directly change the jail.conf
file, but to create a jail.local
file with your local configuration. So if you correctly installed and configured fail2ban you should have a jail.local
file.
The jail.local
file given in this repository should not override your jail.local
file but you should copy the content at the end of your existing jail.local
.
Then you can adapt the configuration to your needs.
enabled
- This enables or disables the jail
- My setting:
enabled = true
logpath
- The path to the file which the filter should parse
- This is the file, which is written by the scripts above
- Remember, this file must exist if you enable this jail, or, fail2ban will not start due to the missing logfile
- My setting:
logpath = /var/log/fail2ban-subnet.log
bantime
- Time period how long the subnet should be banned
- IPSet has a limit (at least on Ubuntu 20.04) of just over 24 days
- My setting:
bantime = 1week
findtime
- A subnet is banned if it has generated
maxretry
logs during the lastfindtime
seconds. - A change only makes sense, if you change the
maxretry
to something other than1
- My setting:
findtime = 1day
- A subnet is banned if it has generated
maxretry
maxretry
is the number of founds before a subnet get banned.- As most of the work is done by the scripts which generate the
fail2ban-subnet.log
once a subnet is found it should be banned directly, so I setmaxretry
to1
- If you don't want to be as aggressive as I, then better change the
maxips
config above to a higher value or lower thebantime
- My setting:
maxretry = 1