(UPDATE: I changed 15 to 14, having discovered the implementation is off-by-one from what I thought! 14 gives 229 days…)
Debian 11 and other OS releases have new versions of fail2ban supporting some nice features:
- Incremental auto-increases of blocking, so that repeat attackers don’t overwhelm your server
- Revised underlying database (this also may work in Debian 10 ie f2b 0.10) allowing smart queries and reports so you can better see what’s going on, and see the impact of your configuration
Below, I share how I’ve set up our fail2ban, along with one example of a nice shell-script report. With this as a start, you can hopefully see how to do what you might want… and perhaps some of this may make its way into the Webmin GUI in the future
I’ll first provide simple instructions to replicate my setup, then discuss why I did what I did.
- In /etc/fail2ban/jail.local (Network->Fail2ban->Edit Config Files, and scroll to the bottom of the list), edit or add these uncommented lines:
[DEFAULT] ignoreip = <provide space-separated list of local ipv4 or ipv6 CIDR addresses, eg 127.0.0.1 192.168.0.0/16 ...> bantime = 1h maxretry = 3 findtime = 1d bantime.increment = true # 20 minutes bantime.factor = 1200 #plh start at bantime, ADD shifted count times factor. Max of 14 is 229 days. bantime.formula = ban.Time + (1<<(ban.Count if ban.Count<14 else 14)) * banFactor # find bad IP in ANY jail, not just the current one. If they're bad, they're bad. bantime.overalljails = true
- Now set specific jails to a longer default bantime.
- You can do this in the GUI by clicking on specific jails in
Filter Action Jails, or do it right here in jail.local while editing. Just go to the section for a specific jail and add a line like:
bantime = 2d
Why set it up this way:
maxretryallows someone 3 tries per day to get in by default, without complaint.
- For some jails, I’ve reduced that further:
- postfix and postfix-sasl: 2 tries
- dovecot, anvil and dkim (I created new jails for the latter 2): only one try. People making invalid login attempts are immediately blocked from our server! It’s amazing how many bots are doing that.
- For some jails, I’ve reduced that further:
I played with the parameters of my auto-increment setup in a spreadsheet until I had a result I like. This is not the same as any of the examples provided in the fail2ban templates!
- I want a reasonably long minimum ban. That’s “bantime” – from an hour to two days. Most jails have a two day minimum for me.
- I want the ban to grow reasonably quickly to…
- A long enough time that an attacker isn’t harming my server performance
- Not so long that a banned IP may well be owned by someone else when unblocked. (One of my early formulas had a max bantime of over 200 years
- With my formula, at 15 tries it’s 229 days, almost 8 months. Ten tries, a little over a week.
A SAMPLE REPORT (Not available in any existing app)
Fail2ban uses a
sqlite3 database. You can use the
sqlite3 CLI utility to extract data quickly and with relative ease. My script below does much of the hard work for you (took a bit to discover how to extract that final field )
NOTE: you may not have the
sqlite3 CLI package installed, even though the database is in use. Just use Webmin tools or the shell (eg
apt install sqlite3) to get it.
Example: list the 25 IP’s with with longest future ban time, including why they are banned:
sqlite3 -header -column 'file:/var/lib/fail2ban/fail2ban.sqlite3?mode=ro' "select datetime(timeofban,'unixepoch','localtime') as startofban, datetime(timeofban+bantime,'unixepoch','localtime') as endofban, ip, jail, bantime, bancount, substr(json_extract(data,'$.matches'),1,100) as Detail from bips where endofban > datetime('now','localtime') order by endofban desc limit 10"
This creates a table with:
- startofban - timestamp when the ban began
- endofban - timestamp when the ban will end
- ip - banned address
- jail - which jail it’s in
- bantime - seconds represented by (endofban - startofban)
- bancount - how many times this IP has been banned
- detail - the specific reason for the ban. Usually includes things like what address and PW was used for a failed login or email attempt, etc. Limited to first 100 characters of the details.
Example: to see the shortest bans, remove " desc" from the ‘order by’ query
Example: want to see this for each jail? change ‘order by’ to “jail, endofban”
WHY THIS HELPS
It’s easy to imagine that system admins shouldn’t be concerned about details like this. In general, I agree! For example, Webmin provides a nice level of information in the
Jails Status and Actions tab, which lets me know I have several thousand IP’s banned in my jails, and none in a few (hmmm… need to check the configuration of those jails!)
However, sometimes a quick look at a detail report like above/below can be incredibly helpful. Some questions I find important…
- Are my bans working correctly?
- Am I banning IP’s too long?
- Is there a significant pattern to the bad apples going after my servers?
Here’s a real report extract… the most recent ten bans on my own server:
startofban endofban ip jail bantime bancount Detail ------------------- ------------------- --------------- ------------ ------- -------- ---------------------------------------------------------------------------------------------------- 2023-03-08 16:42:22 2023-03-10 16:42:22 184.108.40.206 dovecot 172800 1 aster dovecot: auth: passwd-file(firstname.lastname@example.org,220.127.116.11): unknown user 2023-03-08 16:42:35 2023-03-10 16:42:35 18.104.22.168 dovecot 172800 1 aster dovecot: auth: passwd-file(cseab,22.214.171.124): unknown user 2023-03-08 16:42:45 2023-03-10 16:42:45 126.96.36.199 postfix-sasl 172800 1 aster postfix/smtpd: warning: unknown[188.8.131.52]: SASL LOGIN authentication failed: UGFzc 2023-03-08 16:42:57 2023-03-10 16:42:57 184.108.40.206 dovecot 172800 1 aster dovecot: auth: passwd-file(email@example.com,220.127.116.11): unknown user 2023-03-08 16:43:00 2023-03-10 16:43:00 18.104.22.168 dovecot 172800 1 aster dovecot: auth: passwd-file(postmaster,22.214.171.124): unknown user 2023-03-08 16:43:03 2023-03-10 16:43:03 126.96.36.199 dovecot 172800 1 aster dovecot: auth: passwd-file(firstname.lastname@example.org,188.8.131.52): unknown user 2023-03-08 16:43:09 2023-03-10 16:43:09 184.108.40.206 dovecot 172800 1 aster dovecot: auth: passwd-file(email@example.com,220.127.116.11): unknown user 2023-03-08 16:43:10 2023-03-10 16:43:10 18.104.22.168 dovecot 172800 1 aster dovecot: auth: passwd-file(azcqwqz,22.214.171.124): unknown user 2023-03-08 16:43:27 2023-03-10 16:43:27 126.96.36.199 dovecot 172800 1 aster dovecot: auth: passwd-file(firstname.lastname@example.org,188.8.131.52): unknown user 2023-03-08 16:43:28 2023-03-10 16:43:28 184.108.40.206 dovecot 172800 1 aster dovecot: auth: passwd-file(email@example.com,220.127.116.11): unknown user
What this immediately tells me:
- I’m getting about ten attempts a minute on my POP/IMAP ports, just from new IP’s
- It does not look like a dictionary attack. Truly random character strings.
- My fail2ban config is functioning
I’ll stop there. Hopefully this little info-tutorial has been helpful!
|Operating system||Debian Linux 11|