blog/content/posts/how-to-crowdsec.md
2025-04-15 21:38:35 +02:00

7.5 KiB

+++ date = '2025-04-15' draft = true title = "How to Set Up Crowdsec" tags = ["howto", "tutorial", "web", "securoty"] categories = ["technical"] +++

Crowdsec

NOTE: This configuration blocks many varieties of clients and services. You might want to whitelist your own ISP and / or your own IP ranges (perhaps even your entire country if you're trusting enough) in case your own services and homebrew experiments gets banned.

Short for crowdsecurity, crowdsec is a community effort to bring auto-banning security to the masses, and it's surprisingly easy to set up. You just have to understand how the thing works.

I noticed that I am getting a lot of suspicious traffic on my gitea instance. Usernames such as log4j and thomad from china and bulgaria. Yea. Let's enable some fucking security. Fuck I hate that I have to do this, but I guess people will be assholes.

After this, the banhammer came down with the might of zeus. Now no-one gets access. Not even me. I tried to do some country-code whitelisting, but that was a bit of a dud. I'm tired now. Will look at it tomorrow.

Okay! I seem to have it working now! That was an adventure. Will elaborate when I get back home.

Okay, There's multiple "things" to a crowdsec setup. Crowdsec (the non-paid cloud solution) consists of:

  • The core crowdsec security engine (crowdsecurity/crowdsec container image)
    • Does the "detection" and hardcore logic and makes decisions.
  • The bouncer (fbonalair/traefik-crowdsec-bouncer:latest container image in my case)
    • Enforces the decisions.
    • There are multiple different "types" of bouncers. I just use the forwardAuth type, as that is the most straight forward one. Especially when combined with traefik.

Concepts

In short, there are only a couple of concepts you should know in order to use crowdsec. This is Feel free to skip these if you don't care for now, and just want something up and running.

  • Acquisitions
    • In order for crowdsec to know what and where to look for potential intruders, threats etc. You must tell it in the form of acquisition configurations. The easiest thing to do is to just give crowdsec access to your docker logs and traefik logs - this is excactly what we're aiming to do.
  • Parsers
  • Bucket Overflow
  • Bouncers

Note that the core crowdsec security engine should be part of the core traefik/portainer deployment because it will need some elevated privileges. The traefik service should also register some middlewares, so it can't be part of the portainer managed containers / stacks.

When using Traefik, make sure to add the docker labels that enable traefik trafficing to the containers:

# For the new containers.
labels:
  - traefik.enable=true
  - traefik.docker.network=proxy
  - traefik.http.routers.traefik-bouncer.entrypoints=websecure

"easy"

This shit was not easy to set up. But it is easy to maintain. Keep a "new"/"learning" mind, and all should be fine.

Configuring the Bouncer

Also called "Remediation" I am using the traefik bouncer, that is using forwardAuth to check if an IP is blocked or not.

Configure the container in docker compose and afterwards, you should introduce the traefik middleware in the dynamic and static configuration, like so:

# dynamic traefik config
http:
middlewares:
traefikBouncer:
forwardauth:
address: http://traefik-bouncer:8080/api/v1/forwardAuth
trustForwardHeader: true
# static traefik config
entryPoints:
http:
address: ":80"
http:
middlewares:
- traefikBouncer@file
https:
address: ":443"
http:
middlewares:
- traefikBouncer@file

If you have (I do) some other names for the address: ":443" and ":80" middlewares, don worry, just add the traefikBouncer@file to the list of middlewares and you should be good.

You will have to register your bouncer through the cscli as well:

docker exec crowdsec cscli bouncers list
docker exec crowdsec cscli bouncers add traefikBouncer

This should give you an API key. Place it in the environment variable CROWDSEC_BOUNCER_API_KEY: <your-key-here>. Additionally, you should add the CROWDSEC_AGENT_HOST: crowdsec:8080 environment variable (assuming the crowdsec docker service is called crowdsec) - the port is standard and you don't need to portmap or expose anything btw.

Crowdsec Core Security Engine Configuration

In order for the crowdsec security engine to be able to detect intruders, it needs access to the logs of the other containers on the server. To do this, you can just volume mount: /var/run/docker.sock:/var/run/docker.sock:ro and then

Check out https://app.crowdsec.net/hub/configurations if there are logparsers available for the service you want to integrate.

Acquisitions

In the acquis.d directory (volume mapped into the crowdsec container to ./acquis.d:/etc/crowdsec/acquis.d), you should add YAML files for each source you want the crowdsec engine to scan for criminals and other scum:

acquis.d/
├── gitea.yaml
└── traefik.yaml

File Contents:

# traefik.yaml
filenames:
- /var/log/traefik/*
labels:
type: traefik
# gitea.yaml
source: docker
container_name:
- gitea
labels:
type: gitea

traefik.yml is a filename based acquisition file, meaning you need to configure the traefik container to output access and system logs into a directory that is volume-mapped so that it's available to the crowdsec container (traefik-logs:/var/log/traefik/:ro and associated traefik-logs:/var/log/traefik/ on traefik).

The acquisition file for the gitea service is using the docker source. So it'll read the docker logs. The cool thing about this, is that you dont have to do any extra configuration on the gitea side.

To configure traefik to output logs into a file (default it just outputs to stdout/stderr for no-one to read), add the following to your static config (traefik.yml) - make sure to docker compose up -d --force-recreate every time you edit the config (and want to apply the changes):

# ... at the end of traefik.yml
log:
level: INFO
filePath: /var/log/traefik/traefik.log
accessLog:
filePath: /var/log/traefik/access.log

Also, in docker compose file, install some collections:

# in crowdsec container spec
environment:
GID: "$(GID-1000)"
COLLECTIONS: "crowdsecurity/linux crowdsecurity/traefik crowdsecurity/whitelist-good-actors LePresidente/gitea"

Geofenching

You might have lost the bouncer - check with docker exec crowdsec cscli bounders list.

I am hosting some services that may produce some false-flags by crowdsec, so I will be whitelisting my country. To do this, we need to register a country-code whitelist postoverflow in the postoverflows directory, which is volume mapped ./postoverflows:/etc/crowdsec/postoverflows/:

# postoverflow/s01-whitelist/sc-countries-whitelist.yaml
name: my/whitelist
description: Whitelist trusted regions
whitelist:
reason: Whitelisted country
expression:
- "evt.Enriched.IsoCode == 'DK'"  # NO! Not anymore!

Note that the data is not "enriched" with the IsoCode yet. You need to install the geoip-enrich thing:

docker exec crowdsec cscli parsers install crowdsecurity/geoip-enrich

This solution is not very sophisticated, so I might change this to something less "sledgehammer"-y in the future.