IMAP4 Mail Guard (imap)
The IMAP4 Mail Guard plugin monitors Internet Message Access Protocol version 4rev1 (RFC 3501) connections. It tracks client request tags and inspects server responses to detect failed authentication exchanges (NO or BAD [AUTHENTICATIONFAILED]), automatically banning credential stuffers before mail storage engines are impacted.
Capabilities & Threat Defense
| Threat / Attack Vector | Defense Mechanism | Action Taken |
|---|---|---|
| Credential Stuffing & Password Spraying | Tracks tagged NO / BAD authentication responses; enforces connection close with * BYE Too many auth failures when cap is reached (since v3.4.0) | Client IP banned after max_auth_failures threshold; connection terminated immediately |
| Connection Exhaustion | Enforces connection rate limits and burst caps | New connections throttled at the proxy layer |
| STARTTLS Handover | Detects tagged OK Begin TLS negotiation now | Transparently transitions to encrypted bidirectional pipe |
Installation
Install the plugin via CLI or declaratively:
# Install using short nametcp-warden plugins install imap# Or install via Git repository URLtcp-warden plugins install https://github.com/routewarden/plugins/imapConfiguration Reference
Add an IMAP guard service to tcp-warden.yaml:
services: imap_guard: listen: ":1143" upstream: "127.0.0.1:143" protocol: "imap" rate_limit: connections_per_minute: 20 burst: 5 max_auth_failures: 3 ban_after_failures: 3 ban_duration: "1h" plugin_config: banner: "* OK RouteWarden IMAP4rev1 Ready"Configuration Options
| Field | Type | Default | Description |
|---|---|---|---|
listen | string | ":1143" | Local proxy listen address and port. |
upstream | string | "127.0.0.1:143" | Target IMAP server (e.g. Dovecot) address and port. |
protocol | string | "imap" | Must be set to "imap". |
max_auth_failures | int | 3 | Number of failed authentication attempts before banning. Since v3.4.0 the connection is actively closed with * BYE Too many auth failures when the cap is reached, and scanner-style infinite retry loops are prevented. |
ban_duration | string | "1h" | Duration of the automated IP ban ("30m", "1h", "24h"). |
plugin_config.banner | string | "" | Optional synthetic greeting banner returned to clients. |
Network & Deployment Architecture
Option A: Kernel Firewall Redirection (nftables / iptables)
Redirect incoming external traffic on port 143 to RouteWarden port 1143:
# Redirect incoming external traffic on port 143 to RouteWarden port 1143sudo nft add rule ip routewarden_nat prerouting iifname "eth0" tcp dport 143 redirect to :1143Option B: IMAPS Direct Proxying (Port 993)
For explicit IMAPS (IMAP over TLS), RouteWarden can operate in front of the IMAPS service:
# Explicit IMAPS (port 993 over TLS)services: imaps_guard: listen: ":9930" upstream: "127.0.0.1:993" protocol: "generic" # L4 transparent proxy for direct TLS rate_limit: connections_per_minute: 20 burst: 5Option C: Docker Compose Network Isolation
Run the IMAP server inside an isolated container network, exposing both IMAP (143) and IMAPS (993) services only through RouteWarden:
services: routewarden: image: ghcr.io/routewarden/tcp-warden:latest ports: - "143:1143" # Map host IMAP port 143 to RouteWarden - "993:9930" # Map host IMAPS port 993 to RouteWarden - "9091:9091" # Management API volumes: - ./tcp-warden.yaml:/etc/routewarden/tcp-warden.yaml:ro depends_on: - dovecot dovecot: image: mailserver/docker-mailserver:latest environment: - ENABLE_IMAP=1 # Do NOT publish host ports (143/993); keep internal to bridge networkTesting & Verification
Track tagged response codes during authentication:
# Connect via netcat$ nc 127.0.0.1 1143* OK Dovecot ready.a001 LOGIN testuser wrongpassworda001 NO [AUTHENTICATIONFAILED] Authentication failed.a002 LOGOUT