RousselTMLEARNING

Article · CrowdSec: From Discovery to Expertise

Cloudflare, network devices and custom bouncer

1. Cloudflare #

Block before your servers.

The principle #

The bouncer deploys Cloudflare Workers. Decisions are stored in a Cloudflare KV, and the Worker applies a ban or captcha (Turnstile) to each request.

sudo apt install crowdsec-cloudflare-worker-bouncer
sudo cscli -oraw bouncers add cloudflarebouncer
sudo crowdsec-cloudflare-worker-bouncer -g CLOUDFLARE_TOKEN -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
# Then copy the LAPI key into the file
sudo systemctl enable --now crowdsec-cloudflare-worker-bouncer

The Cloudflare token notably needs Turnstile, Workers KV Storage, Workers Scripts and Workers Routes write access, and Account Analytics, DNS and Zone read access.

Precautions #

  • Fail open. Switch the created routes to Fail open in Cloudflare: otherwise, an error or exceeded quota shows an error page to your visitors.
  • Quotas. The free plan limits KV writes and Workers requests: a paid Workers plan is preferable.
  • Real IP. Your server must log the visitor's address, not Cloudflare's, otherwise CrowdSec would ban Cloudflare.

2. Network devices #

Publishing a list: Blocklist Mirror.

Blocklist Mirror #

Blocklist Mirror publishes decisions over HTTP for pfSense, MikroTik, F5 and Juniper

sudo apt install crowdsec-blocklist-mirror
sudo cscli -oraw bouncers add blocklistMirror
crowdsec_config:
  lapi_url: http://127.0.0.1:8080
  lapi_key: ${LAPI_KEY}
  update_frequency: 10s
  supported_decisions_types:
    - ban
  only_include_decisions_from:
    - crowdsec
    - cscli
  listen_uri: 127.0.0.1:41412

Secure access: authentication.type accepts basic or ip_based, and the tls section enables HTTPS. Available formats are plain_text, mikrotik, F5 and juniper.

3. Kubernetes and applications #

Other environments.

Kubernetes #

On Kubernetes, CrowdSec is installed with its Helm chart and reads pod logs. Blocking happens at the Ingress or Gateway: Traefik middleware, Envoy or HAProxy bouncer. The Ingress Nginx bouncer is deprecated: do not use it for a new deployment.

helm repo add crowdsec https://crowdsecurity.github.io/helm-charts
helm repo update
helm install crowdsec crowdsec/crowdsec -n crowdsec --create-namespace -f values.yaml

WordPress, PHP, Magento #

On hosting without root access, an application bouncer is still possible: WordPress extension, Magento module, PHP library. It needs a reachable LAPI and a key. Blocking comes late, after the application starts: prefer an upstream bouncer if you can.

4. Writing your bouncer #

A simple HTTP API.

Stream mode in 25 lines #

A bouncer is only an API client. This script follows decisions: it is up to you to send them to your tool, such as a device or internal service.

#!/usr/bin/env python3
"""Mini bouncer: follows LAPI decisions in stream mode."""
import json, os, time, urllib.request

LAPI = os.environ.get("LAPI_URL", "http://127.0.0.1:8080")
KEY = os.environ["LAPI_KEY"]

def pull(startup):
    url = f"{LAPI}/v1/decisions/stream?startup={'true' if startup else 'false'}"
    req = urllib.request.Request(url, headers={"X-Api-Key": KEY})
    with urllib.request.urlopen(req, timeout=10) as r:
        return json.load(r)

banned, startup = set(), True
while True:
    data = pull(startup)
    startup = False
    for d in data.get("new") or []:
        if d["type"] == "ban":
            banned.add(d["value"])
            print("BAN", d["value"], d["scenario"], flush=True)
    for d in data.get("deleted") or []:
        banned.discard(d["value"])
        print("LIFTED", d["value"], flush=True)
    time.sleep(10)
sudo cscli bouncers add mon-outil
export LAPI_KEY=...
python3 bouncer.py
# BAN 203.0.113.50 crowdsecurity/ssh-bf

The first call, with startup=true, returns all active decisions; the next ones, only changes. Filter on type, because a decision can also be a captcha.

Sources #

Script and API tested on CrowdSec 1.8.2. Cloudflare, Blocklist Mirror and Kubernetes: from the official documentation, not run for this article.

📄 CrowdSec bouncers: Cloudflare, network devices, Kubernetes and custom bouncer →

My progress

  • ⏱ Estimated time : ≈ 9 min

Sign in to track your progress and take notes. Sign in

💬 Ask a question

Recommended Articles

CrowdSec bouncers: principles and firewall bouncer

Understanding CrowdSec bouncers: where to block, live and stream modes, API keys, decisions API, ...

Protecting Traefik with CrowdSec: the bouncer plugin

Setting up the CrowdSec bouncer in Traefik: plugin, middleware, stream and live modes, real IP be...

CrowdSec: understanding the collaborative firewall

What CrowdSec is, how it detects and blocks attacks: Security Engine, parsers, scenarios, Local A...

CrowdSec bouncers for Nginx, Apache and HAProxy

Setting up CrowdSec bouncers for Nginx, OpenResty, Apache and HAProxy SPOA: configuration, block ...

Les plugins Traefik : l'exemple de CrowdSec pour bloquer les attaques

Étendre Traefik avec des plugins (catalogue officiel, interpréteur Yaegi), puis protéger ses appl...

CrowdSec observability: banned IPs, blocked attacks, Prometheus and Grafana

Monitoring CrowdSec: cscli metrics, banned IPs, detected attacks, volume blocked by bouncers, Pro...

CrowdSec or Fail2ban: what are the differences?

Comparing CrowdSec and Fail2ban: detection, blocking, sharing, performance, multi-server, and how...

Installing and configuring CrowdSec: packages, Docker, acquisition

Install CrowdSec with packages or Docker, understand its files, declare the logs to read, enroll ...

Decisions, profiles, allowlists and AppSec in CrowdSec

Manage decisions with cscli, adapt block duration and type with profiles, avoid false positives w...

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!