Skip to content

Configuration Reference ​

TCP Warden is configured via a single declarative YAML file (default: tcp-warden.yaml).

Schema Auto-Completion

Enable real-time autocomplete, tooltips, and validation in VS Code or JetBrains editors by adding the JSON Schema header at the top of your YAML file or mapping it in your workspace settings:

# yaml-language-server: $schema=https://routewarden.github.io/tcp-warden/tcp-warden.schema.jsonglobal:  max_connections: 10000services:  ssh_bastion:    listen: ":2222"    upstream: "127.0.0.1:22"

Configuration Schema ​

Full reference with global policy defaults, management API, CrowdSec integration, plugin declarations, and service definitions:

# yaml-language-server: $schema=https://routewarden.github.io/tcp-warden/tcp-warden.schema.jsonglobal:  max_connections: 10000  ban_duration: "1h"  ban_after_failures: 5  tarpit_ms: 1000  log_level: "warn"  log_file: "/var/log/routewarden/tcp-warden.jsonl"  geoip_db: "/etc/routewarden/GeoLite2-Country.mmdb"  ip_filter:    allow:      - "127.0.0.1/32"      - "10.0.0.0/8"    deny:      - "198.51.100.0/24"  geo_block:    deny_countries:      - "KP"    allow_countries: []api:  enabled: true  listen: "127.0.0.1:9091"  # Optional: Unix domain socket for local IPC (no open TCP ports needed)  socket: "/var/run/routewarden/tcp-warden.sock"  socket_mode: "0666"# Optional: CrowdSec LAPI Bouncer (disabled by default)# crowdsec:#   enabled: true#   lapi_url: "http://127.0.0.1:8080"#   api_key: "${CROWDSEC_API_KEY}"#   update_frequency: "10s"#   fallback_action: "ban"plugins:  postgres:    enabled: true    source: "https://github.com/routewarden/plugins/postgres"  redis:    enabled: true    source: "https://github.com/routewarden/plugins/redis"  tls_sni:    enabled: true    source: "https://github.com/routewarden/plugins/tls_sni"

Global Settings (global) ​

Daemon-wide defaults for connection limits, ban rules, persistent state, and logging.

SettingTypeDefaultWhat it means
max_connectionsint10000Total active connections allowed across all services at once.
ban_durationduration"1h"How long an offending IP stays banned (e.g., "1h", "24h").
ban_after_failuresint5Failed attempts within the sliding window before an IP is banned.
tarpit_msint1000Milliseconds to stall banned or challenged connections before closing.
data_dirstring"/var/lib/routewarden"Persistent state directory storing SQLite bans.db and installed plugins cache.
log_levelstring"warn"Log verbosity: debug, info, warn, error, or off. See Log Levels.
log_filestring—Path to JSONL audit log file (leave empty to log to stdout).
geoip_dbstring—Path to MaxMind GeoLite2 Country database (.mmdb).
ip_filter.allow[]CIDR[]Subnets that are always allowed (e.g. ["10.0.0.0/8"]).
ip_filter.deny[]CIDR[]Subnets that are always blocked immediately.
geo_block.deny_countries[]string[]Two-letter country codes to block (e.g. ["KP"]).

Management API (api) ​

Settings for the local HTTP administration, metrics, and SSE live events server (port 9091).

SettingTypeDefaultWhat it means
enabledbooltrueTurns the management HTTP server on or off.
listenstring"127.0.0.1:9091"Address and port to bind for management API requests (can also be configured via ROUTEWARDEN_API_LISTEN).
socketstring"/var/run/routewarden/tcp-warden.sock"Optional Unix domain socket path for local IPC (can also be configured via ROUTEWARDEN_API_SOCKET).
socket_modestring"0666"File permission mode for the Unix domain socket.
auth_tokenstring—Optional Bearer authentication token for securing REST and SSE endpoints.

CrowdSec Bouncer (crowdsec) Optional ​

Connects TCP Warden to your CrowdSec Local API (LAPI) to automatically block malicious IPs.

Optional Integration

Connecting TCP Warden to CrowdSec is completely optional (enabled: false by default). TCP Warden functions as a complete standalone Layer 4 proxy and firewall with its own GeoIP blocking, CIDR filters, rate limits, protocol inspectors, failure tracking, and embedded SQLite ban storage.

To set up CrowdSec log ingestion, parsers, scenarios, and bouncers, see the dedicated CrowdSec Integration Guide.

SettingTypeDefaultWhat it means
enabledboolfalseEnables real-time CrowdSec ban enforcement.
lapi_urlstring—URL of your CrowdSec instance (e.g. "http://127.0.0.1:8080").
api_keystring—Bouncer API key generated via cscli bouncers add.
update_frequencyduration"10s"How often to refresh active ban decisions from CrowdSec.
fallback_actionstring"ban"Action when an IP is flagged: ban, throttle, or bypass.

Services (services) ​

Each key under services defines an isolated Layer 4 proxy listener. Common service fields:

FieldTypeDescription
listenstringSingle port (":2222") or port range (":8000-8005").
upstreamstringBackend target: single address ("127.0.0.1:22"), single backend for many-to-one ranges ("10.0.0.1:80"), or matching 1:1 range ("10.0.0.1:9000-9005").
transportstringNetwork transport: "tcp" (default), "udp", or "both" (binds both TCP and UDP listeners on the same port, e.g. for DNS on :53).
protocolstringProtocol handler: ssh, smtp, pop3, imap, tcp, or any loaded plugin name (dns, bittorrent, http, postgres, redis, etc.).
plugin_configmapProtocol-specific inspector options passed directly to the active plugin.
rate_limit.connections_per_minuteintToken-bucket rate: connections (TCP) or packets (UDP) allowed per minute per IP.
rate_limit.burstintMaximum burst allowance above the rate limit.
max_auth_failuresintMaximum auth failures before banning the client IP.
ban_durationdurationOverrides global.ban_duration for this service.
response.modestringRejection strategy for TCP: reject
udp.session_timeoutdurationIdle timeout before cleaning up a client's UDP NAT/session mapping (default: "30s").
udp.max_sessionsintMaximum concurrent active UDP client sessions (0 = unlimited). Protects against session table memory exhaustion.
udp.read_buffer_sizeintPer-datagram socket read buffer in bytes (default: 65535).

UDP Transport & Datagram Proxying (udp) ​

TCP Warden v3.0.0 introduces native Layer 4 UDP Proxying alongside TCP. Services can run strictly over UDP (transport: "udp") or dual-stack (transport: "both"), allowing a single service definition to guard both protocols (such as DNS on port 53).

Full Pipeline Protection on Every Datagram ​

Inbound UDP datagrams pass through the complete security pipeline before forwarding:

  1. Active Banlist: Drops datagrams from IPs banned manually, via SQLite, or by auto-ban.
  2. CrowdSec LAPI Bouncer: Drops datagrams if CrowdSec returns an active community ban decision.
  3. CIDR IP Filter: Enforces service-level and global allow and deny subnets.
  4. Geo-Blocking: Evaluates allow_countries and deny_countries using MaxMind GeoIP.
  5. Token Bucket Rate Limiting: Throttles datagram rates per client IP (connections_per_minute and burst).
  6. MaxSessions Guard: Rejects new sessions when active concurrent client count exceeds udp.max_sessions.
  7. Session Table & NAT Mapping: Tracks client endpoints and reaps idle sessions after udp.session_timeout.
  8. Deep Protocol Inspection (UDPPlugin): Analyzes datagram payloads (e.g. DNS domain filtering, BitTorrent DHT/uTP validation) with in-place mutation or drop/reject verdicts.

Anti-Amplification: Silent Drops for UDP

Unlike TCP (which can reply with a TCP RST, banner message, or tarpit delay), blocked UDP datagrams are always dropped silently.

Replying to unauthorized UDP packets would allow attackers with spoofed source IPs to abuse RouteWarden as a reflection/amplification vector. Silent drops guarantee zero reflection risk.


Port Range Forwarding ​

TCP Warden supports listening on continuous port ranges:

  • 1:1 Port Mapping: Each incoming port forwards directly to its corresponding port on the upstream target.
  • Many-to-One Port Mapping: An entire range of ingress ports forwards into a single backend (ideal for HTTP gateways and proxy fleets).
services:  # 1:1 Port Range: each ingress port maps to an offset on upstream  # Port 8000 -> 9000, 8001 -> 9001, ..., 8005 -> 9005  microservice_fleet:    listen: ":8000-8005"    upstream: "10.0.0.10:9000-9005"    protocol: "tcp"

Plugin Configuration (plugin_config) ​

When using a modular plugin from routewarden/plugins, use plugin_config to customize the inspector's behavior:

PluginKey OptionsExample Usage
dnsblocked_domains, blocked_qtypes, block_private_ips, min_ttl, max_packet_sizeIntercept malicious domains, block ANY/AXFR reflection queries, prevent DNS rebinding.
bittorrentblocked_info_hashes, allowed_peer_id_prefixes, private_tracker_mode, blocked_dht_methodsFilter swarms by info-hash, enforce -CCVVVV- client formats, block DHT poisoning.
httpallowed_hosts, blocked_paths (regex), blocked_headers (regex)Intercept sensitive paths (/\.env), block scanner User-Agents.
redisblocked_commandsIntercept destructive commands (FLUSHALL, CONFIG, SHUTDOWN).
mongodbblocked_opsIntercept collection drops (drop, dropDatabase, shutdown).
tls_sniallowed_domains, blocked_domainsFilter TLS SNI domain names with wildcard support (*.example.com).
mqttmax_client_id_len, blocked_client_prefixesEnforce IoT device naming standards and block scanner prefixes.
minecraftblocked_protocol_versionsReject outdated or vulnerable game client versions.

Response Actions (response.mode) ​

Choose how TCP Warden handles blocked or challenged connections:

ModeWhat it doesBest used for
rejectCloses the connection immediately with a TCP RST.Clean, fast rejection with zero latency.
dropCloses the socket silently without sending any data.Hiding services from automated port scanners.
tarpitStalls the connection for tarpit_ms before closing.Slowing down aggressive scanners and wasting bot concurrency.
silentTerminates without writing to logs or events.Silently discarding high-volume spoofed traffic.

Configuration Validation ​

Always validate your configuration file before starting or reloading the proxy daemon:

# Validate config syntax, CIDRs, duplicate ports, and plugin dependenciestcp-warden validate --config /etc/routewarden/tcp-warden.yaml# Output:# ✓ Configuration /etc/routewarden/tcp-warden.yaml is valid!#   • Global Max Connections: 10000#   • Services Configured:    4#   • CrowdSec Enabled:       true

Released under the MIT License.