Skip to main content

CrowdSec Cloudflare Worker

๐Ÿ“š Documentation ๐Ÿ’  Hub ๐Ÿ’ฌ Discourse

ModeStream only
MetricsSupported
MTLSSupported
PrometheusSupported

Overviewโ€‹

This Remediation Component (aka Bouncer) uses Cloudflare Workers to block or challenge incoming requests.

  • It uses decisions taken by your CrowdSec Security Engine and/or Blocklists you subscribed to.
  • It can be directly plugged to CrowdSec Blocklists via a CrowdSec Blocklist as a Service Integration.

The bouncer uses Cloudflare Workers in combination with Cloudflare Workers KV (KeyValue store).

  • Register this remediation component into your Security engine: Here.
  • OR setup a Blocklist as a Service endpoint for a remediation component: Here.
warning

This Remediation Component heavily relies on Cloudflare Workers and KV store.
It works best on a paid Workers subscription. More explanation in the chapter Test with Cloudflare free plan

Operational modesโ€‹

This Remediation Component can operate in two modes:

  • Daemon Mode: A Go process runs continuously on a host/vm, periodically syncing decisions from your CrowdSec Security Engine to Cloudflare.
  • Autonomous Mode: A Go process creates/delete an autonomous Cloudflare Worker that periodically syncs decisions within Cloudflare itself.

Daemon Modeโ€‹

This mode is recommended if you are using a Security Engine and want to relay all/part of the decisions (and subscribed blocklists) to Cloudflare.
It provides more control and flexibility over the decision synchronization process.
It requires the Bouncer (Go process) to run continuously on a host/VM, usually alongside your CrowdSec Security Engine.

info

The Workers and KV created by the bouncer will be cleaned up from Cloudflare upon launch error OR bouncer stoppage.

cloudflare-worker remediation component global view

Autonomous Modeโ€‹

This mode is recommended if you want a minimal footprint deployment, without having the bouncer process running on your host/VM.
๐Ÿ’ก It is ideal if you want to directly plug a Blocklist integrations into Cloudflare.

It can also be plugged to a Security Engine, but woould require an open connection from Cloudflare to your LAPI. We recommend using Daemon mode in a usecase where a Security Engine is involved.

โš™๏ธ Init / Removal on CloudFlareโ€‹

Creation of necessary Cloudflare Workers and KV stores is done once at init time.
And can be cleaned up by running the bouncer with the appropriate instruction* (more details int the installation section).*

The init phase create two workers and one KV store.:

  • The remediation worker, which applies the decisions to incoming requests:
    • It uses the KV store to lookup decisions.
    • It is bound to worker routes to protect your selected zones.
  • The decisions sync worker, which periodically fetches and caches decisions and updates the KV store.

The cleanup phase deletes all the created components.

cloudflare-worker remediation component autonomous init view

โš™๏ธ Periodic decision sync within Cloudflareโ€‹

Once initialized, the decisions sync worker runs periodically based on a cron schedule defined in the configuration.

cloudflare-worker remediation component autonomous sync view

Installationโ€‹

warning

After configuring and starting the Remediation Component, please see the setting up worker fail mode section.

Prerequisitesโ€‹

Before installing the CrowdSec Cloudflare Worker Remediation Component, you need a Cloudflare API token with the required permissions to create and manage Workers, KV stores, and other Cloudflare resources

For instructions on generating a Cloudflare API token with the correct permissions, see Generating a Cloudflare API Token.

Packages Installationโ€‹

Packages for crowdsec-cloudflare-worker-bouncer are available on our repositories. You need to pick the package accord to your firewall system :

SH
sudo apt install crowdsec-cloudflare-worker-bouncer

Then run the following commands to setup your Remediation Component:

SH
sudo crowdsec-cloudflare-worker-bouncer -g <CLOUDFLARE_TOKEN1>,<CLOUDFLARE_TOKEN2> -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't alread
sudo systemctl start crowdsec-cloudflare-worker-bouncer # the Remediation Component now syncs the crowdsec decisions with cloudflare components.
warning

Please configure your server to emit real IPs rather than cloudflare IPs in logs, so crowdsec can function properly. See how to here

info

If your Remediation Component is not installed on the same machine than LAPI, don't forget to set the crowdsec_lapi_url and crowdsec.lapi_key in the configuration file /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml

note

You need to run sudo crowdsec-cloudflare-worker-bouncer -d to cleanup existing cloudflare components created by Remediation Component before editing the config files.

note

You can run sudo crowdsec-cloudflare-worker-bouncer -g <CLOUDFLARE_TOKEN1>,<CLOUDFLARE_TOKEN2> -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml to generate the configuration by discovering all the accounts and the zones associated with the provided tokens.

Manual Installationโ€‹

Assistedโ€‹

Download the latest release.

SH
tar xzvf crowdsec-cloudflare-worker-bouncer.tgz
cd crowdsec-cloudflare-worker-bouncer/
sudo ./install.sh
sudo crowdsec-cloudflare-worker-bouncer -g <CLOUDFLARE_TOKEN1>,<CLOUDFLARE_TOKEN2> -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided tokens
sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't already
sudo systemctl start crowdsec-cloudflare-worker-bouncer # the Remediation Component now syncs the crowdsec decisions with cloudflare components.

From sourceโ€‹

โš ๏ธ requires go >= 1.23

SH
git clone https://github.com/crowdsecurity/cs-cloudflare-worker-bouncer
cd cs-cloudflare-worker-bouncer
make release
cd crowdsec-cloudflare-worker-bouncer-*
./crowdsec-cloudflare-worker-bouncer -g <CLOUDFLARE_TOKEN1>,<CLOUDFLARE_TOKEN2> -o /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # auto-generate cloudflare config for provided space separated tokens
sudo vi /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml # review config and set `crowdsec.lapi_key` if haven't already
sudo systemctl start crowdsec-cloudflare-worker-bouncer

How it worksโ€‹

The Remediation Component can operate in two modes:

Daemon Mode (default)โ€‹

The Remediation Component does the following:

  1. Create a Cloudflare Worker and a Worker KV per configured account.
  2. Create a Worker Route(s) per configured zone. Any request matching the route would be handled by the worker.
  3. For every matching incoming request, the worker checks whether it's IP, Country and AS have a decision against. It checks for this in it's KV store. If found it performs the corresponding remediation.
  4. The Remediation Component runs as a daemon and periodically updates the KV store with the latest decisions from CrowdSec's Security Engine OR Blocklist Integration.

Note that in the following Schema, a Blocklist as a Service Integration can be substituted to the Security Engine.

Architecture

Autonomous Modeโ€‹

info

Autonomous mode is ideal for users who prefer not to run a continuous process on their host/VM.
Combined with Blocklist as a Service (BLaaS), this provides the minimal footprint deployment, only running setup/cleanup commands when needed.

In autonomous mode (enabled with the -S flag), the Remediation Component functions without requiring a continuously running Go daemon process. Instead:

  1. Two Cloudflare Workers are deployed:
    • crowdsec-cloudflare-worker-bouncer (Remediation Worker) - applies cached decisions to incoming requests (same as daemon mode)
    • decisions-sync-worker (Blocklist updater Worker) - periodically fetches and caches security decisions using Cloudflare scheduled tasks
INIT Architecture
  1. The Go process only needs to run once for initial setup and configuration deployment

  2. All decision synchronization is handled automatically by the Blocklist updater Worker using Cloudflare's scheduled tasks

SYNC Architecture
  1. This mode reduces infrastructure requirements as no persistent daemon is needed
Autonomous Architecture

Reset all decisions from Cloudflare KV storeโ€‹

In autonomous mode, you can reset all decisions without redeploying all the infrastructure (with the -S flag). In order to do so, add a RESET key (with a true value) to the KV store. The next time the sync worker runs, it will clear all existing decisions and repopulate them from CrowdSec LAPI.

Metricsโ€‹

The worker writes metric data points to a Workers Analytics Engine dataset, tracking:

  • Number of requests processed
  • Number of requests blocked
  • Number of requests that threw an exception in the worker
  • Average request processing latency
info

Since v0.0.18, metrics are stored in a Workers Analytics Engine dataset instead of a D1 database. Make sure your Cloudflare token has the Account Analytics: Read permission (see the permissions table). Without it the metric poll returns a 403 and metrics are disabled, but remediation enforcement is unaffected.

If you are upgrading from an older version, the legacy CROWDSECCFBOUNCERDB D1 database is no longer used and can be deleted manually from the Cloudflare dashboard.

The dataset name defaults to crowdsec_cloudflare_bouncer and can be customized with the worker.analytics_dataset option.

In Daemon Mode, the running process:

  • Polls the Analytics Engine SQL API on the regular push schedule
  • Exposes metrics through the Prometheus endpoint
  • Automatically pushes metrics to CrowdSec for visualization with cscli

In Autonomous Mode, since there is no running daemon process:

  • Metrics are collected in the Analytics Engine dataset
  • Metrics are NOT pushed to CrowdSec

Configuration explainedโ€‹

YAML
crowdsec_config:
lapi_key: ${API_KEY}
lapi_url: ${CROWDSEC_LAPI_URL}
update_frequency: 10s
include_scenarios_containing: []
exclude_scenarios_containing: []
only_include_decisions_from: []
insecure_skip_verify: false
key_path: "" # Used for TLS authentification with CrowdSec LAPI
cert_path: "" # Used for TLS authentification with CrowdSec LAPI
ca_cert_path: "" # Used for TLS authentification with CrowdSec LAPI

cloudflare_config:
accounts:
- id: <ACCOUNT_ID>
zones:
- zone_id: <ZONE_ID> # crowdflare.co.uk
actions: # Supported Actions [captcha, ban]
- captcha
default_action: captcha # Supported Actions [captcha, ban, none]
routes_to_protect: []
turnstile:
enabled: true
rotate_secret_key: true
rotate_secret_key_every: 168h0m0s
mode: managed # Supported Modes "managed"|"invisible"|"non-interactive"
token: <CLOUDFLARE_ACCOUNT_TOKEN>
account_name: owner@example.com
worker:
log_only: false # If true, allow all requests, but still keep track of what would have been blocked in the metrics
script_name: ""
kv_namespace_name: "" # KV namespace title; change when running multiple bouncers on the same Cloudflare account
decisions_sync_script_name: "" # Decisions sync worker script name; change when running multiple bouncers on the same Cloudflare account
analytics_dataset: "" # Workers Analytics Engine dataset name for metrics (default: crowdsec_cloudflare_bouncer)
logpush: null
tags: []
compatibility_date: ""
compatibility_flags: []
observability: # Optional Workers Observability (logs/traces); omit to leave Cloudflare defaults in place
enabled: true
head_sampling_rate: 1.0
traces:
enabled: true
head_sampling_rate: 1.0
decisions_sync_worker: # Configuration for autonomous decisions sync worker
cron: '*/5 * * * *' # Cron schedule for syncing decisions (e.g., "*/5 * * * *" for every 5 minutes)

log_level: info
log_media: "stdout"
log_dir: "/var/log/"
ban_template_path: "" # set to empty to use default template

prometheus:
enabled: true
listen_addr: 127.0.0.1
listen_port: "2112"

Cloudflare Configurationโ€‹

Background: In Cloudflare, each user can have access to multiple accounts. Each account can own/access multiple zones. In this context a zone can be considered as a domain. Each domain registered with cloudflare gets a distinct zone_id.

Generating a Cloudflare API Tokenโ€‹

For obtaining the token:

warning

Ensure the token you are generating is a user API token these are found via clicking "my profile" and API Tokens. If you are in the Account API Tokens section then this is the incorrect place and these tokens have different rate limits which may cause issues whilst operating this Remediation Component.

  1. Sign in as a user who has access to the desired account.

Then click this link and create the token.

Alternatively, you can go to Tokens and create the token.

The Remediation Component requires the following permissions to function:

Permission GroupItemPermission
AccountTurnstileEdit
AccountWorkers KV StorageEdit
AccountWorkers ScriptsEdit
AccountAccount SettingsRead
AccountAccount AnalyticsRead
UserUser DetailsRead
ZoneDNSRead
ZoneWorkers RoutesEdit
ZoneZoneRead
info

By default, the token will be scopped to all accounts / zones you have access to.
We recommend scoping the token only to the required accounts and zones.

warning

This remediation component require each configured to have at least one A or AAAA records.
If you have zones without them (eg, with only CNAME records), exclude them from the scope.
The bouncer will try to automatically ignore such zones, but if it fails to do so for any reason, you might incur higher KV storage charges.

To automatically generate config, check the helper section below.

Helpersโ€‹

The binary has built in helper scripts to do various operations.

Auto config generatorโ€‹

Generates config by discovering all the accounts and the zones associated with provided list of tokens.

Example Usage:

SH
sudo crowdsec-cloudflare-worker-bouncer -g <TOKEN_1>,<TOKEN_2>...  -o cfg.yaml
cat cfg.yaml > /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
note

This script only generates cloudflare related config. By default it refers to the config at /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml for crowdsec configuration.

Using custom config:

SH
sudo crowdsec-cloudflare-worker-bouncer -c ./cfg.yaml -g <TOKEN_1>,<TOKEN_2>... 

Cloudflare Cleanupโ€‹

This deletes all the Cloudflare infrastructure which was created by the Remediation Component.

Example Usage:

SH
sudo crowdsec-cloudflare-worker-bouncer -d 

Setting up the worker route fail modeโ€‹

The Remediation Component creates worker routes to make the workers act as a reverse proxy for your origin servers. The worker routes are created with the failover mode set to Fail Closed. There's no public Cloudflare API we can use to change/update it to Fail Open mode.

With Fail Closed mode, Routes in fail closed mode will display a Cloudflare 1027 error page to visitors if there's an error within the worker. This error could be triggered due to quotas exceeding your plan etc. Cloudflare doesn't mention all the possible scenarios which could trigger this error page.

Thus we recommend you to manually override the failover mode to Fail Open for all the worker routes created by our Remediation Component. With Fail Open mode the requests would bypass the worker and be served directly from your origin servers. Thus your website would continue to function even if there's an error within the worker.

This can be done by following the steps below:

  1. Log in to the Cloudflare dashboard and select your account.
  2. For all the websites configured with the Remediation Component, do the following:
  3. Click on the website's name to open the Website's Overview page.
  4. Click on the Worker Routes tab from the left menu.

Worker Route

  1. Click on the route created by the Remediation Component.
  2. Click on the Edit button.
  3. Click on the Request limit failure mode. Check the Fail open button.

Fail Open

Appendix: Test with Cloudflare free planโ€‹

Using Cloudflare's free plan with our Remediation Component requires to understand the constraints of the CloudFlare freeplan.
Despite these constraints, it's entirely feasible to leverage the Remediation Component for enhanced security.

In this section we'll guide you through:

  • An overview of the Cloudflare free plan's limitations and their impact on Remediation Component functionality
  • A walkthrough for deploying the Remediation Component within these constraints successfully

Understanding Cloudflare Free Plan Limitationsโ€‹

Our Remediation Component integrates with Cloudflare Workers and Workers KeyValue storage, subject to specific thresholds under the free plan.
For the complete detailed information, refer to Cloudflare's official documentation:

Key limitations to note for Remediation Component operation on the free plan include:

  • KV write: Up to 1K per day
  • Worker Requests:Up to 100k per day or 1K per minute

KV write limit of 1K per day:
It's the primary limiting factor as the full decisions list (blocklist) passed on to the Remediation Component often exceeds tens of thousands of IPs.

  • It implies that the initial population of decisions in the Worker's KV will be truncated to 1K
  • However, it will still periodically receive new decisions and remove expired ones.
  • So, eventually you'll have many more than 1K IPs in the KV but it still diminishes the immediate effectiveness of the Remediation Component

The request quota: While the request quota might seem ample, it's essential to remember that both legitimate traffic and potential attack patterns contribute to this total.

  • โš ๏ธ It's primordial to properly setup the failmode
  • With the failmode set to passthrough, when you reach the Worker request limits your service will stay available, but the Remediation Component won't apply remediation anymore

Quick Guide : Configuring the Remediation Component on Cloudflare's Free Planโ€‹

To adapt to the free plan's constraints, we can prioritize local decision-making and manual intervention over broader community-driven blocklists.
Here's how to set it up:

  1. Configuration Setup: Begin by auto-generating the Remediation Component configuration.
  2. Limiting Decision Sources: Modify the configuration to prioritize decisions generated by your Security Engine and added manually.
YAML
crowdsec_config:
[...]
only_include_decisions_from: ["cscli", "crowdsec"]
  1. Failmode Configuration: It's crucial to configure the failmode properly to ensure your service remains operational even when request quotas are reached.
  2. Testing with manual decisions: Verify the functionality by adding decisions manually, which should be promptly reflected in KV storage and enforced by the Remediation Component.
SH
  sudo cscli decisions add --ip 192.168.1.1 --type captcha

check your decisions has been added using:

SH
  sudo cscli decisions list --origin cscli

And within a few seconds it will be sent to the KV and the proper remediation should be applied to the requests from the specified IP

Configuration Referenceโ€‹

crowdsec_configโ€‹

Used to nest the configuration related to crowdsec.

lapi_urlโ€‹

string

The URL of CrowdSec LAPI. It should be accessible from the Remediation Component.

lapi_keyโ€‹

string

It can be obtained by running the following on the machine CrowdSec LAPI is deployed on.

SH
sudo cscli -oraw bouncers add cloudflarebouncer # -oraw flag can discarded for human friendly output.

update_frequencyโ€‹

string (That is parseable by time.ParseDuration)

The Remediation Component will poll the CrowdSec every update_frequency interval. (default: 10s)

include_scenarios_containingโ€‹

[ ]string

Ignore IPs banned for triggering scenarios not containing either of provided word.

Example
YAMLExample
include_scenarios_containing: ["ssh", "http"]

exclude_scenarios_containingโ€‹

[ ]string

Ignore IPs banned for triggering scenarios containing either of provided word.

Example
YAMLExample
exclude_scenarios_containing: ["ssh", "http"]

only_include_decisions_fromโ€‹

[ ]string

Only include IPs banned due to decisions orginating from provided sources.

Example
YAMLExample
only_include_decisions_from: ["cscli", "crowdsec"]

insecure_skip_verifyโ€‹

boolean

Skip verification of the LAPI certificate, usually used for self-signed certificates

key_pathโ€‹

string

Path to the private key file to use for TLS authentication with CrowdSec LAPI.

cert_pathโ€‹

string

Path to the certificate file to use for TLS authentication with CrowdSec LAPI.

ca_cert_pathโ€‹

string

Path to the CA certificate file to use for TLS authentication with CrowdSec LAPI.

cloudflare_configโ€‹

Cloudflare configuration.

accounts[].idโ€‹

string

The ID of the Cloudflare account.

accounts[].zones[].zone_idโ€‹

string

The ID of the Cloudflare zone.

accounts[].zones[].actionsโ€‹

captcha | ban

Supported actions for the zone.

accounts[].zones[].default_actionโ€‹

captcha | ban | none

Default action to take for the zone.

accounts[].zones[].routes_to_protectโ€‹

[ ]string

List of routes to protect within the zone. Example value ["example.com/"]

accounts[].zones[].turnstile.enabledโ€‹

boolean

Enable or disable turnstile for the zone.

accounts[].zones[].turnstile.rotate_secret_keyโ€‹

boolean

Rotate the secret key for turnstile.

accounts[].zones[].turnstile.rotate_secret_key_everyโ€‹

string (That is parseable by time.ParseDuration)

Duration for rotating the secret key. Values should be in the format of 1h2m3s. Example value 168h0m0s for 7 days.

accounts[].zones[].turnstile.modeโ€‹

Mode for turnstile. Supported values ["managed", "invisible", "non-interactive"]. See cloudflare-docs for more details.

accounts[].zones[].tokenโ€‹

string

Cloudflare account token.

accounts[].zones[].account_nameโ€‹

string

Account name.

worker.log_onlyโ€‹

bool

If true, allow all requests but keep track of what would have been blocked in the metrics.

Defaults to false

worker.script_nameโ€‹

string

Name to use for the worker script.

Default to crowdsec-cloudflare-worker-bouncer.

worker.kv_namespace_nameโ€‹

string

Title of the Worker KV namespace used to create/locate the decision store.

Change this when running multiple bouncer instances on the same Cloudflare account so each instance uses its own KV namespace.

Default to CROWDSECCFBOUNCERNS.

worker.decisions_sync_script_nameโ€‹

string

Name to use for the autonomous decisions sync worker script.

Change this when running multiple bouncer instances on the same Cloudflare account so each instance uses its own sync worker.

Default to crowdsec-decisions-sync-worker.

worker.analytics_datasetโ€‹

string

Name of the Workers Analytics Engine dataset the worker writes metric data points to. See the Metrics section.

Must match ^[a-zA-Z_][a-zA-Z0-9_]{0,63}$.

Default to crowdsec_cloudflare_bouncer.

worker.logpushโ€‹

bool

Enable logpush for the worker.

Default to no value.

worker.compatibility_dateโ€‹

string

See https://developers.cloudflare.com/workers/configuration/compatibility-dates/.

Default to no value

worker.compatibility_flagsโ€‹

list of strings

See https://developers.cloudflare.com/workers/configuration/compatibility-flags/.

Default to no value.

worker.observabilityโ€‹

object

Optional Workers Observability (logs and traces) configuration. Omit the block to leave the Cloudflare defaults in place.

If a deployed worker cannot have observability applied, a warning is logged but the deploy is not aborted.

Example
YAMLExample
observability:
enabled: true
head_sampling_rate: 1.0 # Sampling rate for head-based observability (0.0 to 1.0)
traces:
enabled: true
head_sampling_rate: 1.0

decisions_sync_worker.cronโ€‹

string

Cron expression that defines how often the decisions sync worker runs in autonomous mode. This controls the frequency at which the worker fetches the latest decisions from CrowdSec LAPI and updates the KV store.

The cron expression follows standard cron syntax with 5 fields: minute hour day month day_of_week

Example values:

  • */1 * * * * - Every minute (default)
  • */5 * * * * - Every 5 minutes
  • */10 * * * * - Every 10 minutes
note

This setting only applies to autonomous mode (when using the -S flag). In daemon mode, the update_frequency setting is used instead.

Default to */5 * * * * (every 5 minutes).

prometheusโ€‹

Prometheus configuration.

enabledโ€‹

boolean

Enable or disable Prometheus metrics.

listen_addrโ€‹

string

Address to listen for Prometheus metrics. Example value 127.0.0.1

listen_portโ€‹

string

Port to listen for Prometheus metrics. Example value 2112

Othersโ€‹

ban_template_pathโ€‹

string

Path to the ban template file. If not provided, the default template is used. This HTML would be rendered to requests when they are banned.

log_levelโ€‹

info | debug | error | warning | trace

Log level of the Remediation Component.

log_modeโ€‹

stdout | file

Where the log contents are written (With file it will be written to log_dir with the name crowdsec-cloudflare-worker-bouncer.log)

log_dirโ€‹

Relevant if log_mode is file. This determines where to create log file.

Troubleshootingโ€‹

CrowdSec Docs
We use cookies

This site uses cookies to help us improve your experience. You can accept or decline below.