Mail Server

Security & Spam Protection

Configure auto-ban rules, manage blocked IPs, review TLS settings, and resolve the Docker gateway IP auto-ban issue on the DramWell Stalwart mail server.

advanced8 min read

Overview

Stalwart includes built-in abuse protection — rate limiting on SMTP and authentication endpoints, automatic IP banning on threshold violations, and TLS enforcement for all connections. These protections are effective against common attack patterns but require careful tuning in Docker-based deployments where internal traffic can inadvertently trigger the same rules as external abuse.

Auto-Ban Thresholds

Stalwart monitors three event types and bans the source IP when the count exceeds a threshold within a one-hour rolling window:

Event Type Default Threshold Trigger
scan 100 / hour Port scanning or probing behavior
auth 100 / hour Authentication failures (bad password attempts)
abuse 100 / hour Policy violations (sending to blocked addresses, DNSBL hits)

These thresholds are configured in the Stalwart admin panel under Configuration > Security > Auto-Ban.

Adjusting Thresholds

If the default thresholds are too sensitive for your traffic patterns (e.g., a bulk sending integration triggers the abuse threshold), increase the specific threshold rather than disabling the rule. Access the settings at:

Admin PanelConfigurationSecurityAbuse Protection

Or via the API:

PATCH /api/settings/auth.banned-threshold
Content-Type: application/json
Authorization: Basic <credentials>

{"value": "200"}

TLS Configuration

Stalwart uses two separate TLS mechanisms:

Protocol TLS Method Certificate Source
SMTP (587) STARTTLS, direct binding Stalwart ACME (auto-renew)
IMAPS (993) TLS, direct binding Stalwart ACME (auto-renew)
HTTPS (443) TLS, nginx proxy LetsEncrypt via certbot (auto-renew)

Stalwart ACME

Stalwart manages its own certificate for SMTP and IMAPS using ACME (Let's Encrypt). The renewal is automatic — no manual intervention is required. To check the current certificate expiry:

Admin PanelConfigurationTLSCertificates

If ACME renewal fails (usually due to a firewall blocking port 80 for the HTTP-01 challenge), you can manually trigger a renewal from the same panel.

nginx TLS

nginx handles HTTPS termination for the admin panel and JMAP API. The LetsEncrypt certificate is renewed by certbot running as a cron job on the host. Verify the renewal timer is active:

systemctl status certbot.timer

Certificate expiry can be checked with:

certbot certificates

Managing Blocked IPs

Blocked IPs are stored in Stalwart's settings under the server.blocked-ip.* key namespace. Each blocked entry is a separate key with the IP address as the suffix.

Viewing All Blocked IPs

GET /api/settings?prefix=server.blocked-ip
Authorization: Basic <credentials>

Adding a Block

PATCH /api/settings/server.blocked-ip.203.0.113.42
Content-Type: application/json
Authorization: Basic <credentials>

{"value": true}

Removing a Block

DELETE /api/settings/server.blocked-ip.203.0.113.42
Authorization: Basic <credentials>

Changes take effect immediately without a server restart.

Docker Gateway IP Auto-Ban Issue

Known issue: In the Docker deployment, the host network's Docker gateway IP (typically 172.17.0.1) can get auto-banned by Stalwart's abuse protection. This happens because all traffic from the Docker host — including legitimate internal services calling the mail API — appears to originate from the gateway IP. When that IP accumulates enough events, Stalwart bans it and internal mail delivery stops.

Symptoms

  • Internal services stop receiving mail or API calls to Stalwart return connection refused
  • Stalwart logs show Connection rejected: IP is blocked for 172.17.0.1 or similar
  • External mail (inbound from the internet) continues to work normally

Resolution

  1. Identify the Docker gateway IP on the host:

    docker network inspect bridge --format '{{range .IPAM.Config}}{{.Gateway}}{{end}}'
    

    Typically 172.17.0.1.

  2. Remove the auto-ban via the API:

    DELETE /api/settings/server.blocked-ip.172.17.0.1
    
  3. Add the gateway IP to Stalwart's allowlist to prevent future bans:

    PATCH /api/settings/server.allowed-ip.172.17.0.1
    {"value": true}
    
  4. Verify access is restored by testing an internal API call to Stalwart.

The allowlist entry persists across container restarts. Re-apply it if the Stalwart container is redeployed from scratch with a fresh configuration.

Tips

  • After any change to blocked or allowed IP lists, confirm the change took effect by re-fetching the settings key — Stalwart does not return confirmation in the response body for some PATCH operations.
  • Review the auto-ban log monthly under Admin Panel → Logs → Security. A pattern of repeated bans from the same IP ranges suggests a targeted attack that warrants firewall-level blocking upstream of Stalwart.
  • Set up an alert (via uptime monitor or log scraping) for the string Connection rejected: IP is blocked targeting the Docker gateway IP. Catching the Docker gateway ban early prevents internal mail outages that can be hard to diagnose under pressure.

Related Articles

Was this article helpful?