Files
crowdsec-bouncer-traefik-pl…/examples/custom-captcha
maxlerebourgandGitHub 4ab4f3f183 Transform banTemplate to add blocking reason and client IP (#290)
*  Transform banTemplate to add blocking reason

* 🍱 fix test

* 🍱 fix lint

* 🍱 fix test

* 🍱 fix lint

* 🍱 fix lint

* 🍱 add doc and fix lint

* 🍱 fix lint

* 🍱 fix lint

* 🍱 fix lint

* 🍱 fix lint

* 🍱 fix lint

* 🍱 lint html

* 🍱 fix comments + fix wicketpeeker readme

* 🍱 Give ClientIP in ban page

* 🍱 fix test
2025-11-15 10:42:14 +01:00
..
2025-09-01 19:41:45 +02:00

Example

Read the example captcha before this, to better understand what is done here.

Traefik configuration

The minimal configuration is defined below to implement custom captcha.
This documentation use https://github.com/a-ve/wicketkeeper, a self-hosted captcha provider that have a similar API than big providers.

Minimal API requirement:

  • the JS file URL to load the captcha on the served captcha.html

  • the HTML className to tell to the JS where to display the challenge

  • the verify URL endpoint to send the field response from the captcha with content-type: application/x-www-form-urlencoded

  • the name of the field when you POST the resolved captcha to Traefik

  • the JS file need to respect the data-callback on the div that contains the captcha if you use our template, but you can customize it by your side

  traefik:
    ...
    labels:
      # Choose captcha provider
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaProvider=custom"
      # Define captcha grace period seconds
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaGracePeriodSeconds=1800"
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaCustomJsURL=http://captcha.localhost:8000/fast.js"
      # Inside Traefik container the plugin must be able to reach wicketkeeper service so we can go through a Traefik localhost
      # domain which would resolve traefik itself and the port for the dashboard
      - "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"
      # Define captcha HTML file path
      - "traefik.http.middlewares.crowdsec.plugin.bouncer.captchaHTMLFilePath=/captcha.html"
wicketkeeper:
  image: ghcr.io/a-ve/wicketkeeper:latest
  user: root
  ports:
    - "8080:8080"
  environment:
    - LISTEN_PORT=8080
    - REDIS_ADDR=redis:6379
    - DIFFICULTY=4
    - ALLOWED_ORIGINS=*
    - PRIVATE_KEY_PATH=/data/wicketkeeper.key
  volumes:
    - ./data:/data
  depends_on:
    - redis
redis:
  image: redis/redis-stack-server:latest
<div id="captcha" class="{{ .FrontendKey }}" data-sitekey="{{ .SiteKey }}" data-callback="captchaCallback" data-challenge-url="http://captcha.localhost:8000/v0/challenge">

Exemple navigation

We can try to query normally the whoami server:

curl http://localhost:8000/foo

We can try to ban ourself and retry.

docker exec crowdsec cscli decisions add --ip 10.0.0.20 -d 10m --type captcha

To play the demo environment run:

make run_custom_captcha