1. The role of a bouncer #
Enforcing decisions.
The principle #
A bouncer (remediation component) enforces LAPI decisions. It authenticates with a key generated by cscli. The engine and bouncers can be on different machines.
sudo cscli bouncers add mon-bouncer
sudo cscli bouncers list
sudo cscli bouncers delete mon-bouncerThe key is shown only once. Keep it in a secrets manager. Use one key per bouncer, so you can revoke just one.
Where to block? #
| Bouncer | Level | Keep in mind |
|---|---|---|
| Firewall | Kernel | Protects all ports: SSH, SMTP, databases |
| Traefik | Proxy | Community plugin, see the dedicated lesson |
| Nginx, OpenResty, Apache | Web server | Ban, captcha and AppSec WAF |
| HAProxy SPOA | Proxy | Replaces the old deprecated Lua bouncer |
| Cloudflare, Fastly, AWS WAF | CDN, WAF | Blocks before your servers |
| Blocklist Mirror | Network | Publishes a list for pfSense, Fortinet, MikroTik… |
| WordPress, PHP, Magento | Application | Without root access |
The full list is on the Hub. The Ingress Nginx bouncer is also deprecated.
Live or stream? #
In a real test with the Traefik plugin, a freshly banned IP kept passing in live mode while its “allowed” status stayed cached. In stream mode, it was blocked at the next sync.
The decisions API #
All bouncers use this API. An IP with no decision returns null; without a valid key, the response is 403.
curl -s -H "X-Api-Key: $KEY" "http://127.0.0.1:8080/v1/decisions?ip=203.0.113.50"
# [{"duration":"3h59m44s","origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"203.0.113.50"}]
curl -s -H "X-Api-Key: $KEY" "http://127.0.0.1:8080/v1/decisions/stream?startup=true"
# {"new": [...], "deleted": [...]}2. The firewall bouncer #
Installation, configuration and checks.
Install #
sudo apt install crowdsec-firewall-bouncer-nftables
# ou : crowdsec-firewall-bouncer-iptables
sudo systemctl status crowdsec-firewall-bouncer
sudo cscli bouncers listOn the same machine as the LAPI, the package creates its key by itself. Otherwise, generate it and copy it into the configuration.
Configure #
The file is /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml. Put your settings in a .yaml.local file so they survive upgrades.
mode: nftables
update_frequency: 10s
log_mode: file
log_dir: /var/log/
log_level: info
api_url: http://127.0.0.1:8080/
api_key: YOUR_KEY
disable_ipv6: false
deny_action: DROP
deny_log: false
nftables:
ipv4:
enabled: true
set-only: false
table: crowdsec
chain: crowdsec-chain
priority: -10
ipv6:
enabled: true
set-only: false
table: crowdsec6
chain: crowdsec6-chain
priority: -10| Option | Role |
|---|---|
mode | nftables, iptables, ipset, pf |
update_frequency | Update frequency |
deny_action | DROP (default) or REJECT |
iptables_chains | Chains to protect. Add DOCKER-USER for published container ports |
set-only | You manage the rules, the bouncer only fills the set |
Check #
sudo cscli decisions add --ip 203.0.113.50 --duration 10m
sudo nft list table ip crowdsec
sudo cscli metrics show bouncers
sudo cscli decisions delete --ip 203.0.113.50table ip crowdsec {
counter crowdsec-blacklists-cscli {
packets 3 bytes 180
}
set crowdsec-blacklists-cscli {
type ipv4_addr
flags timeout
elements = { 203.0.113.50 timeout 9m58s expires 9m50s }
}
}Do not ban yourself. Before testing, add your admin address to an allowlist and keep console access at your hosting provider.
Sources #
Commands and blocking verified on CrowdSec 1.8.2 and firewall bouncer 0.0.38 in nftables mode.
