Hiawatha vor einem Hilde-Dienst
Was Hiawatha ist und warum Hilde ihn nutzt
Hiawatha ist ein quelloffener Webserver von Hugo Leisink. Er ist auf Sicherheit, einfache Bedienung und wenig Ressourcen ausgelegt. Er kann FastCGI, TLS und HTTP/2, schreibt URLs um, arbeitet als Proxy und wehrt SQL-Injection, XSS, CSRF und Exploit-Versuche von sich aus ab. Er läuft unter Linux, den BSDs und macOS. Die Dokumentation steht in hiawatha(1), auf seiner Website und in seinem Quelltext.
Für alles, was in Hilde gebaut wird, ist Hiawatha der Webserver der Wahl. Heiko Zimmermann, der Hilde entwickelt, betreibt Hiawatha seit 2010 und arbeitet inzwischen selbst daran mit. Ein Hilde-Programm hört nicht selbst im Netz, sondern bedient FastCGI auf einem Unix-Socket. Hiawatha nimmt die Verbindungen an, übernimmt TLS, liefert die statischen Dateien aus und gibt jede andere Anfrage an den Socket weiter. So laufen alle Dienste, die in Hilde gebaut sind.
Im Überblick:
Browser --TLS--> Hiawatha (:443) --FastCGI über einen Unix-Socket--> das Hilde-Programm
Worum es hier geht
Diese Seite nennt die Einstellungen von Hiawatha, die ein Hilde-Dienst braucht, jeweils mit Begründung und Herkunft. Die Beispiele stammen von einem OpenID-Provider, der in Hilde geschrieben ist und unter dem Host auth.example.org läuft. init aus Standard.Doctor gibt die Blöcke FastCGIserver und UrlToolkit für einen Dienst mit Socket aus.
Hiawatha liest seine Konfiguration nur beim Start, ein Reload gibt es nicht. Nach einer Änderung prüft man sie mit hiawatha -k und startet Hiawatha dann neu (rcctl restart hiawatha unter OpenBSD, systemctl restart hiawatha unter Linux).
Globale Einstellungen (hiawatha.conf, außerhalb jedes VirtualHost)
| Einstellung | Wert | Warum |
|---|---|---|
MaxUrlLength | 8192 | Beim Logout steht ein ID-Token mit ML-DSA-44 in der Query (id_token_hint). Hiawatha erlaubt standardmäßig 1000 Zeichen und beantwortet eine längere URL mit 414, bevor der Dienst sie überhaupt sieht. Gemessen auf einer Testinstanz: ID-Token 3688 Byte, Logout-URL 3710 Zeichen, mit dem Standardwert als 414 abgewiesen, mit 8192 beantwortet. Die Einstellung gilt für den ganzen Server, ein VirtualHost kann sie nicht setzen (hiawatha(1)). |
Der FastCGI-Server und das Toolkit
FastCGIserver {
FastCGIid = Auth
ConnectTo = /var/run/auth/auth.sock
}
UrlToolkit {
ToolkitId = auth
Match ^/static/[A-Za-z0-9._-]+$ Exit
Match ^/favicon\.ico$ Exit
Match .* UseFastCGI Auth
}
ConnectToist der Socket, den der Dienst anlegt, so wie er in dessen Konfiguration steht. Der Socket gehört der Gruppe, unter der Hiawatha läuft (wwwunter OpenBSD).- Die Dateien unter dem Website-Root liefert Hiawatha selbst aus (
Exit), jeder andere Pfad geht an den Dienst. - Bindet Hiawatha ein Verzeichnis mit Konfigurationsdateien ein, liest er es vollständig, auch eine Kopie mit der Endung
.bak. Eine Kopie, die nicht gelten soll, gehört deshalb in ein anderes Verzeichnis, nicht neben die Datei.
Der virtuelle Host
VirtualHost {
Hostname = auth.example.org
WebsiteRoot = /usr/local/share/auth/www
UseToolkit = auth
RequireTLS = yes, 31536000; includeSubDomains
TLScertFile = tls/auth.example.org.pem
BanByCGI = yes, 3600
HTTPAuthToCGI = yes
CustomHeaderClient = X-Content-Type-Options: nosniff
CustomHeaderClient = Referrer-Policy: no-referrer
CustomHeaderClient = X-Frame-Options: DENY
}
| Einstellung | Warum |
|---|---|
HTTPAuthToCGI = yes | Nur damit gibt Hiawatha den Header Authorization an FastCGI weiter. Ein Client eines OpenID-Providers meldet sich an /token mit client_secret_basic in genau diesem Header an. |
BanByCGI = yes, <seconds> | Der Dienst kann Hiawatha nach wiederholt fehlgeschlagenen Anmeldungen eine Adresse sperren lassen. Die Sekunden sind die längste erlaubte Sperre, die Sperrzeit des Dienstes darf also nicht darüber liegen. |
RequireTLS, TLScertFile | Der Dienst setzt Cookies mit Secure und __Host-, und die behält ein Browser nur über TLS. |
CustomHeaderClient | Für die statischen Dateien, die Hiawatha selbst ausliefert. Auf seinen eigenen Seiten setzt der Dienst dieselben Header. |
Wie Hiawatha eingegrenzt ist
- Hiawatha hält seinen Dateizugriff bewusst eng: mit seiner eigenen Sandbox und unter Linux mit einem AppArmor-Profil, wenn das System eines mitbringt. Eine Änderung an der Konfiguration darf ihm keinen Pfad öffnen, den er vorher nicht gebraucht hat.
- In seiner Sandbox nimmt er keine Signale von außen an. Läuft er in einem Container, endet er mit dem Container.
- Ein Test, der Hiawatha braucht, startet ihn in einem eigenen Container und nie gegen einen Hiawatha, der andere bedient.
Nur für Lastmessungen
Wer einen Dienst hinter Hiawatha misst, setzt ThreadPoolSize = 50, ListenBacklog = 128, ConnectionsPerIP und ConnectionsTotal = 1000, MaxKeepAlive = 1000 am Binding und SetResourceLimits = no. Sonst misst man die Grenzen von Hiawatha statt des Dienstes. Für den Produktivbetrieb sind das keine Einstellungen.