From eb42a8272de5fda8b0b3ec6aab27ca336c099d10 Mon Sep 17 00:00:00 2001 From: Maurus Decimus <11444311+mdecimus@users.noreply.github.com> Date: Sun, 5 Jul 2026 10:26:18 +0200 Subject: [PATCH] Fix Auto-ban: IP block expiration ignores per-reason ban durations --- CHANGELOG.md | 1 + crates/common/src/network/security.rs | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db8b9136..308d9bf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If - Masked emails: Return `UnknownRecipient` only for disabled or expired masked emails. - IDN: `sanitize_email` rejects valid Punycode domains. - Directory: Removing a user from all groups does not sync the changes correctly. +- Auto-ban: IP block expiration ignores per-reason ban durations. ## [0.16.11] - 2026-06-25 diff --git a/crates/common/src/network/security.rs b/crates/common/src/network/security.rs index 38a09643..23a045ec 100644 --- a/crates/common/src/network/security.rs +++ b/crates/common/src/network/security.rs @@ -36,7 +36,10 @@ pub struct Security { pub allowed_ip_addresses: AHashSet>, pub allowed_ip_networks: Vec>, pub has_allowed_networks: bool, - pub blocked_ip_expiration: Option, + pub auth_ban_period: Option, + pub abuse_ban_period: Option, + pub loiter_ban_period: Option, + pub scan_ban_period: Option, pub http_banned_paths: Vec, pub scanner_fail_rate: Option, @@ -164,7 +167,10 @@ impl Security { has_allowed_networks: !allowed_ip_networks.is_empty(), allowed_ip_addresses, allowed_ip_networks, - blocked_ip_expiration: security.auth_ban_period.map(|v| v.as_secs()), + auth_ban_period: security.auth_ban_period.map(|v| v.as_secs()), + abuse_ban_period: security.abuse_ban_period.map(|v| v.as_secs()), + loiter_ban_period: security.loiter_ban_period.map(|v| v.as_secs()), + scan_ban_period: security.scan_ban_period.map(|v| v.as_secs()), auth_fail_rate: security.auth_ban_rate, rcpt_fail_rate: security.abuse_ban_rate, loiter_fail_rate: security.loiter_ban_rate, @@ -191,6 +197,16 @@ impl Security { password_default_expiration: auth.password_default_expiry.map(|v| v.as_secs()), } } + + fn ban_period(&self, reason: BlockReason) -> Option { + match reason { + BlockReason::RcptToFailure => self.abuse_ban_period, + BlockReason::AuthFailure => self.auth_ban_period, + BlockReason::Loitering => self.loiter_ban_period, + BlockReason::PortScanning => self.scan_ban_period, + BlockReason::Manual | BlockReason::Other => None, + } + } } impl Server { @@ -304,7 +320,7 @@ impl Server { .core .network .security - .blocked_ip_expiration + .ban_period(reason) .map(|v| now + v); self.inner .data