Im Homelab gilt ja oft safety third
Wenn man herumexperimentiert mit den ganzen Softwaremöglichkeiten der 2020er Jahre, dann vergisst man leider aber auch oft auf die Sicherheit. Solange alles nur lokal abläuft, ist das ja kein großes Problem. Aber vielleicht möchte man ja eine eigene Nextcloud Instanz betreiben, um nicht immer nur auf die Angebote der Techgiganten angewiesen zu sein. Spätestens dann muss man aber allgemeinen Zugriff darauf erlauben (oder man lebt mit einer eingeschränkten Funktionalität). Ab dann gilt es jedoch auf die Sicherheit zu achten. Das heißt einerseits regelmäßig Updates einspielen, aber auch unbefugte Zutritte zu sperren. Klassischerweise machen das Programme wie fail2ban, welches nach ein paar Loginversuchen die IP-Adresse für eine gewisse Zeit sperrt. Da muss der Angreifer aber schon ein paar Mal an der Tür klopfen, bevor das greift. Da kommt die französische Firma Crowdsec mit der gleichnamigen Open Source Software und Webservice ins Spiel. Denn mit diesem Service werden diese Erfahrungswerte (Unbefugte klopfen am Server an) kollektiv gesammelt. Somit muss nicht jeder Server alleine eine Blockliste aufbauen, sondern diese wird gemeinsam gepflegt. Die Software und der Grundservice ist dabei kostenfrei. Die Firma verdient ihr Geld jedoch mit Premium-Abonnements für Extra-Funktionalitäten. Diese Interessieren uns hier nicht, für den Hausgebrauch genügt die Community Variante.
In diesem Beitrag werden wir uns die Installation von Crowdsec auf einem unprivilegierten Proxmox LXC ansehen, wo auch bereits Caddy als Webserver und Reverse Proxy läuft. Letzterer nicht als Docker Container, sondern als Systemd-Service. Die Schwierigkeit hier besteht nicht in der Installation, sondern darin erst einmal die Konzepte zu begreifen und wie man das Ganze dann am Besten angehen soll und kann. Ich gehe Schritt für Schritt vor, sollte also für alle Crowdsec-Interessenten machbar sein, sofern schon Proxmox und Caddy vorhanden sind.
Crowdsec auf Ubuntu 24.04 LXC Container installieren
Die Website von Crowdsec mit den Installationsanleitungen. Wir verwenden für die Installation das Bash-Skript, welches uns das manuelle Hinzufügen des Crowdsec-Repositorys erspart.
Nachdem wir die Installation im unprivilegierten LXC-Container vornehmen, entfernen wir aus dem originalen Befehl…
curl -s https://install.crowdsec.net | sudo sh… das sudo:
curl -s https://install.crowdsec.net | shDas Repo wurde hinzufügt:

Als nächstes Installieren wir den Crowdsec-Server mit:
apt install crowdsec

Als nächstes braucht man einen Account bei Crowdsec, um alles zentral überwachen und einstellen zu können.
In der Übersicht wählt man dann “Enroll command” aus:

Fertig:

Jetzt neustarten mit:
systemctl restart crowdsecUnd schon taucht die Instanz im Dashboard auf, wo man auf “Accept enroll” klicken muss:

Jetzt wird einem die “Security Engine” angezeigt:

Jetzt wird zwar schon fleißig analysiert, aber es kann noch nicht gehandelt werden, dafür brauchen eine remediation component, die in der Kommandozeile und der Doku bouncer genannt wird.
Nachdem wir hier den Reverse Proxy Caddy mit einem solchen Bouncer ausstatten werden, machen wir dort weiter.
Caddy Reverse Proxy mit Crowdsec Bouncer ausstatten
Da ich für Caddy noch nie Module installiert habe, halte ich mich an diese gute Anleitung von Michael Klehr. In seiner Anleitung nimmt er das Github-Repo caddy-crowdsec-bouncer von hslatman.
Wir führen dazu diesen Befehl aus:
caddy add-package github.com/hslatman/caddy-crowdsec-bouncerUpdate bricht caddy add-package: also Caddy selbst kompilieren
Leider ist caddy add-package immer noch etwas experimentell, nach einem Update des LXC Containers ist der Crowdsec Bouncer wieder verschwunden und Caddy hat den Dienst verweigert. Eine stabilere Lösung für solche Zusatzpakete, die auch im Caddy-Forum empfohlen wird, ist das Eigenkompilat xcaddy. Daher hier auch die Variante für Selbstkompilierer.
Unter Debian 12 zuerst Go Repository hinzufügen für aktuelle Pakete:
# add backports (one line)
echo 'deb http://deb.debian.org/debian bookworm-backports main' | \
tee /etc/apt/sources.list.d/backports.list
apt update
apt -t bookworm-backports install golang-1.22-goUnter Ubuntu müsste es so aussehen (konnte ich jedoch nicht testen):
add-apt-repository ppa:longsleep/golang-backports
apt update
apt install --yes golang-goWenn man so wie ich zuerst Go mittels normalen Paketquellen unter Debian 12 installiert hat, muss man noch die Version manuell umstellen:
root@caddy:~# go version
go version go1.19.8 linux/amd64
root@caddy:~# update-alternatives --install /usr/bin/go go /usr/lib/go-1.22/bin/go 90
update-alternatives: using /usr/lib/go-1.22/bin/go to provide /usr/bin/go (go) in auto mode
root@caddy:~# update-alternatives --install /usr/bin/gofmt gofmt /usr/lib/go-1.22/bin/gofmt 90
update-alternatives: using /usr/lib/go-1.22/bin/gofmt to provide /usr/bin/gofmt (gofmt) in auto mode
root@caddy:~# which go
/usr/bin/go
root@caddy:~# go version
go version go1.22.12 linux/amd64
Dann xcaddy in den richtigen Pfad installieren:
GOBIN=/usr/local/bin go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
xcaddy build --with github.com/hslatman/caddy-crowdsec-bouncer@latest
xcaddy build \
--with github.com/hslatman/caddy-crowdsec-bouncer@latest \
--with github.com/hslatman/caddy-crowdsec-bouncer/http@latest \
--with github.com/hslatman/caddy-crowdsec-bouncer/layer4@latest \
--with github.com/hslatman/caddy-crowdsec-bouncer/appsec@latest
Das dauert dann ein bisserl:

mv ./caddy /usr/local/bin/
chmod +x /usr/bin/caddy
systemctl daemon-reload
systemctl restart caddyAb jetzt geht es wieder normal weiter.
Bouncer aktivieren
Schon ist der Bouncer installiert…

… und im Caddyfile muss man diese Zeilen ganz am Anfang hinzufügen:
{
crowdsec {
api_url http://localhost:8080
api_key
ticker_interval 15s
# Additional optional parameters:
# disable_streaming
# enable_hard_fails
}
}Wir starten nun Caddy neu mit systemctl restart caddy.
Jetzt können wir mit…
cscli bouncers add caddy… den Caddy-Bouncer auf dem Crowdsec-Server hinzufügen.
Mit diesem Befehl kann man die Bouncer auflisten:
cscli bouncers list
Caddyfile Konfiguration
Damit die Logs geparst werden können muss man Caddy aber zuerst einmal anweisen überhaupt Logs zu schreiben, das geht so:
domain.com {
route {
crowdsec
reverse_proxy x.x.x.x
}
log {
output file /var/log/caddy/domain-com.log {
roll_size 10mb
roll_keep 20
roll_keep_for 720h
}
}Mit dieser Einstellung wird ein Log mit dem gewünschten Namen (hier domain-com, ich nehme der Einfachheit halber den Domainnamen und ersetze die Punkte mit Strichen) erstellt, welches nach Erreichen einer Größe von 10 MB durch eine neue Logdatei ersetzt wird. Von diesen Logs werden maximal zwanzig gespeichert und diese für dreißig Tage gespeichert.
Wenn das erledigt ist mit systemctl restart caddy den Reverse Proxy neustarten. Logs zu speichern ist überhaupt eine empfehlenswerte Sache.
Caddy Log Parsing
In der Crowdsec-Weboberfläche kann man Log-Parser installieren, wie zb für Caddy:

Die Installation erfolgt mit:
cscli parsers install crowdsecurity/caddy-logsKonsolenausgabe:

Noch einmal mit sudo systemctl reload crowdsec Systemd-Crowdsec neustarten.
Jetzt muss man noch in die acquisition das folgende hinzufügen:

Nur was ist das überhaupt?
ChatGPT meint:

Aha, die Akquise akquiriert Logdateien, verstanden. Und wo?

Ist ja ganz einfach, man muss also unter /etc/crowdsec/acquis.d/caddy.yaml für jeden Dienst, bzw. für jedes Log, das geparst werden soll einen solchen yaml-Eintrag machen. Wenn man mehrere (Sub-)Domains hinzufügen möchte empfiehlt es sich gleich noch die Info site hinzuzufügen, so wie hier:
filenames:
- /var/log/caddy/martinfellner-at.log
labels:
type: caddy
site: martinfellner.atNotabene: die drei Striche --- unterteilen in yaml zwei separate yaml-Einträge in einem Dokument. Nachdem wir hier aber eh eine Konfig pro Log machen, ist das egal. Den type nicht angreifen, ich habe zuerst dort die Domain hinzugefügt (type: caddy-martinfellner-at und das hat überhaupt nicht funktioniert, da crowdsec die Art des Logs mit dieser Bezeichnung bestimmt).
Und mit sudo systemctl restart crowdsec den Dienst neustarten und sobald Aufrufe auf die Seit kommen scheint das Log auch unter cscli metrics auf:

Damit läuft das Log-Parsing wie gewünscht. Jetzt bekommt man automatisch eine Alarmmeldung, wenn es zu unbefugten Zugrffsversuchen kommt. Es ist sogar noch besser, denn crowdsec weist auch den Bouncer an, diese IP-Adresse sofort zu sperren. So soll das sein.
Jetzt kann man für alle öffentlich zugänglichen Services dieses Spiel wiederholen.
Was tun mit direkten Aufrufen auf den Server? Catch all!
Jetzt werden zwar alle Aufrufe auf die verschiedenen Services (mit der jeweiligen Domain) registriert und ggf. blockiert, aber direkt Aufrufe auf zb Port 80 werden nicht analysiert. Es gibt gute Gründe, dass man Port 80 einfach auf der Firewall-Ebene blockiert, dann muss man jedoch für jeden Caddy-Neustart den Port wieder aufmachen, damit die Zertifikate erstellt bzw. erneuert werden können. Wenn man das nicht möchte, dann sollte man im Caddyfile diesen Block hinzufügen:
:80 {
route {
crowdsec
# Optionally, instead of abort, you could respond minimally for logging purposes:
# respond "Access Denied" 403
# But if you prefer no response, use:
abort
}
log {
output file /var/log/caddy/default_access.log
}
}Hier werden diese Aufrufe einfach kommentarlos in den Orkus geschickt, wenn man stattdessen eine “Access Denied” 403er Meldung ausgeben möchte kann man die entsprechenden Zeilen verwenden und dafür abort auskommentieren. Wieder Caddy neustarten. Das default-access.log wie oben besprochen als Akquise hinzufügen, zum Beispiel so:
filenames:
- /var/log/caddy/default_access.log
labels:
type: caddy
site: default_access_port_80Wenn alles neugestartet wurde kann man sich die einzelnen Logs mit dem folgenden Befehl genauer anschauen:
sudo cscli explain --file /var/log/caddy/default_access.log --type caddyFazit
Ich bin froh, endlich die Sicherheit meiner Heimserverei verbessert zu haben. Crowdsec ist neben Firewall und Zwei-Faktor-Authentifizierung sicher einer der relevantesten Maßnahmen, um die Sicherheit zu verbessern.
Jetzt werden verdächtige IPs automatisch geblockt, samt Logging und Dashboard. Es hat sich gezeigt, dass xcaddy zuverlässiger läuft als mit dem Updates nicht überlebenden caddy add-package.
In einem weiteren Beitrag werde ich Crowdsec direkt auf dem Proxmox Host, der auf einem Mietserver läuft, installieren. Damit kann man dann auch alle Abfragen analysieren bzw. blocken, die es gar nicht bis zum Reverse Proxy schaffen (also alles außer http und https).