Skip to content

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 VectorDefense MechanismAction Taken
Credential Stuffing & Password SprayingTracks 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 ExhaustionEnforces connection rate limits and burst capsNew connections throttled at the proxy layer
STARTTLS HandoverDetects tagged OK Begin TLS negotiation nowTransparently 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/imap

Configuration 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 ​

FieldTypeDefaultDescription
listenstring":1143"Local proxy listen address and port.
upstreamstring"127.0.0.1:143"Target IMAP server (e.g. Dovecot) address and port.
protocolstring"imap"Must be set to "imap".
max_auth_failuresint3Number 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_durationstring"1h"Duration of the automated IP ban ("30m", "1h", "24h").
plugin_config.bannerstring""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 :1143

Option 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: 5

Option 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 network

Testing & 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

Released under the MIT License.