saslfail: Escalating Fail2ban Bans for Postfix SASL Authentication Attacks

Postfix mail servers get hammered with SASL authentication brute-force attempts constantly. The standard fail2ban response — ban the IP for an hour or a day — doesn’t change attacker behavior. An IP that gets unbanned just comes back. saslfail takes a different approach: escalating bans that get progressively longer on repeat offenders.

How the escalation works

saslfail implements a three-tier ban system backed by a persistent SQLite database:

  • First offense — 48 hour ban
  • Second offense — 8 day ban
  • Third offense — 32 day ban

The offense history survives fail2ban restarts and server reboots. An IP that comes back after serving a 48-hour ban and tries again gets 8 days. The theory is that the marginal cost of adding an IP to a rotation isn’t zero, and escalating bans make your server progressively less worth targeting.

Architecture

The system runs three fail2ban jails. The higher-tier jails use dummy filters — they don’t scan logs directly. Instead, ban-tracker.sh handles the escalation logic: it watches for new bans from the first jail, looks up the IP’s history in the database, and calls the fail2ban API to promote the ban to the appropriate tier.

This design avoids a cascade bug present in simpler escalating implementations where a single authentication failure could trigger multiple jails simultaneously.

Installation

git clone https://github.com/kshartman/saslfail
cd saslfail
sudo ./install.sh

The installer backs up existing fail2ban configuration, walks you through notification preferences and IP whitelisting, and verifies all three jails activate. Ports 25, 465, and 587 are covered.

Notifications

Five notification modes: None, Smart (batches notifications to avoid noise), Immediate, Daily digest, and Weekly summary. Smart mode is the default — it sends a notification on first ban of a new IP, then batches subsequent activity.

Monitoring

# View active bans with offense history
ban-tracker.sh status

# View all bans sorted by date
ban-tracker.sh list

The ban database lives at /var/lib/saslfail/bans.db and can be queried directly with SQLite if you want custom reporting.

The code is on GitHub: kshartman/saslfail.

← WordPress Full Site Editing: Database vs Theme Files
→ voicemail-transcriber: Whisper-Powered Voicemail Transcription via IMAP