RousselTMLEARNING

Article · CrowdSec: From Discovery to Expertise

Protecting Traefik

1. The principle #

One plugin and two roles.

Two separate integrations #

Traefik and CrowdSec work together in two ways:

  • Detection: CrowdSec reads Traefik access logs thanks to the crowdsecurity/traefik collection.
  • Blocking: the community plugin crowdsec-bouncer-traefik-plugin queries the LAPI and returns 403 to banned addresses.

The client goes through a CDN then Traefik, whose middleware queries the Local API before forwarding to the application

2. Setting it up #

Static and dynamic configuration.

The key #

docker compose exec crowdsec cscli bouncers add traefik
# ou, côté image CrowdSec : BOUNCER_KEY_traefik=une-cle-longue-et-aleatoire

Static configuration #

entryPoints:
  web:
    address: ":80"
    forwardedHeaders:
      trustedIPs:          # only if a proxy or CDN is in front of Traefik
        - 10.0.0.0/8
accessLog:
  filePath: /var/log/traefik/access.log
providers:
  file:
    filename: /etc/traefik/dynamic.yml
experimental:
  plugins:
    bouncer:
      moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
      version: v1.8.1

Restart Traefik: it downloads the plugin at startup, so it needs Internet access at that point.

Dynamic configuration #

http:
  middlewares:
    crowdsec:
      plugin:
        bouncer:
          enabled: true
          crowdsecMode: stream
          updateIntervalSeconds: 15
          crowdsecLapiScheme: http
          crowdsecLapiHost: crowdsec:8080
          crowdsecLapiKey: YOUR_KEY
          forwardedHeadersTrustedIPs:
            - 10.0.0.0/8
  routers:
    app:
      rule: "Host(`app.example.com`)"
      entryPoints: [web]
      service: app
      middlewares: [crowdsec]
  services:
    app:
      loadBalancer:
        servers:
          - url: "http://app:8080"

With Docker labels:

services:
  whoami:
    image: traefik/whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
      - "traefik.http.routers.whoami.middlewares=crowdsec@docker"
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecmode=stream"
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapihost=crowdsec:8080"
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=YOUR_KEY"

The plugin modes #

ModeHow it works
noneOne LAPI request per incoming request
liveSame, with a per-IP cache of defaultDecisionSeconds (60 s). Default mode
streamLocal cache of banned IPs, synced every updateIntervalSeconds (60 s). Recommended
aloneNo local LAPI: list from the CAPI
appsecAppSec inspection only

3. The real IP trap #

Behind a CDN or load balancer.

The symptom #

Everything seems to work, but a banned IP keeps passing. We reproduced it: without entrypoint trust, Traefik overwrites X-Forwarded-For. The plugin sees the proxy's address, never the client's.

Tested configurationBanned IP
Without forwardedHeaders.trustedIPs on the entrypoint200: no block
With it, in stream mode403 after the sync
With it, decision deleted200 again

The fix #

You must declare the trusted proxy in two places: forwardedHeaders.trustedIPs on the entrypoint, and forwardedHeadersTrustedIPs in the plugin. Limit these ranges to your real proxies: a client must not be able to spoof its address.

To exclude your internal network from checks, use clientTrustedIPs.

4. Going further #

Detection and WAF.

Reading Traefik logs #

filenames:
  - /var/log/traefik/access.log
labels:
  type: traefik
docker compose exec crowdsec cscli collections install crowdsecurity/traefik
docker compose exec crowdsec cscli metrics show acquisition parsers

Enabling AppSec #

crowdsecAppsecEnabled: true
crowdsecAppsecHost: crowdsec:7422
crowdsecAppsecFailureBlock: true
crowdsecAppsecUnreachableBlock: true
Mind availability. With crowdsecAppsecUnreachableBlock: true (the default), the site is blocked if AppSec is unreachable. Choose this behavior knowingly.

Sources #

Blocking verified on Traefik 3.7.17, plugin 1.8.1 and CrowdSec 1.8.2.

📄 Protecting Traefik with CrowdSec: the bouncer plugin →

My progress

  • ⏱ Estimated time : ≈ 11 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, ...

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

Block at the CDN with Cloudflare Workers, feed pfSense or MikroTik with Blocklist Mirror, protect...

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

Decisions, profiles, allowlists and AppSec in CrowdSec

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

CrowdSec: understanding the collaborative firewall

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

Traefik : sécuriser et transformer les requêtes avec les middlewares (BasicAuth, ForwardAuth…)

Les middlewares Traefik modifient les requêtes et réponses entre le routeur et le service : authe...

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

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

Traefik : les logs (journaux applicatifs et access logs)

Configurer les deux journaux de Traefik : le journal de fonctionnement (niveaux, format) et les a...

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!