RousselTMLEARNING

Observabilité

Bouncers CrowdSec : Cloudflare, équipements réseau, Kubernetes et bouncer sur mesure

Bloquer au CDN avec Cloudflare Workers, alimenter pfSense ou MikroTik avec Blocklist Mirror, protéger Kubernetes et les CMS, et écrire son propre bouncer.

1. Cloudflare #

Bloquer avant vos serveurs.

Le principe #

Le bouncer déploie des Cloudflare Workers. Les décisions sont stockées dans un KV Cloudflare, et le Worker applique pour chaque requête un ban ou un captcha (Turnstile).

sudo apt install crowdsec-cloudflare-worker-bouncer
sudo cscli -oraw bouncers add cloudflarebouncer
sudo crowdsec-cloudflare-worker-bouncer -g JETON_CLOUDFLARE -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
# Reportez ensuite la clé de la LAPI dans le fichier
sudo systemctl enable --now crowdsec-cloudflare-worker-bouncer

Le jeton Cloudflare a besoin notamment de Turnstile, Workers KV Storage, Workers Scripts et Workers Routes en écriture, et d'Account Analytics, DNS et Zone en lecture.

Les précautions #

  • Fail open. Passez les routes créées en Fail open dans Cloudflare : sinon, une erreur ou un dépassement de quota affiche une page d'erreur à vos visiteurs.
  • Quotas. Le plan gratuit limite les écritures KV et les requêtes Workers : un abonnement Workers payant est préférable.
  • IP réelle. Votre serveur doit journaliser l'adresse du visiteur, pas celle de Cloudflare, sinon CrowdSec bannirait Cloudflare.

2. Les équipements réseau #

Publier une liste : Blocklist Mirror.

Blocklist Mirror #

Blocklist Mirror publie les décisions en HTTP pour pfSense, MikroTik, F5 et 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

Sécurisez l'accès : authentication.type accepte basic ou ip_based, et la section tls active le HTTPS. Les formats disponibles sont plain_text, mikrotik, F5 et juniper.

3. Kubernetes et applications #

Autres environnements.

Kubernetes #

Sur Kubernetes, CrowdSec s'installe avec son chart Helm et lit les logs des pods. Le blocage se fait à l'Ingress ou à la Gateway : middleware Traefik, bouncer Envoy ou HAProxy. Le bouncer Ingress Nginx est déprécié : ne l'utilisez pas pour un nouveau déploiement.

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 #

Sur un hébergement sans accès root, un bouncer applicatif reste possible : extension WordPress, module Magento, bibliothèque PHP. Il a besoin d'une LAPI joignable et d'une clé. Le blocage arrive tard, après le démarrage de l'application : préférez un bouncer en amont si vous le pouvez.

4. Écrire son bouncer #

Une simple API HTTP.

Le mode stream en 25 lignes #

Un bouncer n'est qu'un client de l'API. Ce script suit les décisions : à vous de les envoyer vers votre outil, comme un équipement ou un service interne.

#!/usr/bin/env python3
"""Mini-bouncer : suit les décisions de la LAPI en mode stream."""
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("LEVÉE", 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

Le premier appel, avec startup=true, renvoie toutes les décisions actives ; les suivants, seulement les changements. Filtrez selon type, car une décision peut aussi être un captcha.

Sources #

Script et API testés sur CrowdSec 1.8.2. Cloudflare, Blocklist Mirror et Kubernetes : d'après la documentation officielle, sans exécution pour cet article.

Articles liés

CrowdSec : comprendre le pare-feu collaboratif

Ce qu'est CrowdSec, comment il détecte et bloque les attaques : Security Engine, parsers, scénarios, Local AP…

CrowdSec ou Fail2ban : quelles différences ?

Comparaison de CrowdSec et Fail2ban : détection, blocage, partage, performances, multi-serveurs, et méthode p…

Installer et configurer CrowdSec : paquets, Docker, acquisition

Installer CrowdSec avec les paquets ou Docker, comprendre ses fichiers, déclarer les logs à lire, enrôler la …

Pour aller plus loin

Soutenir

♥ SOUTENIR

Soutenez RousselTM Learning

Les formations, articles, TP et attestations restent gratuits et sans publicité intrusive. Une contribution libre, du montant de votre choix, finance l’hébergement, les environnements de TP et l’écriture de nouveaux contenus.

Contribuer avec PayPal Montant libre · carte bancaire ou compte PayPalEn savoir plus
QR code PayPal
Ou scannez ce QR code avec votre téléphone

Merci, chaque contribution compte !