Caddy Reverse Proxy mit LetsEncrypt, Crowdsec und Bouncer

Webservices in meinem Homelab hatte ich die ganze Zeit mit Nginx Proxy Manager als Dockerimage mit dem Crowdsec Replacement von LePresidente inkl. OpenResty Remediation Component veröffentlicht. Doch bei jedem Update wurde es stressiger und fehleranfälliger. Beim letzten Update startete OpenResty nicht mehr im NGINX. Es ging mir voll auf die Nerven! Ich suchte etwas einfaches und wurde mit dem Projekt „Caddy“ fündig. Der Reverse Proxy hatte alles was ich im Homelab brauche: automatische Erstellung der LetsEncrypt Zertifikate und einen Bouncer für Crowdsec. Es existiert ebenfalls eine Collection für Crowdsec mit Parser und Scenarios. Unter Proxmox habe ich mich für einen LXC Container mit Ubuntu 24.04 entschieden. Die Installation skizziere ich hier grob. Als erstes muss man das Repository von Caddy einbinden und den Dienst installieren:

apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
apt update
apt install caddy


Nun ist Caddy installiert und erzeugt ein Systemd Startscript. Die Konfigurationsparameter habe ich mir aus verschiedenen Quellen zusammengesucht und in der Konfigurationsdatei eingebunden. Hier ein Beispiel:

cat /etc/caddy/Caddyfile
{
crowdsec {
api_url http://192.168.X.Y:8080/
api_key sdfffYgQ17QvQB+LPXyL81ppHCya9p6VTMD3g0Lq7XI4
}
}

<subdomain>.klehr.de {
route {
crowdsec
}
reverse_proxy http://192.168.X.Y:3000
log {
output file /var/log/caddy/subdomain-access.log {
roll_size 10mb
roll_keep 20
roll_keep_for 720h
}
}
}


Beim Start von Caddy wird ein Portforward von Port 80 benötigt, denn Caddy erzeugt jetzt über die HTTP-API-01 ein Lets Encrypt Zertifikat für die Subdomains die veröffentlicht werden. Diese Zertifikate liegen in folgendem Ordner:

/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory

Ich lasse den Port 80 nicht die ganze Zeit geöffnet und überwache die Zertifikate mit CheckMK. Sollte ein Zertifkat ablaufen, so öffne ich den Port 80, lösche das Zertifikat im Ordner und starte Caddy neu. Dabei wird ein neues Zertifkat generiert. Etwas umständlich, aber damit kann ich laben.

In dem Beispiel ist die Sektion für Crowdsec schon enthalten. Es reicht bei einem verteilten Crowdsec Setup wie ich es betreibe (mit Remote LAPI) den Bouncer zu installieren und mit dem Crowdsec Server zu verbinden. Dazu müssen wir den Crowdsec Bouncer installieren:

caddy add-package github.com/hslatman/caddy-crowdsec-bouncer

Auf dem Crowdsec Server muss der Bouncer bekannt gemacht werden der sich verbinden soll. Ein API Key wird erzeugt und dieser muss in die Konfiguration von Caddy:

root@CrowdSec ~ # cscli bouncers add caddy

API key for 'caddy':
sdfffYgQ17QvQB+LPXyL81ppHCya9p6VTMD3g0Lq7XI4
Please keep this key since you will not be able to retrieve it!


Wenn Caddy neu gestartet wurde, sollte man auf dem Crowdsec LAPI Server den Bouncer „sehen“:

root@CrowdSec ~ # cscli bouncers list

caddy 192.168.X.Y ✔️ 2025-02-11T09:36:26Z caddy-cs-bouncer v0.7.0 api-key


Eigentlich würde jetzt alles laufen, aber wir haben im Ordner „/var/log/caddy/“ schöne Logfiles liegen die wir ebenfalls parsen und damit Angriffe erkennen könnten. Ich untersuche die Logfiles der veröffentlichten Services direkt auf den Servern auf denen sie ausgeführt werden. Doch die Logfiles von Caddy selbst wollte ich jetzt auch noch in Crowdsec einbinden. Also muss man Crowdsec installieren und im acquis File die Logs vom Type „caddy“ konfigurieren. Wie gesagt: muss nicht sein, der Bouncer funktioniert und sperrt IPs die von den Services gemeldet werden über die LAPI. Aber wie heisst es so schön: Haben ist besser als brauchen 🙂

curl -s https://install.crowdsec.net | sudo sh
apt update
apt install crowdsec


Nun den Server bei der LAPI anmelden und verbinden:

cscli lapi register --machine caddy --url http://192.168.X.Y:8080/

systemctl reload crowdsec


Auf dem Crowdsec Server die Instanz des Caddyservers validieren:

cscli machines validate caddy

Dann die Collection für „caddy“ installieren und das acquis File editieren:

cscli collections install crowdsecurity/caddy

cat /etc/crowdsec/acquis.yaml

filenames:
- /var/log/caddy/*.log
labels:
type: caddy


Am besten den ganzen Service Crowdsec neu starten und im Logfile nachsehen ob alles erkannt wird:

systemctl restart crowdsec

time="2025-02-11T09:59:29+01:00" level=info msg="Adding file /var/log/caddy/subdomain-access.log to datasources" type=file


Nun ist neben dem Bouncer in Caddy mit Verbindung zum LAPI Server auch ein Logparser aktiv der die Ergebnisse an die LAPI meldet. Gibt es einen Treffer, wird von der LAPI aus eine Sperrung der IP bei den Bouncern veranlasst.
Viel Spaß bei der Umsetzung!

Migration eines Windows Server von VMware zu Proxmox

Ich habe einen standalone Server mit VMwre und musste die darauf befindlichen VMs auf einen neuen Server mit Proxmox migrieren. Ich beschreibe hier meinen Weg und hoffe damit anderen einiges an Recherche zu ersparen. Zum Übertragen der VMDKs der VMs habe ich eine SAS Festplatte im Wechselrahmen mit 14 TB genutzt. Da es zwei Server vom gleichen Hersteller sind, konnte ich die Wechselfestplatte in beiden Servern nutzen.

Exemplarisches Vorgehen mit einer Test-VM mit Windows Server 2019:

– shutdown der VM auf dem VMware Server
– clonen der VM auf die SAS Festplatte
– einbinden der geclonten VM als „Server2019-clone“ ohne aktivierte Netzwerkkarte
– starten der VM zum deinstallieren der VMware Tools
– shutdown der VM und entfernen aus dem VMware Repository
– SAS Festplatte vom VMware Server beim Proxmox Server einbinden (mounten unter /mnt)
– unter Proxmox eine VM für Windows Server 2019 erzeugen und darin keine virtuelle Festplatte anlegen (oder anlegen und direkt wieder löschen)
– die VMDK vom Server 2019 muss im Format „RAW“ auf der Konsole in eine leere VM importiert werden: qm importdisk 101 /mnt/Server2019.vmdk local-lvm –format raw
– die Festplatte erscheint unter „Hardware“ als „detached“ und muss in der neuen Proxmox VM als SATA Festplatte eingebunden werden
– unter „Optionen“ die Festplatte als bootfähig markieren und auf die erste Stelle verschieben. Nun die VM booten und danach die VirtIO-Guest-Tools installieren (link)


– jetzt kann man den SCSI- und Netzwerktreiber nutzen. Dazu wieder ein shutdown der VM und die Netzwerkkarte auf VirtIO Adapter umstellen. Damit der SCSI Treiber installiert wird, muss man einen Trick anwenden. Eine 2GB grosse Festplatte hinzufügen mit SCSI. Dann die VM booten und warten bis die Treiber installiert sind. Jetzt die VM wieder herunterfahren, die 2GB Festplatte entfernen und die bootfähige Systemfestplatte der VM ebenfalls entfernen (detach) und direkt wieder als SCSI Festplatte hinzufügen.
– die VM booten und kontrollieren das alle Treiber erkannt und geladen wurden:


Ich hoffe das mein Leitfaden bei euch auch zum gewünschten Ergebnis führt. Bei mir hat sich dieses Vorgehen als der beste und schnellste Weg herausgestellt. Nur kurz zur Erklärung warum man die VMware Tools noch unter VMware entfernen muss: die Tools erkennen nur VMware als Virtual Host und verweigern unter Hardware oder Proxmox die Ausführung mit der Meldung „muss in einer VM ausgeführt werden“. Damit hat man keine Chance den Deinstaller zu starten und muss die Tools sehr unschön aus dem System entfernen und man sieht unter Programme immer noch die Fragmente der Installation. Daher kurz in VMware einbinden, deinstallieren und wieder aus VMware entfernen. Damit hat man die Tools sauber aus dem System und der Programmliste entfernt.

OPNsense 24.7 mit ZFS und Snapshots

Jetzt sind auch Snapshots der kompletten Firewall über die GUI möglich. Gerade bei Installationen auf Hardware ist das ein Feature, mit dessen Hilfe sich bei fehlerhaften Firmwareupdates oder Fehlkonfigurationen, extrem schnell wieder der vorherige „known-good“ Zustand herstellen lässt:


Voraussetzung dafür ist die Verwendung des Dateisystems ZFS. Systeme mit UFS muss man unter Verwendung von ZFS neu installieren. Vorher ein Konfigurationsbackup machen und per USB Stick bei der Installation wieder einspielen (config.xml). Das ganze geht super easy und schnell. Wenn das System später durch eine Fehlkonfiguration nicht mehr über die GUI erreichbar ist, kann man den entsprechenden Snapshot beim Booten auswählen:

Weitere Infos unter: https://docs.opnsense.org/manual/snapshots.html


Proxmox Linux VM: konsistentes Backup mit fsfreeze (freeze/thaw)

Wenn man ein virtuelles Linuxsystem sichert, wird das meistens mit dem Verfahren „snapshot“ erledigt. Gerade bei VMs mit Datenbanken hat man dann evtl. einen inkonsistenten Zustand. Mit dem installierten QEMU Guest Agent wird beim Auslösen des Snapshots ein Script vor und nach dem Snapshot ausgeführt. Genau hier kann man dann Dienste in der VM für den Zeitpunkt des Snapshots anhalten oder einfrieren und somit einen konsistenten Zustand der Daten herstellen. Im Log sieht man folgenden Eintrag:

101: 2024-10-12 21:00:03 INFO: issuing guest-agent 'fs-freeze' command
101: 2024-10-12 21:00:04 INFO: issuing guest-agent 'fs-thaw' command

In der VM mit den QEMU Guest Agent wird folgendes Script ausgeführt:

/etc/qemu/fsfreeze-hook

Durch dieses Script werden Scripte im Ordner „/etc/qemu/fsfreeze-hook.d“ mit den Parametern „freeze“ und „thaw“ ausgeführt. Hier ein Demoscript von mir, mit dem ich Docker Container vor dem Snapshot pausiere und danach wieder weiterlaufen lasse:

cat /etc/qemu/fsfreeze-hook.d/script.sh

#!/bin/bash
case "$1" in
freeze)
#Commands for freeze
docker pause $(docker ps -a -q)
;;
thaw)
#Commands for thaw
docker unpause $(docker ps -a -q)
;;
*)
echo $"Neither freeze nor thaw provided"
exit 1
;;
esac

Leider wird bei einer Ubuntu VM das Script nicht ausgeführt, weil ein wichtiger Eintrag in der Konfigurationsdatei vom QEMU Guest Agent fehlt:

fsfreeze-hook=/etc/qemu/fsfreeze-hook

Die Konfigurationsdatei fehlt bei Ubuntu vollkommen und muss erst erzeugt werden. Keine Ahnung wie es bei anderen Distributionen ist, aber bei Debian/Ubuntu scheint man die laut Proxmox Forum erst erzeugen zu müssen:

qemu-ga -D > /etc/qemu/qemu-ga.conf

Nun kann man den fehlenden Verweis auf die Scriptdatei einfügen und den QEMU Guest Agent Dienst neu starten. Schon funktioniert das Einfrieren und Auftauen der Dienste bei einem Snapshot:

systemctl restart qemu-guest-agent.service