diff --git a/SETUP.md b/SETUP.md index 5e186be..cbb655f 100644 --- a/SETUP.md +++ b/SETUP.md @@ -506,14 +506,19 @@ Enable jails for `sshd`, `postfix`, `postfix-sasl`, `postfix-rbl`, `/etc/fail2ban/jail.local`, all watching `/var/log/mail.log` / `/var/log/auth.log` / `/var/log/apache2/*.log` as appropriate. -**Widen `sshd`'s `findtime` beyond the 30-minute default.** Default -`findtime=30m`/`maxretry=3` only catches bursts — a bot that spaces login -attempts ~33 minutes apart never accumulates 3 strikes inside any 30-minute -window and is never banned at all (seen live on this host against -`47.76.192.176`; check `fail2ban-client status sshd` and grep -`/var/log/fail2ban.log` for `Found`/`Ban` counts per IP if a repeat -offender never shows up banned). Fix in its own drop-in rather than -editing the packaged jail file: +**Widen `findtime` beyond the 30-minute default on every credential-auth +jail, not just `sshd`.** Default `findtime=30m`/`maxretry=3` only catches +bursts — a bot that spaces login attempts ~22-33 minutes apart never +accumulates 3 strikes inside any 30-minute window and is never banned at +all. Seen live on this host twice with the *identical* pacing trick: +first against `sshd` (`47.76.192.176`, ~33min spacing), then — because +only `sshd` got fixed at the time — against `dovecot` +(`47.95.196.60`/`82.157.132.42`/`120.48.118.132`/others, ~22-25min +spacing, coordinated multi-IP campaign, ran for days unbanned). Don't +wait for it to recur in a third jail: apply the same override to every +jail guarding a real credential (`sshd`, `dovecot`, `postfix-sasl`, +`sieve`, `courier-auth` if in use) at provisioning time, each in its own +drop-in rather than editing the packaged jail file: ``` # /etc/fail2ban/jail.d/sshd-findtime.local [sshd] @@ -521,10 +526,23 @@ findtime = 1d maxretry = 4 bantime = 1d ``` -`fail2ban-client reload sshd` applies it. Worth spot-checking the other -jails' `Found`/`Ban` ratios the same way — a *distributed* variant (many -different source IPs, each trying once) evades per-IP banning by design -and needs subnet-level blocking instead, which `findtime` tuning can't fix. +``` +# /etc/fail2ban/jail.d/dovecot-findtime.local +[dovecot] +findtime = 1d +maxretry = 4 +bantime = 1d +``` +`fail2ban-client reload ` applies each one. To check whether a jail +still has the gap: `fail2ban-client status ` for who's currently +banned, cross-referenced against grepping the jail's own log +(`/var/log/auth.log`, `/var/log/mail.log`, etc.) for per-IP hit counts — +if an IP has dozens of failures spread evenly a few minutes past +`findtime` apart and never shows up banned, that's this pattern. Also +worth spot-checking the Apache jails' `Found`/`Ban` ratios the same way — +a *distributed* variant (many different source IPs, each trying once) +evades per-IP banning by design and needs subnet-level blocking instead, +which `findtime` tuning can't fix. ### Bring it up @@ -706,10 +724,11 @@ Run through this after everything above is live: - [ ] Disk partition actually uses the full disk (`df -h /` vs. `lsblk`/`parted ... print free` should agree) - [ ] `PermitRootLogin no` / `PasswordAuthentication no` — verify live with `sshd -T`, not just the config file (see §1) -- [ ] `fail2ban-client status sshd` findtime is wide enough to catch - low-and-slow attempts, not just bursts (see §3) — spot-check - `/var/log/fail2ban.log` for any repeat-offender IP with several - `Found` entries but no `Ban` +- [ ] `fail2ban-client status ` findtime is wide enough to catch + low-and-slow attempts, not just bursts, for every credential jail + (`sshd`, `dovecot`, `postfix-sasl`, not just `sshd`) — see §3 — + spot-check `/var/log/fail2ban.log` for any repeat-offender IP with + several `Found` entries but no `Ban` - [ ] Any chrooted SFTP accounts (`/var/sftp/*`) no longer in active use are password-locked (`sudo passwd -S ` shows `L`), not left active diff --git a/TODO.md b/TODO.md index 0095656..764710a 100644 --- a/TODO.md +++ b/TODO.md @@ -236,3 +236,25 @@ Nothing here is urgent; all are low-risk, no-downtime changes. rather than editing the Debian-packaged jail file. Applied via `fail2ban-client reload sshd`; `47.76.192.176` was banned on its very next attempt after the change. + +- [x] **fail2ban: `dovecot` jail had the same low-and-slow gap as `sshd`** — done 2026-07-25 + found while auditing which IPs were hitting webmail hard enough to + deserve a ban but weren't in any currently-banned list. Same default + `findtime=30m`/`maxretry=3` as `sshd`'s pre-fix config. At least 4 IPs + (`47.95.196.60` 167 hits, `82.157.132.42` 144, `120.48.118.132` 76, + `188.164.195.116` 57, `157.245.38.26` 34) ran a coordinated IMAP + password spray against generic mailbox names (`admin@`, `test@`, + `support@`, `sales@jayfield.org`) starting almost simultaneously around + 2026-07-21 22:40-23:38, each pacing itself at ~1 attempt/22-25min — + just outside the 30-minute window, so none ever tripped 3 strikes. + `120.48.118.132` was still active as late as 2026-07-25 13:32, so the + campaign was ongoing, not historical. `postfix-sasl` shares the same + default thresholds and mail stack but showed much lower per-IP volume + in this pass — worth a follow-up check if it starts trending the same + way. + Fixed: `/etc/fail2ban/jail.d/dovecot-findtime.local`, same values as + the `sshd` fix (`findtime=1d`, `maxretry=4`, `bantime=1d`). Applied via + `fail2ban-client reload dovecot`; verified live with + `fail2ban-client get dovecot findtime/maxretry/bantime` and confirmed + the jail's existing ban state (`47.88.56.201`, 29 total bans) survived + the reload.