diff --git a/CHANGELOG.md b/CHANGELOG.md index bac3851..e4f949f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,28 @@ getaggte Releases (Kanal `stable`, optional `beta`) — niemals Entwicklungs-Bui _Keine offenen Änderungen — der nächste Stand wird hier gesammelt und als `vX.Y.Z` getaggt._ +## [0.9.27] - 2026-06-20 + +### Hinzugefügt +- **Anmeldeschutz — Brute-Force-Sperre für das Panel-Login selbst.** Nach zu vielen fehlgeschlagenen + Anmelde- oder 2FA-Versuchen wird die Quell-IP zeitlich gesperrt (Standard: 10 Versuche in 10 Min → + 60 Min Sperre). Durchgesetzt auf HTTP-Ebene für **nicht angemeldete** Anfragen — eingeloggte + Operatoren werden nie geblockt und können ihre eigene IP weiterhin im Panel entsperren. (Eigenständig + von der Flotten-fail2ban-Verwaltung, die entfernte Server härtet.) +- **Neuer Einstellungs-Reiter „Anmeldeschutz"** (Einstellungen → Anmeldeschutz): An/Aus, max. Versuche, + Zeitfenster, Bann-Dauer, Whitelist (IP/CIDR), Liste aktiver Sperren mit Entsperren / Alle entsperren, + plus „Meine IP zur Whitelist hinzufügen". +- **Host-Befehl `clusev unban ` (`--all`)** als Notfall-Ausweg, falls man sich aussperrt — analog + zu `clusev reset-admin`. +- Fehlgeschlagene Logins und 2FA-Versuche sowie Sperren/Entsperrungen landen jetzt im **Audit-Log** + (`auth.login_failed`, `auth.2fa_failed`, `auth.ip_banned`, `auth.ip_unbanned`). + +### Sicherheit +- Loopback und private Netze sind standardmäßig ausgenommen (gegen Selbst-Aussperrung). Der + IP-Vergleich erfolgt kanonisch (inet_pton; IPv4-mapped-IPv6 wird auf die IPv4-Form zusammengefasst), + damit eine Sperre nicht über zwei Schreibweisen derselben Adresse umgangen werden kann. Sperren sind + immer zeitlich begrenzt — es gibt keinen permanenten Lockout. + ## [0.9.26] - 2026-06-20 ### Hinzugefügt diff --git a/config/clusev.php b/config/clusev.php index 90053f6..17efd47 100644 --- a/config/clusev.php +++ b/config/clusev.php @@ -2,7 +2,7 @@ return [ // First tagged release is v0.1.0 (semantic, not -dev). - 'version' => '0.9.26', + 'version' => '0.9.27', // Deployed commit + branch. install.sh bakes these into .env from the host's .git (the prod // image ships no .git); the Versions page prefers them and falls back to a live .git read in