CrowdSec Integration Optional
TCP Warden is built to run fully autonomously, but it also natively supports bidirectional integration with CrowdSec.
Optional Integration
TCP Warden operates as a complete standalone proxy and firewall without CrowdSec. All core features—including GeoIP filtering, CIDR allow/deny lists, token-bucket rate limiting, protocol inspection, brute-force failure tracking, and embedded SQLite ban storage—function out of the box with zero external dependencies.
Only follow this guide if you wish to link TCP Warden to CrowdSec for collaborative community blocklists and centralized multi-server decision sharing.
How the Integration Works
The integration forms a closed-loop security cycle:
- Log Acquisition (Outbound Threat Feed): TCP Warden records every connection attempt, authentication failure, and port scan to
/var/log/routewarden/tcp-warden.jsonl. CrowdSec tail-reads this file, applying custom parsers and detection scenarios. - LAPI Bouncer (Inbound Enforcement): TCP Warden acts as a high-performance CrowdSec remediation bouncer. It periodically polls CrowdSec Local API (LAPI) for active decisions and drops or tarpits malicious IPs at Layer 4 before they consume backend server resources.
Step-by-Step Setup Guide
Follow these sequential steps to deploy the combined TCP Warden and CrowdSec stack.
Step 1: Set Up Log Acquisition (acquis.yaml)
Tell CrowdSec where to find TCP Warden's structured JSONL audit log:
# /etc/crowdsec/acquis.d/tcp-warden.yamlfilenames: - /var/log/routewarden/tcp-warden.jsonllabels: type: routewarden-tcpBuilt-in Optimization: Default warn Level
TCP Warden defaults to log_level: "warn", which logs only actionable security signals (auth_failure and blocked events) to /var/log/routewarden/tcp-warden.jsonl while suppressing routine allowed connection records. This significantly reduces log volume, disk I/O, and CPU consumption by CrowdSec parsers while maintaining 100% scenario detection fidelity. See Log Levels for full details.
Step 2: Install Custom Parser & Scenarios
TCP Warden ships with custom CrowdSec parsers and scenarios located in the repository under crowdsec/:
Parser (parsers/s01-parse/routewarden-tcp-warden.yaml)
Extracts service, client_ip, action, and reason fields from incoming audit records:
# /etc/crowdsec/parsers/s01-parse/routewarden-tcp-warden.yamlfilter: "evt.Line.Labels.type == 'routewarden-tcp'"onsuccess: next_stagename: routewarden/tcp-warden-parserdescription: "Parse TCP Warden structured JSONL security logs"nodes: - grok: pattern: '^%{GREEDYDATA:raw_json}$' apply_on: Line.Raw - json: target: evt.Parsed apply_on: raw_jsonstatics: - meta: service expression: "evt.Parsed.service" - meta: source_ip expression: "evt.Parsed.client_ip" - meta: action expression: "evt.Parsed.action" - meta: reason expression: "evt.Parsed.reason"Scenarios
Install or mount the scenarios from the crowdsec/scenarios/ directory:
- SSH Brute Force (
routewarden-tcp-ssh-bf.yaml): Detects repeated SSH authentication failures within a 60-second window. - SMTP Spam / Brute Force (
routewarden-tcp-smtp-bf.yaml): Detects senders repeatedly hitting blocked domains or failing authentication. - Port Scan Detector (
routewarden-tcp-portscan.yaml): Flags IPs attempting connection floods across unconfigured or closed ports.
Step 3: Register the Bouncer API Key
In CrowdSec, create a bouncer entry for TCP Warden to obtain an API key:
# Register TCP Warden as a bouncer in CrowdSecdocker compose exec crowdsec cscli bouncers add tcp-warden-bouncer# Output example:# Api key for 'tcp-warden-bouncer':# a1b2c3d4e5f678901234567890abcdef## Add this key to your .env file:echo "CROWDSEC_API_KEY=a1b2c3d4e5f678901234567890abcdef" >> .envStep 4: Configure tcp-warden.yaml
Enable the CrowdSec bouncer section in your tcp-warden.yaml:
# CrowdSec integration in tcp-warden.yamlglobal: # "warn" is recommended: suppresses routine "allowed" events from the JSONL # audit feed so CrowdSec only parses auth failures, port scans, and blocks. log_level: "warn" log_file: "/var/log/routewarden/tcp-warden.jsonl"crowdsec: enabled: true lapi_url: "http://127.0.0.1:8080" api_key: "${CROWDSEC_API_KEY}" update_frequency: "10s" fallback_action: "ban" # "ban" | "throttle" | "bypass"| Field | Type | Default | Description |
|---|---|---|---|
global.log_level | string | "warn" | Defaults to "warn" so the JSONL feed emits only auth_failure and blocked events. |
enabled | bool | false | Set to true to activate CrowdSec decision polling. |
lapi_url | string | "http://127.0.0.1:8080" | URL of your CrowdSec Local API service. |
api_key | string | — | Bouncer API token obtained in Step 3. |
update_frequency | duration | "10s" | Interval for polling new ban/unban decisions. |
fallback_action | string | "ban" | Strategy when decisions match: ban, throttle, or bypass. |
Step 5: Full-Stack Docker Compose Deployment
Run both services in a unified Docker Compose file with shared log and data volumes:
services: # TCP Warden tcp-warden: image: ghcr.io/routewarden/tcp-warden:latest container_name: tcp-warden restart: unless-stopped network_mode: host volumes: - tcp-warden-config:/etc/routewarden - tcp-warden-plugins:/var/lib/routewarden/plugins - tcp-warden-data:/var/lib/routewarden - tcp-warden-logs:/var/log/routewarden environment: - ROUTEWARDEN_LOG_LEVEL=warn - CROWDSEC_API_KEY=${CROWDSEC_API_KEY} # CrowdSec Security Engine crowdsec: image: crowdsecurity/crowdsec:latest container_name: crowdsec restart: unless-stopped environment: - COLLECTIONS=crowdsecurity/linux volumes: - ./crowdsec/acquis.yaml:/etc/crowdsec/acquis.d/tcp-warden.yaml:ro - ./crowdsec/parsers:/etc/crowdsec/parsers:ro - ./crowdsec/scenarios:/etc/crowdsec/scenarios:ro - tcp-warden-logs:/var/log/routewarden:ro - crowdsec-db:/var/lib/crowdsec/data - crowdsec-config:/etc/crowdsec ports: - "8080:8080"volumes: tcp-warden-config: tcp-warden-plugins: tcp-warden-data: tcp-warden-logs: crowdsec-db: crowdsec-config:Start the stack:
docker compose up -dStep 6: Verify the Integration
Verify that TCP Warden successfully connects to CrowdSec LAPI and receives active decisions:
# 1. Verify TCP Warden health & CrowdSec statuscurl -s http://127.0.0.1:9091/health# Expected output contains:# {"status":"ok","version":"1.2.1","crowdsec":{"status":"healthy","decisions":1250,"update_frequency":"10s"}}# 2. List registered bouncers in CrowdSecdocker compose exec crowdsec cscli bouncers list# 3. View active decision / ban records in CrowdSecdocker compose exec crowdsec cscli decisions listIn the Management Dashboard or via curl http://127.0.0.1:9091/health, the health response will show the active CrowdSec connection status:
{ "status": "ok", "version": "1.2.1", "crowdsec": { "status": "healthy", "decisions": 1250, "update_frequency": "10s" }}Architectural Deep Dive & Comparison
Want to understand the fundamental architectural differences between TCP Warden and CrowdSec, and why they work best together? Check out the TCP Warden FAQ & Comparison Guide.