🇩🇪 Dieser Artikel ist auf Deutsch. An English version will follow as a separate post.
BunkerWeb ist eine Open-Source Web Application Firewall (WAF) auf Basis von NGINX bzw. OpenResty: Sie sitzt als Reverse Proxy vor euren Webanwendungen, terminiert TLS, kümmert sich auf Wunsch automatisch um Let’s-Encrypt-Zertifikate und bringt von Haus aus Schutzmechanismen wie ModSecurity mit dem OWASP Core Rule Set, Bad-Behavior-Erkennung, Ratelimiting, Country-Blocking und einiges mehr mit.
Bisher war BunkerWeb vor allem eine Docker-/Linux-Geschichte. Seit ich das Projekt auf FreeBSD portiert habe, gibt es BunkerWeb als offiziellen Port www/bunkerweb im FreeBSD Ports Tree, und damit ist die Installation nur noch ein pkg install entfernt. In diesem Artikel zeige ich, wie ihr BunkerWeb auf einem frischen FreeBSD-System installiert, die Dienste startet und die Ersteinrichtung durchlauft.
Voraussetzungen
- FreeBSD 14.x oder 15.x
- Root-Zugriff bzw.
sudo/doas - Eine aktuelle Paketquelle (die offiziellen FreeBSD-Repositories oder ein eigenes Poudriere-Repo)
BunkerWeb läuft auf FreeBSD gegen OpenResty (www/openresty) als Web-Server-Runtime, das zieht die Installation automatisch als Abhängigkeit mit, ihr müsst euch darum nicht kümmern. Dazu kommt ein Python-Unterbau (aktuell Python 3.12) für Scheduler, Web-UI und API.
Installation
Die Installation selbst ist unspektakulär, genau so soll es sein:
pkg install bunkerweb
Wer lieber aus den Ports baut:
cd /usr/ports/www/bunkerweb
make install clean
Das Paket bringt vier Dienste mit, die über eigene rc-Skripte gesteuert werden:
| Dienst | Aufgabe |
|---|---|
bunkerweb | Die eigentliche WAF (OpenResty/NGINX) |
bunkerweb_scheduler | Generiert die Konfiguration, verwaltet Jobs und Zertifikate |
bunkerweb_ui | Die Weboberfläche zur Verwaltung |
bunkerweb_api | Optionale REST-API zur Fernsteuerung |
Dienste aktivieren und starten
Zuerst aktivieren wir die Dienste für den Systemstart:
sysrc bunkerweb_scheduler_enable=YES
sysrc bunkerweb_ui_enable=YES
sysrc bunkerweb_enable=YES
Die API lasse ich hier bewusst außen vor, dazu gleich mehr.
Beim Start ist die Reihenfolge wichtig: Der Scheduler muss zuerst laufen, denn er generiert die Konfiguration, die die anderen Komponenten benutzen:
service bunkerweb_scheduler start
service bunkerweb_ui start
service bunkerweb start
Beim ersten Start legt der Scheduler automatisch selbstsignierte Default-Zertifikate und eine interne Root-CA an, das dauert einen kurzen Moment.
Danach lauschen folgende Ports:
- 8080/8443: hier nimmt die WAF den eigentlichen HTTP-/HTTPS-Traffic entgegen (8443 zusätzlich per QUIC/HTTP-3)
- 7000: die Web-UI für die Verwaltung
Ein kurzer Test, ob alles läuft:
service bunkerweb_scheduler status
service bunkerweb_ui status
service bunkerweb status
Alle drei sollten is running melden. Im Log (/var/log/bunkerweb/error.log) begrüßt euch BunkerWeb dann mit der Zeile „BunkerWeb is ready to fool hackers“. Mission erfüllt.
Exkurs: Warum die API standardmäßig nicht startet
Wer bunkerweb_api_enable=YES setzt und den Dienst startet, wird feststellen: Er beendet sich sofort wieder. Das ist kein Fehler, sondern Absicht. Die API verweigert den Start, solange keine Authentifizierung konfiguriert ist, sie geht lieber gar nicht online als ungeschützt.
Es gibt drei Wege, sie abzusichern:
API_TOKEN: ein statisches Bearer-Token mit Vollzugriff, gesetzt über die Umgebung (auf FreeBSD z. B. viabunkerweb_api_envin derrc.conf)- Admin-API-Benutzer: Username/Passwort, beim ersten Start über
API_USERNAME/API_PASSWORDangelegt, danach in der Datenbank - Biscuit-Keys mit ACL: feingranulare Berechtigungen über kryptografische Token
Für den normalen Betrieb mit Web-UI braucht ihr die API nicht, Scheduler, UI und WAF kommunizieren intern. Wer BunkerWeb per Skript oder Automatisierung fernsteuern will, fängt am einfachsten mit einem zufällig generierten API_TOKEN an.
Ersteinrichtung über den Setup Wizard
Jetzt geht es in den Browser: http://<server-ip>:7000 leitet euch auf den Setup Wizard. Der führt in vier Schritten durch die Grundeinrichtung:
Schritt 1, Admin-Konto: Benutzername und ein ordentliches Passwort. Optional lässt sich hier später auch Zwei-Faktor-Authentifizierung (TOTP) aktivieren.
Schritt 2, UI-Einstellungen: Hier wird es interessant. Der Server name ist der Hostname, unter dem die UI später über die WAF selbst erreichbar sein soll, denn BunkerWeb routet intern über den Host-Header. Eine IP funktioniert für rein internen Zugriff; wer der UI ein Let’s-Encrypt-Zertifikat geben will, braucht einen echten FQDN.
Außerdem konfiguriert ihr hier die Let’s-Encrypt-Defaults. Zwei Hinweise aus der Praxis:
- Steht euer BunkerWeb hinter einer Firewall und ist nicht direkt aus dem Internet erreichbar, wählt als Challenge Type
dnsstatthttp. Die DNS-01-Validierung läuft über TXT-Records bei eurem DNS-Provider (BunkerWeb bringt Plugins für Hetzner, Cloudflare, OVH und viele weitere mit), der Server selbst muss dafür von außen nicht erreichbar sein. - Zum Experimentieren lohnt sich der Schalter Let’s Encrypt Staging: Die Rate-Limits der Produktivumgebung sind schneller erschöpft, als man denkt, wenn ein DNS-Plugin noch zickt.
Die Werte hier sind übrigens nur Voreinstellungen, pro Service lassen sie sich später einzeln übersteuern.
Schritt 3, PRO Features: Kann leer übersprungen werden. Ein Lizenzschlüssel lässt sich jederzeit später in der globalen Konfiguration nachtragen.
Schritt 4, Übersicht: Einstellungen prüfen, abschließen, einloggen. Fertig.
Das typische Setup: BunkerWeb hinter der Firewall
Ein Wort zur Architektur, denn die Ports 8080/8443 sind kein Zufall: BunkerWeb ist dafür gedacht, hinter eurer Firewall zu sitzen. Das Muster sieht so aus:
Internet
│ 443/80
▼
Firewall (pfSense, OPNsense, …)
│ DNAT bzw. TCP-Passthrough auf 8443/8080
▼
BunkerWeb (FreeBSD-VM)
│ TLS-Terminierung, WAF-Regeln, Let’s Encrypt
▼
Backend-VMs (WordPress, Nextcloud, …), intern, plain HTTP
Die Firewall reicht 443 und 80 einfach an BunkerWeb durch und terminiert selbst kein TLS mehr. BunkerWeb übernimmt Zertifikate und Schutz zentral für alle dahinterliegenden Dienste, und die Backends selbst bleiben komplett intern. Pro Backend legt ihr in der UI einen „Service“ an (Hostname, Upstream, gewünschte Schutzfunktionen) und BunkerWeb generiert die passende NGINX-Konfiguration selbst.
Die Web-UI auf Port 7000 gehört dabei nicht ins Internet. Die bleibt intern, per VPN, Management-Netz oder schlicht per interner IP.
Fazit
BunkerWeb fühlt sich auf FreeBSD inzwischen wie zuhause an: pkg install, drei sysrc-Zeilen, drei service start, Wizard durchklicken, und ihr habt eine vollwertige WAF mit automatischer Zertifikatsverwaltung im Rack, ganz ohne Docker. Genau so soll Software-Paketierung auf FreeBSD aussehen.
In einem Folgeartikel zeige ich, wie man den ersten Service anlegt und eine Webanwendung komplett hinter BunkerWeb betreibt, inklusive Let’s Encrypt per DNS-01 und dem Zusammenspiel mit pfSense.
Bei Fragen zum Port: Der Maintainer bin ich, Feedback, Bug-Reports und PRs zu www/bunkerweb sind jederzeit willkommen.
Wenn deine Firma mit meinen Ports Geld verdient oder dir dieser Artikel geholfen hat, freue ich mich über eine Spende, die Links findest du in der Seitenleiste.