integrity_scanner_fuer_stat.../BEDIENUNGSANLEITUNG.md
Your Name 5769f3fc88 docs: Bedienungsanleitung hinzufügen
Vollständige Bedienungsanleitung für den täglichen Betrieb, Erstinbetriebnahme,
Alarm-Workflows, Cron-Setup, E-Mail-Konfiguration und Konfigurationsreferenz.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 03:28:36 +02:00

542 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bedienungsanleitung — Website Integrity Scanner
Überwachungswerkzeug für die statische Website **bredelar.info** gegen SEO-Spam und
unbefugte Manipulationen. Der Scanner läuft lokal im Verantwortungsbereich des Betreibers.
---
## Inhaltsverzeichnis
1. [Grundprinzip](#1-grundprinzip)
2. [Voraussetzungen und Installation](#2-voraussetzungen-und-installation)
3. [Erstinbetriebnahme](#3-erstinbetriebnahme)
4. [Täglicher Betrieb](#4-täglicher-betrieb)
5. [Befehle im Überblick](#5-befehle-im-überblick)
6. [Ergebnis-Level und Exit-Codes](#6-ergebnis-level-und-exit-codes)
7. [Berichte lesen](#7-berichte-lesen)
8. [Änderungen freigeben (approve)](#8-änderungen-freigeben-approve)
9. [Vorgehen bei einem Alarm](#9-vorgehen-bei-einem-alarm)
10. [Automatisierung per Cron-Job](#10-automatisierung-per-cron-job)
11. [E-Mail-Benachrichtigung einrichten](#11-e-mail-benachrichtigung-einrichten)
12. [Konfigurationsreferenz](#12-konfigurationsreferenz)
13. [Externe Domains verwalten](#13-externe-domains-verwalten)
14. [Rausch-Unterdrückung konfigurieren](#14-rausch-unterdrückung-konfigurieren)
15. [Was der Scanner erkennt](#15-was-der-scanner-erkennt)
16. [Verzeichnisstruktur](#16-verzeichnisstruktur)
---
## 1. Grundprinzip
Der Scanner arbeitet nach dem **Baseline-Diff-Prinzip**:
```
Initiale Sichtprüfung → Baseline festlegen
Täglicher Scan
Aktueller Zustand ──vergleiche── genehmigte Baseline
Abweichungen → Score → GREEN / YELLOW / RED
```
- Die **Baseline** ist ein einmal manuell geprüfter und freigegebener Referenzzustand.
Sie wird **niemals automatisch** aktualisiert.
- Jede Abweichung erhält Punkte. Der Gesamt-Score entscheidet über das Alarm-Level.
- Legitime Änderungen (z.B. neuer Artikel) müssen explizit per `approve` freigegeben werden.
---
## 2. Voraussetzungen und Installation
```bash
# Python 3.10 oder neuer erforderlich
python3 --version
# Virtuelle Umgebung anlegen und aktivieren
cd /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten
python3 -m venv venv
source venv/bin/activate
# Abhängigkeiten installieren
pip install -r requirements.txt
```
Alle Befehle müssen aus dem Projektverzeichnis ausgeführt werden (dort liegt `config.yaml`).
---
## 3. Erstinbetriebnahme
### Schritt 1: Ersten Crawl durchführen
```bash
python -m scanner init
```
Die Ausgabe zeigt:
- alle gefundenen internen URLs
- alle externen Domains (mit Hinweis, ob in der Whitelist)
- potenzielle Auffälligkeiten (Hidden Content, Meta-Refresh, verdächtige Scripts)
- Crawl-Fehler (Seiten, die nicht erreichbar waren)
### Schritt 2: Ausgabe manuell prüfen
Wichtig vor dem nächsten Schritt:
- Alle externen Domains prüfen. Legitime Domains in `config/allowed_external.yaml` eintragen
(siehe [Abschnitt 13](#13-externe-domains-verwalten)).
- Auffälligkeiten im Browser nachschauen.
### Schritt 3: Baseline freigeben
Nur wenn alles sauber ist:
```bash
python -m scanner approve --all --note "Initiale Baseline, geprüft am $(date +%Y-%m-%d)"
```
Ab jetzt ist der tägliche Betrieb möglich.
---
## 4. Täglicher Betrieb
### Manueller Scan
```bash
python -m scanner scan
```
Ergebnis erscheint direkt im Terminal. Der vollständige Report liegt in `reports/`.
### Automatischer Scan (Cron)
```bash
# Cron-Eintrag hinzufügen
crontab -e
```
Eintrag:
```cron
# Website-Scan täglich um 03:00 Uhr
0 3 * * * cd /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten && /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/venv/bin/python -m scanner scan >> logs/cron.log 2>&1
```
Der Exit-Code (0/1/2) ist für Cron-basierte Alarmierung nutzbar (z.B. mit `cronitor` oder
systemd-Timern mit `OnFailure=`).
---
## 5. Befehle im Überblick
Alle Befehle werden mit `python -m scanner <befehl>` aufgerufen.
Globale Optionen: `--config path/to/config.yaml`, `--verbose` (`-v`).
| Befehl | Zweck |
|---|---|
| `init` | Erstcrawl, Ausgabe aller Funde, noch kein Baseline-Update |
| `crawl` | Crawlt die Website, speichert Snapshot (kein Vergleich) |
| `check` | Vergleicht letzten Snapshot mit Baseline, erstellt Report |
| `scan` | `crawl` + `check` in einem Schritt (für den Cron-Betrieb) |
| `approve --all` | Alle neuen Snapshot-URLs in die Baseline übernehmen |
| `approve --url URL` | Einzelne URL freigeben |
| `approve --rebuild` | Gesamte Baseline ersetzen (nach großem Redesign) |
| `report` | Letzten Report im Terminal anzeigen |
| `report --format json` | Letzten Report als JSON anzeigen |
| `status` | Baseline-Datum, letzter Scan, aktueller Risk-Level |
### Beispiele
```bash
# Einzelne Seite freigeben (z.B. nach Impressums-Update)
python -m scanner approve --url https://bredelar.info/impressum/ --note "Impressum aktualisiert Juni 2026"
# Alle Änderungen auf einmal freigeben (nur nach vollständiger Prüfung!)
python -m scanner approve --all --note "Redesign vom 2026-06-12 freigegeben"
# Baseline nach komplettem Umbau neu aufbauen
python -m scanner approve --rebuild --note "Komplettes Redesign v2, alle Seiten neu geprüft"
# Bestimmten Snapshot freigeben (statt den neuesten)
python -m scanner approve --all --snapshot data/snapshots/20260612_030000
# Aktuellen Stand prüfen
python -m scanner status
# Letzten Report anzeigen
python -m scanner report
```
---
## 6. Ergebnis-Level und Exit-Codes
| Level | Score | Exit-Code | Bedeutung |
|---|---|---|---|
| **GREEN** | 019 | `0` | Keine Auffälligkeiten |
| **YELLOW** | 2059 | `1` | Warnung — manuelle Prüfung empfohlen |
| **RED** | ≥ 60 | `2` | Alarm — sofortige Prüfung notwendig |
Die Schwellenwerte sind in `config.yaml` unter `thresholds` anpassbar.
---
## 7. Berichte lesen
Reports liegen in `reports/YYYYMMDD_HHMMSS/` als `report.md` und `report.json`.
```bash
# Neuesten Report im Terminal lesen
python -m scanner report
# Direkt die Datei öffnen
ls reports/
cat reports/20260612_030000/report.md
```
### Aufbau des Reports
| Abschnitt | Inhalt |
|---|---|
| **Zusammenfassung** | Kennzahlen auf einen Blick |
| **Risikobewertung** | Alle Gründe für den Score (was hat wie viele Punkte ausgelöst) |
| **Neue externe Domains** | Domains, die bisher nicht in der Baseline waren |
| **Neue interne URLs** | Seiten, die neu dazugekommen sind |
| **Fehlende URLs** | Seiten, die in der Baseline stehen, jetzt aber nicht mehr gefunden wurden |
| **Geänderte Seiten** | Detailansicht: Textänderungen, Link-Diffs, Meta-Änderungen |
| **Kaputte Links** | `[NEU]` = noch nicht in Baseline, `[bekannt]` = schon bekannt, wird nicht bewertet |
| **Unerwartetes JSON-LD** | Strukturierte Daten mit unbekanntem `@type` |
| **Verdächtige Dateinamen** | Links auf Dateien mit Webshell-typischen Namen |
| **Whitelist-Verstösse** | Externe Domains, die nicht in `allowed_external.yaml` stehen |
| **Fehlende Security-Header** | Informativ (kein Score) — nur auf HTTP-200-Seiten |
| **Crawl-Fehler** | URLs, die der Crawler nicht laden konnte |
| **Nächste Schritte** | Abhängig vom Level: konkrete Handlungsempfehlungen |
---
## 8. Änderungen freigeben (approve)
Wann `approve` nötig ist:
- Nach einer legitimen Inhaltsänderung (neuer Artikel, aktualisiertes Impressum, ...)
- Nach einem Redesign
- Nach Bereinigung eines echten Angriffs
### Einzelne URL freigeben
Wenn nur eine bestimmte Seite geändert wurde:
```bash
python -m scanner approve --url https://bredelar.info/veranstaltungen/ \
--note "Veranstaltungskalender aktualisiert"
```
### Alle Änderungen freigeben
Nach Prüfung aller markierten URLs:
```bash
python -m scanner approve --all --note "Monatliches Update geprüft und freigegeben"
```
**Achtung**: `--all` übernimmt alles aus dem letzten Snapshot. Nur anwenden, wenn jede
gemeldete Änderung manuell gesichtet wurde.
### Komplette Baseline neu aufbauen
Nach einem großen Redesign oder nach Bereinigung eines Angriffs:
```bash
python -m scanner approve --rebuild --note "Nach Angriff bereinigt, neues Redesign"
```
`--rebuild` ersetzt die gesamte bestehende Baseline durch den aktuellen Snapshot.
---
## 9. Vorgehen bei einem Alarm
### YELLOW — Warnung
1. Report lesen: `python -m scanner report`
2. Markierte URLs im Browser aufrufen und Quelltext prüfen
3. Ist die Änderung legitim?
- Ja: `python -m scanner approve --url <URL> --note "Grund"`
- Nein: Abschnitt [Angriff](#angriff) lesen
### RED — Alarm
Der Score ist ≥ 60. Typische Auslöser: neue externe Domain (50 Pkt.) + Hidden Content
(40 Pkt.), Webshell-Dateiname (60 Pkt.), Meta-Refresh (40 Pkt.).
#### Angriff
1. **Nicht sofort approve aufrufen** — das würde den kompromittierten Zustand als neue
Baseline festschreiben.
2. Report sichern: `cp -r reports/$(ls reports/ | tail -1) ~/alarm-$(date +%Y%m%d)/`
3. Website im Browser aufrufen und nach sichtbaren Fremdinhalten suchen.
4. Quelltext der betroffenen Seiten prüfen (insbesondere `display:none`-Bereiche).
5. Hoster kontaktieren, SSH-/FTP-Zugriffslogs prüfen.
6. Dateien mit Backup vergleichen (diff oder rsync --dry-run).
7. Nach vollständiger Bereinigung:
```bash
python -m scanner scan # muss GREEN ergeben
python -m scanner approve --rebuild --note "Nach Angriff bereinigt $(date +%Y-%m-%d)"
```
---
## 10. Automatisierung per Cron-Job
### Cron-Eintrag
```bash
crontab -e
```
```cron
# Website-Scan täglich um 03:00 Uhr
0 3 * * * cd /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten && /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/venv/bin/python -m scanner scan >> logs/cron.log 2>&1
```
### Log prüfen
```bash
tail -50 logs/cron.log
tail -f logs/scanner.log # detaillierteres Log des Scanners selbst
```
### Log-Rotation (optional)
Datei `/etc/logrotate.d/integrity-scanner`:
```
/home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/logs/*.log {
daily
rotate 30
compress
missingok
notifempty
}
```
---
## 11. E-Mail-Benachrichtigung einrichten
### config.yaml anpassen
```yaml
alerting:
min_level: "yellow" # oder "red" — nur bei rotem Alarm mailen
email:
enabled: true
smtp_host: "mail.linix.de" # SMTP-Server des Providers
smtp_port: 587
smtp_tls: true
smtp_user: "scanner@linix.de"
smtp_password_env: "SCANNER_SMTP_PASSWORD"
from: "scanner@bredelar.info"
to:
- "dieter.schlueter@linix.de"
```
### Passwort als Umgebungsvariable setzen
**Niemals** das Passwort direkt in `config.yaml` eintragen. Stattdessen:
```bash
# Temporär (bis zum nächsten Login)
export SCANNER_SMTP_PASSWORD="geheimesPasswort"
# Dauerhaft in ~/.bashrc oder ~/.profile
echo 'export SCANNER_SMTP_PASSWORD="geheimesPasswort"' >> ~/.bashrc
```
Für den Cron-Job die Variable in der Crontab oder in `/etc/environment` setzen:
```cron
SCANNER_SMTP_PASSWORD=geheimesPasswort
0 3 * * * cd /home/dschlueter/...
```
---
## 12. Konfigurationsreferenz
Alle Einstellungen in `config.yaml`. Fehlende Werte werden aus den Defaults übernommen.
### Kern-Einstellungen
| Schlüssel | Standard | Bedeutung |
|---|---|---|
| `target` | — | Zu überwachende URL (Pflicht) |
| `user_agent` | `integrity-scanner/1.0` | HTTP User-Agent |
| `request_timeout` | `20` | Timeout pro Seite in Sekunden |
### Crawl-Einstellungen (`crawl:`)
| Schlüssel | Standard | Bedeutung |
|---|---|---|
| `max_pages` | `200` | Maximale Anzahl gecrawlter Seiten |
| `delay_seconds` | `1.0` | Pause zwischen Requests (Server-Schonung) |
| `skip_extensions` | `.jpg`, `.pdf` etc. | Dateitypen, die nicht gecrawlt werden |
### Score-Gewichte (`scoring:`)
| Ereignis | Standard-Punkte |
|---|---|
| Verdächtiger Dateiname (Webshell) | 60 |
| Neue externe Domain | 50 |
| Hidden Content (CSS-verstecktes Element mit Links/Text) | 40 |
| Meta-Refresh | 40 |
| Unerwartete Canonical-URL | 35 |
| Unerwartetes JSON-LD `@type` | 35 |
| Neue interne URL | 30 |
| Neues verdächtiges Inline-Script | 30 |
| Link in HTML-Kommentar | 25 |
| Großer Textblock (>200 Zeichen) | 20 |
| Fehlende interne URL | 20 |
| Neuer kaputte Link (4xx/5xx, nicht in Baseline) | 20 |
Alle Werte sind in `config.yaml` unter `scoring:` anpassbar.
### Alarm-Schwellen (`thresholds:`)
```yaml
thresholds:
yellow: 20 # ab hier: YELLOW
red: 60 # ab hier: RED
large_text_block_chars: 200 # ab dieser Zeichenanzahl gilt ein Textblock als "groß"
```
### Erlaubte JSON-LD-Typen (`allowed_jsonld_types:`)
Alle `@type`-Werte, die in den strukturierten Daten der Website vorkommen dürfen.
Unbekannte Typen lösen einen Fund aus (35 Punkte). Aktuell konfiguriert:
`Organization`, `WebSite`, `WebPage`, `Article`, `BreadcrumbList`, `LocalBusiness`,
`Event`, `FAQPage` u.a.
### Security-Header (`security_headers:`)
Liste der Header, die auf jeder Seite erwartet werden. Fehlende Header werden im Report
gemeldet, aber **nicht** bewertet (kein Score-Einfluss).
---
## 13. Externe Domains verwalten
Datei: `config/allowed_external.yaml`
```yaml
# Legitime externe Domains — eine pro Zeile
- fonts.googleapis.com
- www.kloster-bredelar.de
```
Neue externe Domain erscheint im Scanner:
1. Domain im Browser prüfen — gehört sie zur Website?
2. Wenn legitim: in `config/allowed_external.yaml` eintragen
3. `python -m scanner approve --url <betroffene-Seite>` oder `--all`
Wenn eine Domain **nicht** in der Liste steht, löst jedes Vorkommen 50 Punkte aus
(YELLOW-Alarm, bei weiteren Funden RED).
---
## 14. Rausch-Unterdrückung konfigurieren
Manche Inhalte ändern sich automatisch (Datumsangaben, Zeitstempel) und würden sonst
bei jedem Scan einen Fund auslösen. Zwei Mechanismen:
### CSS-Selektoren ignorieren (`ignore_selectors:`)
Elemente werden vor dem Diff vollständig aus dem DOM entfernt:
```yaml
normalization:
ignore_selectors:
- "#last-modified"
- ".timestamp"
- ".cookie-banner"
```
Datei: direkt in `config.yaml` oder in `config/ignore_rules.yaml` (kommentierte Beispiele
dort vorhanden).
### Text-Muster ignorieren (`ignore_patterns:`)
Reguläre Ausdrücke, die im normalisierten Text durch `[IGNORED]` ersetzt werden:
```yaml
normalization:
ignore_patterns:
- '\b\d{1,2}\.\s*(?:Januar|Februar|März|April|Mai|Juni|Juli|August|September|Oktober|November|Dezember)\s+\d{4}\b'
- '\b\d{1,2}\.\d{1,2}\.\d{4}\b'
- 'Stand:\s+\S+'
```
---
## 15. Was der Scanner erkennt
### Erkennt der Scanner ...
| Prüfung | Erkannt? | Anmerkung |
|---|---|---|
| Neuen Text auf einer Seite | Ja | Ab 200 Zeichen bewertet |
| Versteckten Text (CSS display:none etc.) | Ja | 40 Punkte |
| Neue externe Domain | Ja | 50 Punkte |
| Meta-Refresh-Weiterleitung | Ja | 40 Punkte |
| Webshell-Dateien (shell.php, c99 etc.) | Ja | 60 Punkte |
| Links in HTML-Kommentaren | Ja | 25 Punkte |
| Geänderte Canonical-URL | Ja | 35 Punkte |
| Unbekanntes JSON-LD `@type` | Ja | 35 Punkte |
| `eval()`, `atob()`, `XMLHttpRequest` in Scripts | Ja | 30 Punkte |
| Kaputte interne Links (neu) | Ja | 20 Punkte |
| Kaputte interne Links (bekannt) | Ja, informativ | Kein Score |
| Fehlende Security-Header | Ja, informativ | Kein Score |
| Kaputte **externe** Links | Nein | Nur ob Domain neu ist |
| Veränderungen in Bilddateien | Nein | Nur Dateiname/URL |
| Serverseitige Code-Änderungen | Nein | Nur sichtbare HTML-Ausgabe |
### Grenzen des Scanners
- Er prüft nur, was der Crawler als HTML-Seite sieht. Serverseitig eingeschleuster Code,
der nur unter bestimmten Bedingungen aktiv wird (z.B. nur für Suchmaschinen-Bots),
wird möglicherweise nicht erkannt.
- Bilder und andere Binärdateien werden nicht auf Inhalt geprüft.
- Externe Links werden nur auf Neuheit geprüft, nicht auf Erreichbarkeit.
---
## 16. Verzeichnisstruktur
```
config.yaml Hauptkonfiguration
config/
allowed_external.yaml Whitelist erlaubter externer Domains
ignore_rules.yaml Kommentierte Beispiele für Rausch-Unterdrückung
data/
baseline/ Freigegebene Referenz (NIEMALS automatisch geändert)
manifest.json Wer/was/wann freigegeben hat
pages/ Pro URL eine JSON-Datei (16-stelliger Hex-Name)
snapshots/ Ein Verzeichnis pro Crawl-Durchlauf
YYYYMMDD_HHMMSS/
manifest.json Zeitstempel, Seitenzahl, Fehler
pages/ Extrahierte Seiten-Daten
logs/
scanner.log Detailliertes Laufzeit-Log
cron.log Ausgabe der Cron-Ausführungen
reports/
YYYYMMDD_HHMMSS/
report.md Menschenlesbarer Report
report.json Maschinenlesbarer Report (für spätere Auswertung)
scanner/ Python-Paket (Quellcode)
tests/ Automatisierte Tests
```
### Tests ausführen
```bash
pytest tests/ -v # alle Tests
pytest tests/test_differ.py -v # einzelnes Testmodul
pytest tests/test_differ.py::TestScoreDiff::test_green_for_no_changes -v # einzelner Test
```