POP3 Mail Guard (pop3)
The POP3 Mail Guard plugin monitors Post Office Protocol 3 (RFC 1939) client/server exchanges. It tracks authentication commands (USER and PASS) and intercepts negative server responses (-ERR) to ban brute-force attacks against user mailboxes while seamlessly supporting STLS TLS upgrades.
Capabilities & Threat Defense
| Threat / Attack Vector | Defense Mechanism | Action Taken |
|---|---|---|
| Mailbox Password Spraying | Tracks -ERR [AUTH] responses on PASS commands; enforces connection close with -ERR Too many auth failures when cap is reached (since v3.4.0) | Client IP banned after max_auth_failures; connection terminated immediately |
| Session Flooding | Enforces connection rate limits and burst caps | New connections throttled at the proxy layer |
| STLS TLS Handover | Detects successful +OK Begin TLS negotiation | Transparently transitions to encrypted bidirectional pipe |
Installation
Install the plugin via CLI or declaratively:
# Install using short nametcp-warden plugins install pop3# Or install via Git repository URLtcp-warden plugins install https://github.com/routewarden/plugins/pop3Configuration Reference
Add a POP3 guard service to tcp-warden.yaml:
services: pop3_guard: listen: ":1110" upstream: "127.0.0.1:110" protocol: "pop3" rate_limit: connections_per_minute: 20 burst: 5 max_auth_failures: 3 ban_after_failures: 3 ban_duration: "1h" plugin_config: banner: "+OK RouteWarden POP3 Proxy Ready"Configuration Options
| Field | Type | Default | Description |
|---|---|---|---|
listen | string | ":1110" | Local proxy listen address and port. |
upstream | string | "127.0.0.1:110" | Target POP3 server (e.g. Dovecot) address and port. |
protocol | string | "pop3" | Must be set to "pop3". |
max_auth_failures | int | 3 | Failed login attempts before banning. Since v3.4.0 the connection is actively closed with -ERR Too many auth failures when the cap is reached, preventing brute-force tools from retrying indefinitely. |
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 110 to RouteWarden port 1110:
# Redirect incoming external traffic on port 110 to RouteWarden port 1110sudo nft add rule ip routewarden_nat prerouting iifname "eth0" tcp dport 110 redirect to :1110Option B: POP3S Direct Proxying (Port 995)
For explicit POP3S (POP3 over TLS), RouteWarden can operate in front of the POP3S service:
# Explicit POP3S (port 995 over TLS)services: pop3s_guard: listen: ":9950" upstream: "127.0.0.1:995" protocol: "generic" # L4 transparent proxy for direct TLS rate_limit: connections_per_minute: 20 burst: 5Option C: Docker Compose Network Isolation
Run the POP3 server inside an isolated container network, exposing both POP3 (110) and POP3S (995) services only through RouteWarden:
services: routewarden: image: ghcr.io/routewarden/tcp-warden:latest ports: - "110:1110" # Map host POP3 port 110 to RouteWarden - "995:9950" # Map host POP3S port 995 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_POP3=1 # Do NOT publish host ports (110/995); keep internal to bridge networkTesting & Verification
Simulate authentication failures and observe -ERR tracking:
# Connect via netcat$ nc 127.0.0.1 1110+OK Dovecot ready.USER testuser+OK Send passwordPASS wrongpassword-ERR [AUTH] Authentication failed.QUIT+OK Logging out.