CrowdSec Bouncer Traefik Plugin

repository·main·Indexed 21 days ago

https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin

A Traefik middleware plugin that integrates with CrowdSec to block malicious traffic. It supports AppSec WAF features, captcha remediation (hcaptcha, recaptcha, turnstile, and custom providers), custom ban pages with dynamic variables, and configuration for trusting forwarded headers when Traefik is behind a proxy.

Tokens
12.3K
Snippets
43
Records
54
Agent score
74%

What's inside crowdsec-bouncer-traefik-plugin

  1. Understand the plugin's global singleton behavior

    main

    The Crowdsec Bouncer Traefik plugin is designed such that only one instance of the plugin is possible within a Traefik instance. While you can declare multiple middlewares, they share global behaviors and configuration parameters:

    • Shared Cache: All services protected by any instance of the plugin share the same cache. If an IP is banned in one middleware, it is denied across all services protected by the plugin.
    • Cache Instantiation: If you define different caches for different middlewares, only the first one to be instantiated will be bound to the Crowdsec stream.
    • Parameter Alignment: If you use multiple middlewares, key parameters like MetricsUpdateIntervalSeconds, CrowdsecMode, and CrowdsecAppsecEnabled must be aligned across them.
  2. Use AppSec for virtual patching and WAF capabilities

    main

    Starting from plugin version 1.2.0 and Crowdsec 1.6.0, the plugin supports the AppSec feature. This allows you to:

    • Implement low-effort virtual patching.
    • Use legacy ModSecurity rules.
    • Combine classic WAF benefits with advanced CrowdSec behavior detection.

    To use this, set the CrowdsecMode to appsec. This mode disables standard IP reputation checks and focuses on inspecting the request content for malicious patterns.

  3. Understand the testing environment architecture

    main

    The example environment simulates a production-like setup with the following components:

    • Traefik: Installed as a systemd service. It listens on port 80 (web) and port 8081 (dashboard). It acts as the entry point for traffic.
    • Crowdsec: Running on port 8080. The Plugin/Bouncer authenticates with the Crowdsec Local API.
    • Whoami: A service installed as a systemd service on port 9000. It is accessible via Traefik on port 80 at any domain/path (e.g., curl http://localhost:80/test).
    • Security: The Plugin/Bouncer uses certificates to validate server certificates and authenticate with the Crowdsec Local API. Certificates are automatically generated during the Vagrant provision step.
  4. Configure remediation types: ban vs captcha

    main

    The plugin supports two types of remediation for malicious actors:

    1. ban: The user is immediately blocked in Traefik with an HTTP 403 response.
    2. captcha: The user is redirected to a challenge page.

    Supported captcha providers include:

    • hcaptcha
    • recaptcha
    • turnstile (Cloudflare)
    • custom/wicketkeeper

    Upon successful captcha completion, the user's IP is marked as 'clean' in the cache for a duration specified by captchaGracePeriodSeconds before a new challenge is required.

  5. Separate LAPI and Appsec TLS configuration

    main

    By default, LAPI and Appsec configurations share settings. To use different TLS configurations for the LAPI and the Appsec component, you can map LAPI-specific variables to Appsec.

    Replace the prefix CrowdsecLapi... with CrowdsecAppsec... for the desired settings. You must also explicitly set CrowdsecAppsecScheme to either HTTP or HTTPS to enable the separate configuration.

  6. How to use the custom captcha HTML template

    main

    When providing a custom captcha.html file, you can use the following template structure. The plugin injects {{ .FrontendKey }}, {{ .SiteKey }}, and other attributes into the div. Ensure your JS implementation respects the data-callback attribute to handle the captcha resolution.

    <div id="captcha" class="{{ .FrontendKey }}" data-sitekey="{{ .SiteKey }}" data-callback="captchaCallback" data-challenge-url="http://captcha.localhost:8000/v0/challenge">
  7. Understand Crowdsec Bouncer Traefik plugin modes

    main

    The plugin operates in five distinct modes (CrowdsecMode) depending on your performance requirements and infrastructure setup:

    • none: Every request calls the Crowdsec LAPI. If the IP is on the ban list, the user receives an HTTP 403. Use this for simple setups where latency is not a primary concern.
    • live: Uses a local cache to reduce LAPI requests. It stores the status of queried IPs for a duration defined by DefaultDecisionSeconds. If an IP is not in the cache, it queries the LAPI and then caches the result.
    • stream: Recommended for performance. The plugin maintains a local cache of only Banned IPs. It synchronizes with the Crowdsec LAPI every UpdateIntervalSeconds (default 60s). Every request hits the local cache for near-instant decisions.
    • alone: Standalone mode that fetches blacklisted IPs from the Crowdsec CAPI (Central API) instead of a local LAPI. The cache updates every 2 hours. This can work without a local Crowdsec service.
    • appsec: Disables standard IP checking and instead applies Crowdsec AppSec checking (virtual patching and ModSecurity rule support). This is intended for use when IP checking is already handled at the Firewall level.
  8. Understand the Captcha vs Ban workflow

    main

    The plugin handles different Crowdsec decision types differently:

    • No Decision: The request is forwarded to the webserver normally.
    • Captcha Decision: The plugin intercepts the request and serves the HTML file defined in captchaHTMLFilePath. Once the user completes the captcha successfully, the plugin caches the IP as 'clean' for the duration of captchaGracePeriodSeconds.
    • Ban Decision: The plugin immediately returns an HTTP 403 error. No captcha is shown.
  9. Enable the AppSec WAF feature in Traefik

    main

    To enable the CrowdSec AppSec (Web Application Firewall) feature via the Traefik plugin, you must configure the middleware labels to enable the feature and specify the location of the AppSec engine.

    Note that this requires CrowdSec to be configured with virtual patching and custom rules enabled. The Traefik instance itself only needs to know the address of the AppSec engine.

    labels:
      - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecappsecenabled=true"
      - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecappsechost=crowdsec:7422"
  10. Configure a custom captcha provider in Traefik

    main

    To use a custom captcha provider instead of the default, set the captchaProvider to custom in your Traefik middleware labels. You must provide the JavaScript URL for the captcha, the validation endpoint, the key name, and the response field name.

    Minimal API Requirements for your provider:

    • A JS file URL to load the captcha on the served captcha.html.
    • An HTML className to tell the JS where to display the challenge.
    • A verify URL endpoint that accepts a POST request with the field response using content-type: application/x-www-form-urlencoded.
    • The name of the field used when POSTing the resolved captcha to Traefik.
    • If using the provided template, the JS must respect the data-callback attribute on the div containing the captcha (though this can be customized).
    traefik:
      labels:
        - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaProvider=custom"
        - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaGracePeriodSeconds=1800"
        - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaCustomJsURL=http://captcha.localhost:8000/fast.js"
        - "traefik.http.middlewares.crowdsec.plugin.bouncer.CaptchaCustomValidateURL=http://wicketkeeper:8080/v0/siteverify"
        - "traefik.http.middlewares.crowdsec.plugin.bouncer.CaptchaCustomKey=wicketkeeper"
        - "traefik.http.middlewares.crowdsec.plugin.bouncer.CaptchaCustomResponse=wicketkeeper_solution"
        - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaHTMLFilePath=/captcha.html"
  11. Authenticate with CrowdSec LAPI using TLS certificates

    main

    For more secure environments, you can use client certificates for mTLS authentication. This requires crowdsecLapiScheme to be set to https.

    Options for verifying the LAPI server certificate:

    • Publicly trusted certificate: Leave crowdsecLapiTLSCertificateAuthority empty and crowdsecLapiTLSInsecureVerify as false. The plugin uses the host's system trust store.
    • Private/self-signed CA: Set crowdsecLapiTLSCertificateAuthority (or crowdsecLapiTLSCertificateAuthorityFile) to the PEM-encoded CA.
    • Skip verification: Set crowdsecLapiTLSInsecureVerify to true (not recommended for production).

    Client Certificate Parameters:

    • crowdsecLapiTLSCertificateBouncer: PEM-encoded client Certificate of the Bouncer.
    • crowdsecLapiTLSCertificateBouncerKey: PEM-encoded client private key of the Bouncer.
  12. Configure the CrowdSec Bouncer plugin to trust forwarded headers from a proxy

    main

    When Traefik is behind another proxy service (such as Cloudflare), you must configure both Traefik and the CrowdSec Bouncer plugin to trust the forwarded headers from that proxy. This ensures Traefik and the plugin correctly identify the actual client IP address instead of the proxy's IP.

    1. Configure Traefik Entrypoints: Set the trustedips for your entrypoint to include the IP of your front proxy.
    2. Configure the Plugin Middleware: Set the forwardedheaderstrustedips option in your middleware configuration to the same proxy IP.
    # 1. Configure Traefik entrypoint
    --entrypoints.web.forwardedheaders.trustedips=172.21.0.5
    
    # 2. Configure the CrowdSec Bouncer plugin middleware
    traefik.http.middlewares.crowdsec1.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5