dev: Monitoring-Plan — Nachtrag fehlgeschlagene Anmeldungen (Befund, Auswertung) und Einrichtung des externen Monitors (Uptime Kuma, ntfy, zweite Ebene)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-10-06 15:30:29 +00:00
parent 05535aac37
commit 2c25eea045

View file

@ -203,3 +203,89 @@ Einträge in [`../glitch-tip/README.md`](../glitch-tip/README.md). Befunde:
Testsuite meldete an die echte DSN (behoben, `2f02acc`), Search-Console-Lauf
robuster (`a90f24a`), Registrierung mit Alpine-Fehler, Promise-Ablehnungen
lesbar, Tippfehler bei artisan nicht mehr gemeldet (`16af374`).
### 06.10.2026 — Nachtrag 1.7: fehlgeschlagene Anmeldungen
Befund auf Live (05.10. 15:26 – 06.10. 16:25): rund 250 Fehlversuche aus
53 Quellen, **alle** `unknown_account`, kein falsches Passwort, keine Sperre,
gleichmäßig auch nachts — verteiltes, langsames Durchprobieren fremder
Zugangsdaten („low and slow“, jede Quelle bleibt unter der Sperre von
5/Minute). Kein Konto betroffen. Die Einträge verdeckten im Verlauf die
relevanten Fälle. Das Nginx-Zugriffsprotokoll der Site ist bei Ploi aus,
der Einstieg ließ sich so nicht klären.
Umgesetzt:
- `meta.entry` an jedem Fehlversuch, jeder Sperre und jedem 2FA-Fehler:
`livewire` (Formular), `fortify` (`POST /login`, alle Domains, auch JSON),
`two-factor`, sonst `other`.
- Unbekannte Adressen nicht mehr im Verlauf, sondern in `failed_login_tallies`
(Tag × Einstieg × IP-Hash → Versuche, erster/letzter Zeitpunkt). Löschfrist
90 Tage über `model:prune` (täglich 04:05).
- Systemstatus-Kachel „Anmeldeversuche mit unbekannter Adresse“ (heute/gestern,
Versuche und Quellen); `warn` ab `MONITORING_FAILED_LOGIN_WARN_PER_DAY` (1000).
Auswertung auf Live (nach dem Deploy):
```bash
php artisan tinker --execute '
DB::table("failed_login_tallies")
->where("day", ">=", now()->subDays(7)->toDateString())
->selectRaw("day, entry, count(*) as quellen, sum(attempts) as versuche")
->groupBy("day", "entry")->orderBy("day")->orderBy("entry")
->get()
->each(fn ($r) => print(sprintf("%s %-10s %4d Quellen %5d Versuche\n", $r->day, $r->entry, $r->quellen, $r->versuche)));
'
```
Danach entscheiden: überwiegend `fortify` → `POST /login` auf den Hub
beschränken bzw. je IP drosseln (vorher klären, wer den JSON-Login nutzt);
überwiegend `livewire` → Honeypot/Turnstile im Formular.
### Externer Monitor auf `/health` — Einrichtung (offen)
Ziel: Ausfälle melden, die die App selbst nicht melden kann (Server weg,
PHP-FPM hängt, Scheduler steht, Platte voll). **Uptime Kuma** auf dem
GlitchTip-Server (`178.105.154.106`); die App läuft auf `178.105.240.70` —
ein anderer Server, also echte Außensicht. ntfy liegt auf demselben Server
wie Uptime Kuma; fällt dieser aus, kommt kein Push (siehe Schritt 6).
1. **Installation** (Docker, neben GlitchTip, hinter demselben Reverse Proxy,
z. B. `status.adametz.media`):
```yaml
services:
uptime-kuma:
image: louislam/uptime-kuma:1
restart: unless-stopped
volumes:
- ./uptime-kuma:/app/data
ports:
- "127.0.0.1:3001:3001"
```
Admin-Konto beim ersten Aufruf anlegen, 2FA in den Einstellungen aktivieren.
2. **Benachrichtigung** (Settings ▸ Notifications ▸ ntfy): Server
`https://push.adametz.media`, Topic `pressekonto-ops`, Priorität 4,
Authentifizierung „Access Token“ mit dem Token von `pressekonto-alerts`.
Zusätzlich SMTP-Mail an das Ops-Postfach.
3. **Monitor „pressekonto /health“**: Typ HTTP(s), URL
`https://pressekonto.com/health`, Methode GET, Header (JSON)
`{"Authorization": "Bearer <MONITORING_HEALTH_TOKEN aus der Live-.env>"}`,
Intervall 60 s, Wiederholungen 2 (Retry-Intervall 60 s), akzeptierte
Statuscodes `200-299`. 503 = mindestens ein Check kritisch, Details in der
JSON-Antwort.
4. **Monitore „Domains“** ohne Token, Typ HTTP(s) - Keyword oder HTTP(s):
`https://presseecho.de/up`, `https://businessportal24.com/up`,
`https://pressekonto.com/up` — prüft Nginx/SSL/PHP je Domain, Intervall 5 min.
Zertifikatsablauf-Warnung aktivieren (Settings ▸ „Certificate Expiry Notification“, 14 Tage).
5. **Test:** Einen zweiten Monitor mit absichtlich falschem Token anlegen —
`/health` antwortet dann 404, der Alarm muss auf dem Handy und per Mail
ankommen. Danach diesen Test-Monitor löschen. Beim nächsten Deploy zeigt
der echte Monitor die Wartungsphase (`down` → 503) als kurzen Ausfall.
6. **Zweite Ebene (optional, empfohlen):** ein kostenloser externer Dienst
(z. B. UptimeRobot) mit einem einfachen Monitor auf `https://pressekonto.com/up`
und Mail-Benachrichtigung. Er meldet, wenn der Monitoring-Server selbst
ausfällt oder beide Server gemeinsam nicht erreichbar sind.
Nach der Einrichtung: Punkt 29 in `deploy-v1.1.0.md` und Phase 1 hier als erledigt eintragen.