CrowdSec Bouncer Cheat Sheet
Overview
CrowdSec Bouncers are remediation components that enforce decisions made by the CrowdSec Security Engine. When CrowdSec detects malicious behavior (brute force, scanning, crawling, CVE exploitation), it generates alerts and decisions. Bouncers consume these decisions and take action — blocking IPs at the firewall level, presenting CAPTCHA challenges, rate limiting requests, or modifying application behavior. Bouncers query the CrowdSec Local API (LAPI) to fetch active decisions and apply them in real-time.
The bouncer ecosystem covers multiple enforcement points: firewall bouncers (iptables, nftables, ipset, pf) block at the network layer, reverse proxy bouncers (Nginx, Traefik, HAProxy, Caddy) block at the application layer, and WAF bouncers integrate with web application firewalls. CrowdSec also provides the CrowdSec Blocklist Mirror for integrating with third-party firewalls that support blocklist feeds. Bouncers can operate in multiple modes — blocking (deny), captcha (challenge), or allow/passthrough — and support IP, range, AS, and country-level decisions from both local detections and the CrowdSec Central API threat intelligence feed.
Installation
Firewall Bouncer (iptables/nftables)
# Install via package manager
curl -s https://install.crowdsec.net | sudo bash
sudo apt install crowdsec-firewall-bouncer-iptables
# or for nftables
sudo apt install crowdsec-firewall-bouncer-nftables
# Register bouncer with CrowdSec LAPI
sudo cscli bouncers add firewall-bouncer
# Save the displayed API key
# Configure the bouncer
sudo nano /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
# Start the bouncer
sudo systemctl enable --now crowdsec-firewall-bouncer
Nginx Bouncer
# Install the Nginx bouncer
sudo apt install crowdsec-nginx-bouncer
# Register bouncer
sudo cscli bouncers add nginx-bouncer
# Configure with the returned API key
# Restart Nginx to load the module
sudo systemctl restart nginx
Traefik Bouncer (Docker)
# docker-compose.yml
services:
traefik-bouncer:
image: fbonalair/traefik-crowdsec-bouncer:latest
environment:
- CROWDSEC_BOUNCER_API_KEY=<your-api-key>
- CROWDSEC_AGENT_HOST=crowdsec:8080
restart: unless-stopped
networks:
- traefik
WordPress / PHP Bouncer
# Install via Composer
composer require crowdsec/bouncer
# Or install WordPress plugin from WP admin panel
# Search for "CrowdSec" in Plugins > Add New
Core Commands
Bouncer Management
| Command | Description |
|---|---|
cscli bouncers add <name> | Register a new bouncer |
cscli bouncers list | List all registered bouncers |
cscli bouncers delete <name> | Remove a bouncer |
cscli decisions list | List all active decisions |
cscli decisions add --ip <ip> --type ban | Manually ban an IP |
cscli decisions delete --ip <ip> | Remove a ban decision |
# List registered bouncers
sudo cscli bouncers list
# Check bouncer connectivity
sudo cscli bouncers list -o json | jq '.[] | {name, last_pull}'
# Add bouncer and get API key
sudo cscli bouncers add my-nginx-bouncer
# View active decisions being enforced
sudo cscli decisions list
# Manually ban an IP for 24 hours
sudo cscli decisions add --ip 192.168.1.100 --duration 24h --type ban --reason "manual block"
# Ban a CIDR range
sudo cscli decisions add --range 10.0.0.0/24 --duration 48h --type ban --reason "scanning activity"
# Add captcha decision instead of ban
sudo cscli decisions add --ip 192.168.1.100 --duration 4h --type captcha --reason "suspicious behavior"
# Remove specific decision
sudo cscli decisions delete --ip 192.168.1.100
# Remove all decisions
sudo cscli decisions delete --all
Configuration
Firewall Bouncer Configuration
# /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
mode: iptables # iptables, nftables, ipset, pf
update_frequency: 10s
daemonize: true
log_mode: file
log_dir: /var/log/
log_level: info
api_url: http://localhost:8080/
api_key: <your-bouncer-api-key>
# Disable IPv6 if not needed
disable_ipv6: false
# iptables-specific settings
iptables_chains:
- INPUT
- FORWARD
# nftables-specific settings
nftables:
ipv4:
table: crowdsec
chain: crowdsec-chain
set: crowdsec-blacklists
ipv6:
table: crowdsec6
chain: crowdsec6-chain
set: crowdsec6-blacklists
# Deny action (DROP or REJECT)
deny_action: DROP
deny_log: false
deny_log_prefix: "crowdsec: "
# Blacklist type
blacklists_ipv4: crowdsec-blacklists
blacklists_ipv6: crowdsec6-blacklists
Nginx Bouncer Configuration
# /etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf
API_URL=http://127.0.0.1:8080
API_KEY=<your-bouncer-api-key>
# Cache configuration
CACHE_EXPIRATION=1
CACHE_SIZE=1000
# Bouncer mode
BOUNCING_ON_TYPE=ban # ban, captcha, all
# Ban template
BAN_TEMPLATE_PATH=/var/lib/crowdsec/lua/templates/ban.html
# Captcha configuration
CAPTCHA_PROVIDER=recaptcha # recaptcha, hcaptcha, turnstile
CAPTCHA_SITE_KEY=<your-site-key>
CAPTCHA_SECRET_KEY=<your-secret-key>
# Exclusions
EXCLUDE_LOCATION=/health,/api/status
# SSL verification
SSL_VERIFY=true
Nginx Server Block Integration
# /etc/nginx/conf.d/crowdsec.conf
lua_shared_dict crowdsec_cache 50m;
lua_package_path '/usr/lib/crowdsec/lua/?.lua;;';
init_by_lua_block {
cs = require "crowdsec"
local ok, err = cs.init("/etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf", "crowdsec-nginx-bouncer/v1.0")
if ok == nil then
ngx.log(ngx.ERR, "[Crowdsec] " .. err)
error()
end
ngx.log(ngx.ALERT, "[Crowdsec] Initialization done")
}
access_by_lua_block {
local cs = require "crowdsec"
cs.Allow(ngx.var.remote_addr)
}
Advanced Usage
Blocklist Mirror
# Install blocklist mirror for third-party firewall integration
sudo apt install crowdsec-blocklist-mirror
# Configure mirror
sudo nano /etc/crowdsec/bouncers/crowdsec-blocklist-mirror.yaml
# /etc/crowdsec/bouncers/crowdsec-blocklist-mirror.yaml
crowdsec_config:
lapi_key: <your-api-key>
lapi_url: http://localhost:8080
listen_uri: 0.0.0.0:41412
tls:
cert_file: ""
key_file: ""
blocklists:
- format: plain_text # plain_text, mikrotik, f5
path: /security/blocklist
authentication:
type: basic
user: admin
password: secretpassword
# Fetch blocklist from mirror
curl http://localhost:41412/security/blocklist
# Use with external firewall (e.g., pfSense, OPNsense)
# Configure firewall to pull from: http://crowdsec-host:41412/security/blocklist
Custom Ban Pages
<!-- /var/lib/crowdsec/lua/templates/ban.html -->
<!DOCTYPE html>
<html>
<head>
<title>Access Denied</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
.container { max-width: 600px; margin: 0 auto; }
h1 { color: #e74c3c; }
</style>
</head>
<body>
<div class="container">
<h1>Access Denied</h1>
<p>Your IP address has been blocked due to suspicious activity.</p>
<p>If you believe this is an error, contact support.</p>
</div>
</body>
</html>
Monitoring Bouncer Performance
# Check firewall bouncer status
sudo systemctl status crowdsec-firewall-bouncer
# View bouncer logs
sudo tail -f /var/log/crowdsec-firewall-bouncer.log
# Check iptables rules created by bouncer
sudo iptables -L INPUT -n | grep -i crowdsec
sudo ipset list crowdsec-blacklists | head -20
# Count blocked IPs
sudo ipset list crowdsec-blacklists | wc -l
# Check nftables rules
sudo nft list table inet crowdsec
# Monitor decision sync
sudo cscli bouncers list -o json | jq '.[].last_pull'
Multi-Server Deployment
# On central LAPI server
sudo cscli bouncers add edge-bouncer-01
sudo cscli bouncers add edge-bouncer-02
# On edge servers, configure bouncer to point to central LAPI
# /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
# api_url: http://central-lapi:8080/
# api_key: <edge-specific-key>
Troubleshooting
| Issue | Solution |
|---|---|
| Bouncer not pulling decisions | Check API key and URL in config, verify LAPI is running: cscli lapi status |
| IPs not being blocked | Verify firewall bouncer is running: systemctl status crowdsec-firewall-bouncer |
| False positive blocks | Remove decision: cscli decisions delete --ip <ip>, add to whitelist |
| Nginx bouncer 500 errors | Check Lua module installation and config file path |
| High memory usage | Reduce CACHE_SIZE or update_frequency in bouncer config |
| Bouncer registration fails | Ensure LAPI is accessible on port 8080, check firewall rules |
| ipset errors | Verify ipset module is loaded: lsmod | grep ip_set |
| Decisions not syncing | Check time synchronization between LAPI and bouncer hosts |