Skip to content

hslatman/caddy-crowdsec-bouncer

Repository files navigation

CrowdSec Bouncer for Caddy

Go Report Card License

A Caddy module that blocks malicious traffic based on decisions made by CrowdSec.

Table of Contents

Description

The Caddy CrowdSec Bouncer consists of five components:

  • Caddy App: Responsible for communicating with CrowdSec via the Local API and keeping track of its decisions. It supports both StreamBouncer (HTTP polling) and LiveBouncer (a request is made on every incoming connection).
  • Bouncer HTTP Handler: Checks client IPs of incoming HTTP requests against the decisions stored by the App. Multiple independent HTTP Handlers and Connection Matchers can share the storage exposed by the App.
  • Layer 4 Connection Matcher: Matches TCP and UDP IP addresses against the CrowdSec Local API. Uses the Caddy Layer 4 app.
  • AppSec HTTP Handler: Communicates with an AppSec component configured on your CrowdSec deployment, seamlessly checking incoming HTTP requests against configured rulesets.
  • caddy crowdsec Command: Offers useful Caddy CLI commands for your CrowdSec integration.

What is CrowdSec?

CrowdSec is a free and open source security automation tool that uses local logs and a set of scenarios to infer malicious intent. In addition to operating locally, an optional community integration is also available, through which crowd-sourced IP reputation lists are distributed.

The architecture of CrowdSec is very modular. At its core is the CrowdSec Security Engine, which keeps track of all data and related systems. Bouncers are pieces of software that perform specific actions based on the decisions of the Security Engine.

Usage

Tip

You can find full setup examples in /examples inside this repository.

You can use the bouncer by either building a custom Caddy image with Docker or by fetching the required Go modules directly into your own build.

Note: You will need a recent version of Caddy (v2.7.3+) and Go (1.20+).

Option 1: Docker Build

To include the bouncer in a Docker Image using xcaddy. Create a Dockerfile:

ARG CADDY_VERSION=2

FROM caddy:${CADDY_VERSION}-builder-alpine AS builder

RUN xcaddy build \
    --with github.com/mholt/caddy-l4 \
    --with github.com/caddyserver/transform-encoder \
    --with github.com/hslatman/caddy-crowdsec-bouncer/http@main \
    --with github.com/hslatman/caddy-crowdsec-bouncer/appsec@main \
    --with github.com/hslatman/caddy-crowdsec-bouncer/layer4@main

FROM caddy:${CADDY_VERSION}

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

Option 2: Custom Go Build

If you are compiling outside of Docker, you can fetch the modules using go get:

# get the CrowdSec Bouncer HTTP handler
go get github.com/hslatman/caddy-crowdsec-bouncer/http

# get the CrowdSec layer4 connection matcher (only required for TCP/UDP level blocking)
go get github.com/hslatman/caddy-crowdsec-bouncer/layer4

# get the AppSec HTTP handler (only required for CrowdSec AppSec support)
go get github.com/hslatman/caddy-crowdsec-bouncer/appsec

Configuration

Configuration using a Caddyfile is supported for HTTP handlers and Layer 4 matchers.

Configuration Options

Directive Description Default
api_url The URL of the CrowdSec Local API. http://127.0.0.1:8080/
api_key The API key to authenticate with the Local API. <empty> (required)
disable_streaming Falls back to LiveBouncer mode (queries API per request). false
metrics_interval Interval for pushing metrics to the Local API. 0s (disabled)
enable_caddy_metrics Enables emitting bouncer metrics at Caddy's /metrics endpoint. false
ticker_interval Interval for pulling decisions from the Local API. 60s
enable_hard_fails Caddy fails to start if CrowdSec API is unreachable. false
appsec_url The URL of the CrowdSec AppSec component. <empty> (disabled)
appsec_max_body_bytes Maximum request body size sent to AppSec. 0 (full request)
appsec_max_timeout. Maximum time for request to AppSec component. 2s
appsec_fail_open Ignore AppSec component connection errors. false
enable_caddy_error Propagates decisions as Caddy errors to allow custom error pages. Warning: Ensure handle_errors routes are strictly static to avoid resource exhaustion (DoS). false

Example

{
  debug

  crowdsec {
    api_url http://localhost:8080
    api_key <api_key>
    ticker_interval 15s
    appsec_url http://localhost:7422
    #disable_streaming
    #enable_hard_fails
    #enable_caddy_error
  }

  layer4 {
    localhost:4444 {
      @crowdsec crowdsec
      route @crowdsec {
        proxy {
          upstream localhost:6443
        }
      }
    }
  }
}

localhost:8443 {
  route {
    crowdsec
    respond "Allowed by Bouncer!"
  }
}

localhost:7443 {
  route {
    appsec
    respond "Allowed by AppSec!"
  }
}

localhost:6443 {
  route {
    crowdsec
    appsec
    respond "Allowed by Bouncer and AppSec!"
  }
}

Run the Caddy server

# with a Caddyfile
caddy run --config Caddyfile 

Demo

This repository also contains an example using Docker inside the examples/demo folder. Steps to run this demo are as follows:

# run CrowdSec container
docker compose up -d crowdsec

# add the Caddy bouncer, generating an API key
docker compose exec crowdsec cscli bouncers add caddy-bouncer

# copy and paste the API key in the ./examples/demo/config.json file

# run Caddy; at first run a custom build will be created using xcaddy
docker compose up -d caddy

# tail the logs
docker compose logs -tf

You can then access https://localhost:9443 and https://localhost:8443. The latter is an example of using the Layer 4 App and will simply proxy to port 9443 in this case.

Utilities

When Caddy is built with this module enabled, a new caddy crowdsec command will be enabled. Its subcommands allow you to interact with your CrowdSec integration at runtime using Caddy's Admin API. This is useful to verify the status of your integration, and check if it's configured and working properly. The command requires the Admin API to be reachable from the system it is run from.

Support for the command is currently experimental, and will be improved and extended in future releases. Output of the commands should not be relied upon in automated processes (yet).

Usage

$ caddy crowdsec

Commands related to the CrowdSec integration (experimental)

Usage:
  caddy crowdsec [command]

Available Commands:
  check       Checks an IP to be banned or not
  health      Checks CrowdSec integration health
  info        Shows CrowdSec runtime information
  ping        Pings the CrowdSec LAPI endpoint

Flags:
  -a, --adapter string   Name of config adapter to apply (when --config is used)
      --address string   The address to use to reach the admin API endpoint, if not the default
  -c, --config string    Configuration file to use to parse the admin address, if --address is not used
  -h, --help             help for crowdsec
  -v, --version          version for crowdsec

Use "caddy crowdsec [command] --help" for more information about a command.

Full documentation is available at:
https://caddyserver.com/docs/command-line

Client IP

When your Caddy server is deployed behind a proxy (like a CDN or load balancer), the actual client IP is masked. Starting with v0.3.1, this module relies on Caddy's native logic (introduced in Caddy v2.7.0 via caddy#5104) to determine the correct client IP before checking it against CrowdSec decisions.

Important: Caddy uses the X-Forwarded-For header by default. To trust this header, you must configure the trusted_proxies global directive in your Caddyfile.

You can override the default header using the client_ip_headers directive.

Note: For Caddy versions up to v2.4.6 and older versions of this module, the realip module is required.

Things That Can Be Done

  • Add integration tests for the HTTP and L4 handlers
  • Implement tests for IPv6 support
  • Validate project conncept (Caddy layer 4 app: TCP working, UDP needs testing)
  • Add support for captcha actions
  • Implement support for custom actions (currently defaults to block)
  • Integrate with Caddy metrics
  • Integrate with Caddy profiling
  • Implement caching for the LiveBouncer

...and more things to come!

Contributing

We are always open to contributions! Whether it's fixing bugs, improving documentation, or adding new features from the Roadmap above, your help is welcome. Feel free to open an issue or submit a pull request.

About

A Caddy module that blocks malicious traffic based on decisions made by CrowdSec.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages