Skip to content

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:

  1. 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.
  2. 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.
Inbound Client TCP Connection TCP Warden L4 Pipeline Zero-copy bidirectional forwarding & protocol inspection hooks Step A: CrowdSec Local Cache Check • In-memory query with zero network overhead • Checks if client IP exists in active CrowdSec decision list IP Match (Banned) Clean IP Instant Ban Connection dropped or socket tarpitted Upstream Service Zero-copy pass to target backend socket Step B: Protocol & Auth Monitoring • Plugin inspectors evaluate authentication handshakes • Detects password failures, scans, and command anomalies Emits Security Event Structured JSONL Audit Log Written to /var/log/routewarden/tcp-warden.jsonl CrowdSec Daemon & LAPI • RouteWarden scenarios detect brute-force patterns • Pushes ban decision to CrowdSec Local API (LAPI) • TCP Warden polls LAPI and updates local cache

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-tcp

Built-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" >> .env

Step 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"
FieldTypeDefaultDescription
global.log_levelstring"warn"Defaults to "warn" so the JSONL feed emits only auth_failure and blocked events.
enabledboolfalseSet to true to activate CrowdSec decision polling.
lapi_urlstring"http://127.0.0.1:8080"URL of your CrowdSec Local API service.
api_keystring—Bouncer API token obtained in Step 3.
update_frequencyduration"10s"Interval for polling new ban/unban decisions.
fallback_actionstring"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 -d

Step 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 list

In 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.

Released under the MIT License.