feat!: Migration auf Go-Binary

BREAKING CHANGE: Die alte Shell-Version muss vor der Installation der Go-Version deinstalliert werden.
This commit is contained in:
Patrick Asmus
2026-05-01 00:08:57 +02:00
parent 0d1f7db43b
commit 4f17f7ff81
50 changed files with 8012 additions and 9496 deletions

View File

@@ -1,15 +1,59 @@
# Dokumentation
Hier findest du die vollständige Dokumentation zu AdGuard Shield.
Willkommen in der Dokumentation von AdGuard Shield.
## Inhaltsverzeichnis
AdGuard Shield ist ein Go-Daemon, der das Query Log von AdGuard Home auswertet, auffällige DNS-Clients erkennt und diese über eine eigene Firewall-Struktur sperrt. Die Dokumentation ist bewusst ausführlich gehalten: Sie soll nicht nur Befehle auflisten, sondern erklären, was im Hintergrund passiert, welche Werte sinnvoll sind und wie du Fehler sauber eingrenzt.
| Dokument | Beschreibung |
## Schnellnavigation
| Dokument | Wofür es gedacht ist |
|---|---|
| [Architektur & Funktionsweise](architektur.md) | Überblick über den Systemaufbau, Datenfluss und die internen Komponenten |
| [Befehle & Nutzung](befehle.md) | Alle verfügbaren Befehle des Installers, des Hauptskripts und des Watchdogs |
| [Konfiguration](konfiguration.md) | Beschreibung aller Konfigurationsparameter in `adguard-shield.conf` |
| [Webhook-Benachrichtigungen](benachrichtigungen.md) | Einrichtung von Push-Benachrichtigungen über Telegram, Discord, Gotify u.a. |
| [E-Mail Report](report.md) | Konfiguration des automatischen Statistik-Reports per E-Mail |
| [Update-Anleitung](update.md) | Schritt-für-Schritt-Anleitung zum Aktualisieren einer bestehenden Installation |
| [Tipps & Troubleshooting](tipps-und-troubleshooting.md) | Best Practices, häufige Probleme und deren Lösungen |
| [Architektur & Funktionsweise](architektur.md) | Erklärt den Aufbau, den Datenfluss, Firewall, SQLite, Hintergrundjobs und Sperrlogik |
| [Befehle & Nutzung](befehle.md) | Vollständige CLI-Referenz mit typischen Betriebsabläufen |
| [Konfiguration](konfiguration.md) | Alle Parameter aus `adguard-shield.conf` mit Beispielen und Empfehlungen |
| [Docker-Installationen](docker.md) | Firewall-Modi für klassische Installation, Docker Host Network und veröffentlichte Docker-Ports |
| [Benachrichtigungen](benachrichtigungen.md) | Einrichtung von Ntfy, Discord, Slack, Gotify und Generic Webhooks |
| [E-Mail Report](report.md) | Report-Inhalte, Mailversand, Cron-Job und manuelle Tests |
| [Update-Anleitung](update.md) | Update der Go-Version und Migration von alten Shell-Installationen |
| [Tipps & Troubleshooting](tipps-und-troubleshooting.md) | Diagnosewege für API, Firewall, GeoIP, Reports, Listen und falsch gesetzte Sperren |
## Wichtigster Unterschied zur alten Shell-Version
Die frühere Version bestand aus mehreren Shell-Skripten, Hilfs-Workern, Cron-Jobs und einem separaten Watchdog. Die Go-Version bündelt diese Aufgaben in einem einzelnen Binary:
```text
/opt/adguard-shield/adguard-shield
```
Dieses Binary ist gleichzeitig:
- Daemon für den produktiven Betrieb
- CLI für Status, History, Logs, Firewall, Listen, GeoIP und Reports
- Installer, Updater und Uninstaller
- Report-Generator
- Hintergrundprozess für externe Whitelist, externe Blocklist, GeoIP und Offense-Cleanup
Die meisten Befehle beginnen daher mit:
```bash
sudo /opt/adguard-shield/adguard-shield <befehl>
```
Für Installation oder Update nutzt du das neue Binary aus dem Repository, Release oder Build-Verzeichnis:
```bash
sudo ./adguard-shield install
sudo ./adguard-shield update
```
## Empfohlener Lesefluss
Wenn du AdGuard Shield neu einrichtest:
1. Lies zuerst [Architektur & Funktionsweise](architektur.md), damit klar ist, was genau gesperrt wird.
2. Passe danach [Konfiguration](konfiguration.md) an, besonders API-Zugang, Whitelist und Rate-Limits.
3. Nutze [Befehle & Nutzung](befehle.md) für Installation, Dry-Run und Service-Start.
4. Richte optional [Benachrichtigungen](benachrichtigungen.md), [Reports](report.md), GeoIP oder externe Listen ein.
5. Bei Problemen hilft [Tipps & Troubleshooting](tipps-und-troubleshooting.md).
Wenn du von der alten Shell-Version kommst, beginne mit [Update-Anleitung](update.md).

View File

@@ -1,232 +1,407 @@
# Architektur & Funktionsweise
## Überblick
Dieses Dokument erklärt, wie AdGuard Shield intern arbeitet. Es geht dabei nicht nur um die Dateien auf dem System, sondern auch um den Weg einer DNS-Anfrage vom AdGuard-Home-Querylog bis zur Firewall-Sperre.
```
┌─────────────────────┐
│ Client Anfragen │
│ (DNS/DoH/DoT/DoQ) │
└──────────┬──────────┘
┌─────────────────────┐ ┌──────────────────────┐
│ AdGuard Home │────▶ │ Query Log (API) │
│ DNS Server │ └──────────┬───────────┘
└─────────────────────┘ │
┌──────────────────────┐
│ adguard-shield.sh │
│ (Monitor Script) │
└──────────┬───────────┘
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ iptables │ │ Log │ │ Webhook │
│ DROP │ │ Datei │ │ Notify │
└──────────┘ └──────────┘ └──────────┘
## Kurzüberblick
AdGuard Shield besteht in der Go-Version aus einem einzelnen Binary:
```text
/opt/adguard-shield/adguard-shield
```
## Ablauf einer Sperre
Das Binary übernimmt alle Aufgaben, die früher auf mehrere Shell-Skripte verteilt waren:
### Rate-Limit-Sperre
- Querylog-Polling über die AdGuard-Home-API
- Erkennung von Rate-Limit-Verstößen
- Erkennung von Random-Subdomain-Floods
- DNS-Flood-Watchlist mit sofortigem Permanent-Ban
- Verwaltung aktiver Sperren in SQLite
- Firewall-Steuerung über `ipset`, `iptables` und `ip6tables`
- automatische Freigabe abgelaufener temporärer Sperren
- externe Blocklisten und externe Whitelists
- GeoIP-Länderfilter
- progressive Sperren für Wiederholungstäter
- Benachrichtigungen und AbuseIPDB-Reporting
- E-Mail-Reports
1. Client `192.168.1.50` fragt `microsoft.com` 45x in 60 Sekunden an
2. Monitor fragt die AdGuard Home API alle 10 Sekunden ab (`/control/querylog`)
3. Die Anfragen werden pro Client+Domain-Kombination gezählt
4. Monitor erkennt: 45 > 30 (Limit überschritten)
5. Prüfung: Ist der Client auf der Whitelist? → Nein
6. **Progressive Sperren:** Offense-Level wird geprüft/erhöht, Sperrdauer berechnet
7. iptables-Regel wird erstellt: `DROP` für `192.168.1.50` auf allen DNS-Ports
8. State-Datei wird angelegt: `/var/lib/adguard-shield/192.168.1.50.ban`
9. Offense-Datei wird aktualisiert: `/var/lib/adguard-shield/192.168.1.50.offenses`
10. Ban-History Eintrag wird in `/var/log/adguard-shield-bans.log` geschrieben
11. Log-Eintrag + optionale Webhook-Benachrichtigung
12. Nach Ablauf der (progressiven) Sperrdauer: automatische Entsperrung + History-Eintrag
## Datenfluss
### Subdomain-Flood-Sperre (Random Subdomain Attack)
1. Client `10.0.0.99` fragt `abc123.microsoft.com`, `xyz456.microsoft.com`, ... ab
2. Monitor extrahiert die **Basisdomain** (`microsoft.com`) aus jeder Anfrage
3. Pro Client wird gezählt, wie viele **eindeutige Subdomains** einer Basisdomain im Zeitfenster abgefragt wurden
4. Monitor erkennt: 63 eindeutige Subdomains > 50 (Schwellwert überschritten)
5. Prüfung: Ist der Client auf der Whitelist? → Nein
6. Sperre wird ausgeführt mit Domain `*.microsoft.com` und Grund `subdomain-flood`
7. Progressive Sperren greifen auch hier — Wiederholungstäter werden stufenweise länger gesperrt
> **Hinweis:** Die Subdomain-Flood-Erkennung hat ein eigenes Zeitfenster (`SUBDOMAIN_FLOOD_WINDOW`) und einen eigenen Schwellwert (`SUBDOMAIN_FLOOD_MAX_UNIQUE`), unabhängig von den Rate-Limit-Einstellungen.
### DNS-Flood-Watchlist-Sperre
1. Client `10.0.0.42` fragt `microsoft.com` 35x in 60 Sekunden an
2. Monitor erkennt: 35 > 30 (Limit überschritten)
3. Domain `microsoft.com` steht auf der DNS-Flood-Watchlist → **sofortige permanente Sperre**
4. Progressive-Ban-Stufe wird ignoriert — kein stufenweises Hochstufen
5. IP wird an AbuseIPDB gemeldet (falls aktiviert)
6. Permanente Sperre bleibt bis zur manuellen Freigabe aktiv
> **Hinweis:** Die Watchlist greift sowohl bei normalen Rate-Limit-Verstößen als auch bei Subdomain-Flood-Erkennungen. Subdomains werden automatisch erkannt: `foo.microsoft.com` matcht den Watchlist-Eintrag `microsoft.com`.
## iptables Strategie
Das Tool erstellt eine eigene Chain `ADGUARD_SHIELD`:
```
INPUT Chain
├── ... (bestehende Regeln bleiben unberührt)
├── -p tcp --dport 53 → ADGUARD_SHIELD
├── -p udp --dport 53 → ADGUARD_SHIELD
├── -p tcp --dport 443 → ADGUARD_SHIELD
├── -p udp --dport 443 → ADGUARD_SHIELD
├── -p tcp --dport 853 → ADGUARD_SHIELD
├── -p udp --dport 853 → ADGUARD_SHIELD
└── ...
ADGUARD_SHIELD Chain
├── -s 192.168.1.50 → DROP (gesperrter Client)
├── -s 10.0.0.25 → DROP (gesperrter Client)
└── RETURN (alle anderen passieren)
```text
Clients
|
| DNS, DoH, DoT, DoQ, DNSCrypt
v
AdGuard Home
|
| /control/querylog
v
AdGuard Shield Go-Daemon
|
|-- Rate-Limit-Prüfung pro Client + Domain
|-- Subdomain-Flood-Prüfung pro Client + Basisdomain
|-- Watchlist-Prüfung
|-- Whitelist-Prüfung
|-- GeoIP-Prüfung
|-- externe Listen
v
SQLite State
|
v
ipset + iptables/ip6tables
|
v
DNS-relevante Ports werden für gesperrte Clients blockiert
```
**Vorteile der eigenen Chain:**
- Greift nicht in bestehende Firewall-Regeln ein
- Kann komplett geflusht werden ohne andere Regeln zu beeinflussen
- Einfaches Debugging per `iptables -L ADGUARD_SHIELD`
Wichtig: AdGuard Shield analysiert nicht den Netzwerkverkehr direkt. Es liest das Querylog von AdGuard Home. Dadurch erkennt es auch Anfragen über moderne DNS-Protokolle, solange diese in AdGuard Home sichtbar sind.
## State-Management (SQLite)
## Laufzeit im produktiven Betrieb
Alle Laufzeitdaten werden in einer zentralen SQLite-Datenbank gespeichert:
Der systemd-Service startet den Daemon so:
```bash
/opt/adguard-shield/adguard-shield -config /opt/adguard-shield/adguard-shield.conf run
```
Beim Start passiert in dieser Reihenfolge:
1. Konfiguration wird geladen.
2. SQLite-Datenbank unter `STATE_DIR` wird geöffnet oder angelegt.
3. Logdatei wird geöffnet.
4. Firewall-Chain und ipsets werden vorbereitet.
5. GeoIP-Datenbank wird geöffnet, falls GeoIP aktiv ist.
6. Whitelist-Cache wird aus SQLite geladen.
7. GeoIP-Sperren werden gegen die aktuelle GeoIP-Konfiguration geprüft.
8. Aktive Sperren aus SQLite werden wieder in die Firewall geschrieben.
9. Hintergrundjobs für externe Whitelist, externe Blocklist und Offense-Cleanup starten, falls aktiviert.
10. Der zentrale Querylog-Poller beginnt mit der regelmäßigen Auswertung.
Das Reconcile beim Start ist wichtig: Wenn der Server neu startet oder iptables-Regeln verloren gehen, bleiben die Sperren in SQLite erhalten und werden beim nächsten Start wieder in die Firewall übertragen.
## Querylog-Poller
Der Daemon ruft regelmäßig den AdGuard-Home-Endpunkt ab:
```text
/control/querylog?limit=<API_QUERY_LIMIT>&response_status=all
```
Gesteuert wird das über:
```bash
CHECK_INTERVAL=10
API_QUERY_LIMIT=500
```
Aus jedem Querylog-Eintrag werden diese Informationen extrahiert:
| Feld | Verwendung |
|---|---|
| Zeitstempel | Bestimmt, ob die Anfrage im aktuellen Zeitfenster liegt |
| Client-IP | Schlüssel für Rate-Limit, Whitelist, GeoIP und Firewall |
| Domain | Schlüssel für Rate-Limit und Subdomain-Flood |
| `client_proto` | Anzeige von DNS, DoH, DoT, DoQ oder DNSCrypt |
Bereits gesehene Querylog-Einträge werden im Speicher dedupliziert. Der Daemon hält nur Ereignisse aus dem relevanten Zeitfenster plus kleinem Puffer vor.
## Rate-Limit-Sperre
Eine Rate-Limit-Sperre entsteht, wenn ein Client dieselbe Domain innerhalb des konfigurierten Fensters zu oft abfragt.
Beispiel:
```bash
RATE_LIMIT_MAX_REQUESTS=30
RATE_LIMIT_WINDOW=60
```
Ablauf:
1. Client `192.168.1.50` fragt `example.com` 45-mal innerhalb von 60 Sekunden ab.
2. Der Poller sieht diese Einträge im Querylog.
3. AdGuard Shield zählt pro Client und Domain.
4. `45 > 30`, also ist das Limit überschritten.
5. Die IP wird gegen statische und externe Whitelists geprüft.
6. Falls die Domain nicht auf der Watchlist steht, entsteht eine normale `rate-limit`-Sperre.
7. Bei aktivem Progressive-Ban wird die aktuelle Offense-Stufe berechnet.
8. Die IP wird in SQLite gespeichert und per Firewall blockiert.
9. History, Log und optionale Benachrichtigung werden geschrieben.
## Subdomain-Flood-Erkennung
Random-Subdomain-Floods sehen anders aus als normale Wiederholungen. Ein Client fragt nicht eine Domain ständig neu ab, sondern viele zufällige Subdomains:
```text
a8f3.example.com
k29x.example.com
z9p1.example.com
```
AdGuard Shield extrahiert daraus die Basisdomain `example.com` und zählt pro Client, wie viele unterschiedliche Subdomains im Fenster vorkommen.
Gesteuert wird das über:
```bash
SUBDOMAIN_FLOOD_ENABLED=true
SUBDOMAIN_FLOOD_MAX_UNIQUE=50
SUBDOMAIN_FLOOD_WINDOW=60
```
Ablauf:
1. Client `10.0.0.99` fragt 63 verschiedene Subdomains von `example.com` ab.
2. Direkte Anfragen an `example.com` zählen für diese Erkennung nicht.
3. Sobald mehr als `SUBDOMAIN_FLOOD_MAX_UNIQUE` eindeutige Subdomains erkannt werden, wird gesperrt.
4. In der History erscheint die Domain als `*.example.com`.
5. Der Grund lautet `subdomain-flood`, außer die Basisdomain steht auf der DNS-Flood-Watchlist.
## DNS-Flood-Watchlist
Die Watchlist ist für Domains gedacht, bei denen du nicht stufenweise reagieren möchtest. Wenn eine Domain auf der Watchlist steht und gleichzeitig ein Rate-Limit- oder Subdomain-Flood-Verstoß erkannt wird, wird sofort permanent gesperrt.
```bash
DNS_FLOOD_WATCHLIST_ENABLED=true
DNS_FLOOD_WATCHLIST="microsoft.com,google.com"
```
Matching:
- `microsoft.com` matcht `microsoft.com`
- `login.microsoft.com` matcht ebenfalls `microsoft.com`
- `evil-microsoft.com` matcht nicht
Bei einem Treffer:
- Reason wird `dns-flood-watchlist`
- Sperre ist permanent
- Progressive-Ban-Stufen werden für die Dauer ignoriert
- AbuseIPDB-Reporting kann ausgelöst werden, wenn es aktiviert und ein API-Key vorhanden ist
## Progressive Sperren
Progressive Sperren erhöhen die Sperrdauer bei wiederholten Monitor-Sperren. Das Verhalten ähnelt fail2ban.
Standard:
```bash
BAN_DURATION=3600
PROGRESSIVE_BAN_ENABLED=true
PROGRESSIVE_BAN_MULTIPLIER=2
PROGRESSIVE_BAN_MAX_LEVEL=5
PROGRESSIVE_BAN_RESET_AFTER=86400
```
Beispiel:
| Vergehen | Stufe | Dauer |
|---|---:|---|
| 1 | 1 | 1 Stunde |
| 2 | 2 | 2 Stunden |
| 3 | 3 | 4 Stunden |
| 4 | 4 | 8 Stunden |
| 5 | 5 | permanent |
Der Offense-Zähler wird in SQLite gespeichert. Wenn eine IP länger als `PROGRESSIVE_BAN_RESET_AFTER` nicht auffällig war, kann der Cleanup sie entfernen.
Progressive Sperren gelten für Monitor-Sperren. GeoIP- und externe Blocklist-Sperren haben eigene Regeln.
## Firewall-Modell
AdGuard Shield nutzt eine eigene Chain und zwei ipsets:
```text
ADGUARD_SHIELD
adguard_shield_v4
adguard_shield_v6
```
Die Chain wird je nach `FIREWALL_MODE` in die passende Host-Chain eingehängt:
| Modus | Parent-Chain |
|---|---|
| `host` / `docker-host` | `INPUT` |
| `docker-bridge` | `DOCKER-USER` |
| `hybrid` | `INPUT` und `DOCKER-USER` |
Für klassische Installationen und Docker mit Host-Netzwerk sieht das so aus:
```text
INPUT
|- tcp/53 -> ADGUARD_SHIELD
|- udp/53 -> ADGUARD_SHIELD
|- tcp/443 -> ADGUARD_SHIELD
|- udp/443 -> ADGUARD_SHIELD
|- tcp/853 -> ADGUARD_SHIELD
|- udp/853 -> ADGUARD_SHIELD
ADGUARD_SHIELD
|- src in adguard_shield_v4 -> DROP
|- src in adguard_shield_v6 -> DROP
```
Bei Docker Bridge mit veröffentlichten Ports ersetzt `DOCKER-USER` die `INPUT`-Chain im oberen Teil des Diagramms. Docker leitet solche Pakete nach DNAT über `FORWARD`; `INPUT` sieht sie dort nicht zuverlässig.
Die Ports kommen aus:
```bash
BLOCKED_PORTS="53 443 853"
```
Das blockiert klassische DNS-Anfragen und die üblichen Ports für DoH, DoT und DoQ. Die Erkennung selbst basiert weiterhin auf dem AdGuard-Home-Querylog.
Warum `ipset`?
- viele gesperrte IPs erzeugen nicht tausende einzelne iptables-Regeln
- IPv4 und IPv6 werden getrennt sauber verwaltet
- Sperren und Freigaben sind schneller
- die eigene Chain bleibt übersichtlich
## SQLite-State
Der zentrale Zustand liegt standardmäßig hier:
```text
/var/lib/adguard-shield/adguard-shield.db
```
Die Datenbank enthält folgende Tabellen:
Wichtige Tabellen:
| Tabelle | Beschreibung |
|---------|--------------|
| `active_bans` | Aktive Sperren (IP, Domain, Sperrdauer, Offense-Level, Grund, Quelle, GeoIP) |
| `offense_tracking` | Offense-Zähler für progressive Sperren (Level, letztes/erstes Vergehen) |
| `ban_history` | Vollständige Ban-History (alle Sperren und Entsperrungen) |
| `whitelist_cache` | Cache der aufgelösten externen Whitelist-IPs |
| `schema_version` | Datenbank-Schema-Version für zukünftige Migrationen |
| Tabelle | Inhalt |
|---|---|
| `active_bans` | aktuell aktive Sperren mit IP, Grund, Dauer, Quelle und Ablaufzeit |
| `ban_history` | dauerhafte Historie von `BAN`, `UNBAN` und `DRY` |
| `offense_tracking` | Progressive-Ban-Stufen pro Client-IP |
| `whitelist_cache` | aufgelöste IPs aus externen Whitelists |
| `geoip_cache` | gecachte GeoIP-Ergebnisse |
**Vorteile gegenüber Flat-Files:**
- Schnellere Abfragen, besonders bei vielen aktiven Sperren
- Atomare Transaktionen — kein Datenverlust bei Stromausfall
- WAL-Modus für parallelen Lese-/Schreibzugriff
- Indexierte Suche nach IP, Zeitstempel, Quelle und Aktion
- Kompakte Speicherung statt tausender Einzeldateien
Die Datenbank nutzt WAL-Modus und einen Busy-Timeout, damit Daemon und CLI-Befehle gleichzeitig lesen können.
Die zentrale Datenbankbibliothek (`db.sh`) wird von allen Scripts per `source db.sh` eingebunden und stellt typisierte Funktionen für alle Tabellen bereit (z.B. `db_ban_insert`, `db_offense_get_level`, `db_history_add`).
## Verzeichnisstruktur
### Migration von Flat-Files
Nach einer Standardinstallation sieht die Struktur so aus:
Beim Update auf die SQLite-Version werden bestehende Flat-File-Daten (`.ban`, `.offenses`, Ban-History-Log, Whitelist-Cache) automatisch in die Datenbank migriert. Die alten Dateien werden als Backup nach `/var/lib/adguard-shield/.backup_pre_sqlite/` verschoben. Die Migration läuft einmalig beim Update und zeigt den Fortschritt im Terminal an.
## Dateistruktur nach Installation
```
```text
/opt/adguard-shield/
├── adguard-shield.sh # Haupt-Monitor-Script
├── adguard-shield.conf # Konfiguration (chmod 600)
├── adguard-shield.conf.old # Backup der Konfig nach Update
── adguard-shield-watchdog.sh # Watchdog Health-Check-Script
├── iptables-helper.sh # iptables Verwaltung
├── external-blocklist-worker.sh # Externer Blocklist-Worker
├── external-whitelist-worker.sh # Externer Whitelist-Worker (DNS-Auflösung)
├── geoip-worker.sh # GeoIP-Länderfilter-Worker
├── offense-cleanup-worker.sh # Aufräumen abgelaufener Offense-Zähler (nice 19, idle I/O)
├── db.sh # SQLite Datenbank-Bibliothek (wird von allen Scripts eingebunden)
├── unban-expired.sh # Cron-basiertes Entsperren
└── geoip/ # Auto-Download MaxMind GeoLite2 DB (optional)
├── adguard-shield # Go-Binary
├── adguard-shield.conf # Konfiguration, chmod 600
├── adguard-shield.conf.old # Backup nach Konfigurationsmigration
── geoip/ # automatische MaxMind-Downloads
/etc/systemd/system/
── adguard-shield.service # systemd Service (Autostart aktiv)
├── adguard-shield-watchdog.service # systemd Watchdog-Unit (oneshot)
└── adguard-shield-watchdog.timer # systemd Timer (alle 5 Min.)
── adguard-shield.service
/var/lib/adguard-shield/
├── adguard-shield.db # SQLite-Datenbank (Bans, Offenses, History, Whitelist-Cache)
├── .migration_v1_complete # Marker: Flat-File-Migration abgeschlossen
├── .backup_pre_sqlite/ # Backup der alten Flat-Files nach Migration
├── external-blocklist/ # Cache für externe Blocklisten
── external-whitelist/ # Cache für externe Whitelisten
└── geoip-cache/ # Cache für GeoIP-Lookups (24h)
├── adguard-shield.db
├── external-blocklist/
├── external-whitelist/
├── iptables-rules.v4
── iptables-rules.v6
/var/log/
── adguard-shield.log # Laufzeit-Log
└── adguard-shield-bans.log # Ban-History (Legacy, wird nach Migration nicht mehr geschrieben)
── adguard-shield.log
```
## Installer-Architektur
## Hintergrundjobs im Daemon
Der Installer (`install.sh`) bietet ein interaktives Menü und folgende Funktionen:
Es gibt in der Go-Version keine separaten Worker-Skripte mehr. Diese Aufgaben laufen als Goroutines im Daemon:
| Befehl | Beschreibung |
|--------|--------------|
| `install` | Vollständige Neuinstallation (Abhängigkeiten, Dateien, Konfiguration, Service, Watchdog) |
| `update` | Update mit automatischer Konfigurations-Migration, Datenbank-Migration, Watchdog-Aktivierung und Service-Neustart |
| `uninstall` | Deinstallation mit optionalem Behalten der Konfiguration |
| `status` | Installationsstatus, Version und Service-Status anzeigen |
| `--help` | Hilfe und Befehlsübersicht |
| Aufgabe | Wann aktiv | Zweck |
|---|---|---|
| Querylog-Poller | immer | liest und analysiert AdGuard-Home-Querylogs |
| externe Whitelist | `EXTERNAL_WHITELIST_ENABLED=true` | lädt Listen, löst Hostnamen auf, aktualisiert Whitelist-Cache |
| externe Blocklist | `EXTERNAL_BLOCKLIST_ENABLED=true` | lädt Listen, sperrt gewünschte IPs und hebt entfernte IPs optional auf |
| Offense-Cleanup | `PROGRESSIVE_BAN_ENABLED=true` | entfernt abgelaufene Offense-Zähler |
| GeoIP-Lookups | `GEOIP_ENABLED=true` | prüft neue öffentliche Client-IPs gegen Länderregeln |
### Konfigurations-Migration beim Update
Externe Whitelist und Blocklist laufen sofort beim Start einmalig und danach im jeweiligen Intervall.
```
┌─────────────────────────┐ ┌─────────────────────────┐
│ Bestehende Konfig │ │ Neue Konfig (Repo) │
│ (Benutzer-Settings) │ │ (mit neuen Parametern) │
└───────────┬─────────────┘ └───────────┬─────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────┐
│ Konfigurations-Migration │
│ 1. Backup als .conf.old erstellen │
│ 2. Alle Schlüssel vergleichen │
│ 3. Neue Schlüssel zur Konfig ergänzen │
│ 4. Bestehende Werte NICHT ändern │
└──────────────────────┬───────────────────┘
┌──────────────────────────┐
│ Aktualisierte Konfig │
│ (alte Werte + neue Keys) │
└──────────────────────────┘
```
## Whitelist-Logik
## Ban-History
Vor jeder Sperre wird geprüft, ob die IP vertrauenswürdig ist.
Jede Sperre und Entsperrung wird dauerhaft in der SQLite-Datenbank protokolliert (Tabelle `ban_history`). Das ermöglicht eine lückenlose Nachvollziehbarkeit mit indexierter Suche nach IP, Zeitstempel und Aktion.
Quellen:
**Gespeicherte Felder pro Eintrag:**
| Feld | Beschreibung |
|------|--------------|
| `timestamp_epoch` | Unix-Zeitstempel |
| `timestamp_text` | Lesbarer Zeitstempel |
| `action` | `BAN` oder `UNBAN` |
| `client_ip` | Betroffene IP-Adresse |
| `domain` | Angefragte Domain |
| `count` | Anzahl der Anfragen |
| `duration` | Sperrdauer |
| `protocol` | Verwendetes DNS-Protokoll |
| `reason` | Sperrgrund |
- statische `WHITELIST` aus der Konfiguration
- aufgelöste IPs aus externen Whitelists
**Mögliche Gründe (GRUND-Spalte):**
| Grund | Bedeutung |
|-------|----------|
| `rate-limit` | Automatische Sperre wegen Limit-Überschreitung |
| `subdomain-flood` | Sperre wegen zu vieler eindeutiger Subdomains einer Basisdomain |
| `dns-flood-watchlist` | Sofortige permanente Sperre + AbuseIPDB-Meldung (Domain auf der Watchlist) |
| `dry-run` | Im Dry-Run erkannt (nicht wirklich gesperrt) |
| `dry-run (subdomain-flood)` | Subdomain-Flood im Dry-Run erkannt |
| `dry-run (dns-flood-watchlist)` | Watchlist-Treffer im Dry-Run erkannt |
| `expired` | Automatisch entsperrt nach Ablauf der Sperrdauer |
| `expired-cron` | Entsperrt durch den Cron-Job (`unban-expired.sh`) |
| `manual` | Manuell entsperrt per `unban`-Befehl |
| `manual-flush` | Entsperrt durch `flush`-Befehl (alle Sperren aufgehoben) |
Eine gewhitelistete IP wird nicht gesperrt. Wenn eine externe Whitelist später eine bereits gesperrte IP enthält, hebt der Daemon diese Sperre automatisch auf.
## GeoIP-Logik
GeoIP arbeitet nur mit öffentlichen IPs, wenn `GEOIP_SKIP_PRIVATE=true` gesetzt ist. Private Netze, Loopback, Link-Local und CGNAT werden übersprungen.
Modi:
| Modus | Verhalten |
|---|---|
| `blocklist` | Länder aus `GEOIP_COUNTRIES` werden gesperrt |
| `allowlist` | nur Länder aus `GEOIP_COUNTRIES` sind erlaubt, alle anderen öffentlichen Länder werden gesperrt |
GeoIP-Sperren sind permanent, werden aber beim Start gegen die aktuelle Konfiguration geprüft. Wenn GeoIP deaktiviert wird, der Modus wechselt oder ein Land nicht mehr blockiert werden müsste, kann die Sperre automatisch aufgehoben werden.
## AbuseIPDB-Reporting
AbuseIPDB wird nur für permanente Monitor-Sperren genutzt:
- DNS-Flood-Watchlist-Treffer
- Progressive-Ban-Sperren, die die maximale Stufe erreicht haben
Nicht gemeldet werden:
- temporäre Rate-Limit-Sperren
- manuelle Sperren
- GeoIP-Sperren
- externe Blocklist-Sperren
Voraussetzung:
**History anzeigen:**
```bash
sudo /opt/adguard-shield/adguard-shield.sh history # letzte 50
sudo /opt/adguard-shield/adguard-shield.sh history 200 # letzte 200
ABUSEIPDB_ENABLED=true
ABUSEIPDB_API_KEY="..."
```
## History und Logs
Es gibt zwei unterschiedliche Blickwinkel:
| Quelle | Inhalt |
|---|---|
| `ban_history` in SQLite | Sperren, Freigaben und Dry-Run-Ereignisse |
| `LOG_FILE` | Daemon-Ereignisse, Worker-Läufe, Warnungen, Fehler |
Query-Inhalte werden nicht dauerhaft in die Logdatei geschrieben. Für aktuelle Queries gibt es die Live-Ansicht:
```bash
sudo /opt/adguard-shield/adguard-shield live
```
History:
```bash
sudo /opt/adguard-shield/adguard-shield history
sudo /opt/adguard-shield/adguard-shield history 200
```
Logs:
```bash
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
sudo journalctl -u adguard-shield -f
```
## Unterschied zur alten Shell-Architektur
Früher gab es unter anderem:
- `adguard-shield.sh`
- `iptables-helper.sh`
- `external-blocklist-worker.sh`
- `external-whitelist-worker.sh`
- `geoip-worker.sh`
- `offense-cleanup-worker.sh`
- `report-generator.sh`
- `unban-expired.sh`
- Watchdog-Service und Watchdog-Timer
In der Go-Version gibt es diese Skripte nicht mehr. Der systemd-Service nutzt `Restart=on-failure`; die eigentlichen Worker laufen im Daemon. Alte Artefakte werden vom Installer erkannt und müssen vor der Go-Installation entfernt werden, damit keine zwei Implementierungen parallel dieselbe Firewall und dieselben Dateien verwalten.

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,47 @@
# Webhook-Benachrichtigungen
# Benachrichtigungen
Das Tool kann beim Starten und Stoppen des Services sowie bei Sperren und Entsperrungen Benachrichtigungen an verschiedene Dienste senden.
AdGuard Shield kann Ereignisse an Ntfy, Discord, Slack, Gotify oder einen eigenen Webhook senden. Benachrichtigungen sind optional und werden über `adguard-shield.conf` gesteuert.
## Aktivierung
Typische Ereignisse:
In der Konfiguration (`adguard-shield.conf`):
- Service gestartet
- Service gestoppt
- automatische Sperre
- manuelle Sperre
- GeoIP-Sperre
- externe Blocklist-Sperre, falls separat aktiviert
- Freigabe
- Bulk-Freigabe, zum Beispiel durch `flush`
## Grundkonfiguration
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="<typ>"
NOTIFY_WEBHOOK_URL="<url>"
NOTIFY_TYPE="ntfy"
```
Mögliche Typen:
```text
ntfy
discord
slack
gotify
generic
```
Nach Änderungen:
```bash
sudo systemctl restart adguard-shield
```
Zum Prüfen kannst du den Service neu starten oder im Dry-Run eine Erkennung auslösen.
## Ntfy
Ntfy ist der einfachste Einstieg, weil kein komplexer Webhook-Body benötigt wird.
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="ntfy"
@@ -23,28 +51,29 @@ NTFY_TOKEN=""
NTFY_PRIORITY="4"
```
> **Hinweis:** Bei Ntfy wird `NOTIFY_WEBHOOK_URL` nicht benötigt Server-URL und Topic werden separat konfiguriert.
Eigene Ntfy-Instanz:
**Eigene Ntfy-Instanz:**
```bash
NTFY_SERVER_URL="https://ntfy.mein-server.de"
NTFY_SERVER_URL="https://ntfy.example.com"
NTFY_TOPIC="dns-security"
NTFY_TOKEN="tk_mein_geheimer_token"
NTFY_TOKEN="tk_geheimer_token"
```
**Prioritäten:**
| Wert | Bedeutung |
|------|-----------|
| 1 | Minimum |
| 2 | Niedrig |
| 3 | Standard |
| 4 | Hoch |
| 5 | Maximum |
Prioritäten:
**Token erstellen (Self-hosted):**
1. Ntfy Web-UI → Benutzer/Tokens
2. Token kopieren und in `NTFY_TOKEN` eintragen
3. Bei ntfy.sh: Account erstellen → Access Token generieren
| Wert | Bedeutung |
|---:|---|
| `1` | Minimum |
| `2` | Niedrig |
| `3` | Standard |
| `4` | Hoch |
| `5` | Maximum |
Hinweise:
- Bei `NOTIFY_TYPE="ntfy"` wird `NOTIFY_WEBHOOK_URL` nicht verwendet.
- Bei privaten Topics oder eigener Instanz ist ein Token empfehlenswert.
- Der Topic-Name sollte nicht öffentlich erratbar sein.
## Discord
@@ -54,21 +83,16 @@ NOTIFY_TYPE="discord"
NOTIFY_WEBHOOK_URL="https://discord.com/api/webhooks/xxx/yyy"
```
**Webhook erstellen:**
1. Discord Server → Servereinstellungen → Integrationen → Webhooks
2. Neuer Webhook → URL kopieren
Webhook erstellen:
## Gotify
1. Discord-Server öffnen.
2. Servereinstellungen öffnen.
3. Integrationen auswählen.
4. Webhooks öffnen.
5. Neuen Webhook erstellen.
6. URL kopieren und in `NOTIFY_WEBHOOK_URL` eintragen.
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="gotify"
NOTIFY_WEBHOOK_URL="https://gotify.example.com/message?token=xxx"
```
**Token erstellen:**
1. Gotify Web-UI → Apps → App erstellen
2. Token kopieren und in die URL einfügen
Discord erhält den Inhalt als `content`.
## Slack
@@ -78,144 +102,223 @@ NOTIFY_TYPE="slack"
NOTIFY_WEBHOOK_URL="https://hooks.slack.com/services/xxx/yyy/zzz"
```
**Webhook erstellen:**
1. Slack App → Incoming Webhooks aktivieren
2. Webhook-URL kopieren
Slack erhält den Inhalt als `text`.
## Generic (eigener Endpoint)
Einrichtung grob:
1. Slack-App mit Incoming Webhooks einrichten.
2. Webhook für den gewünschten Channel aktivieren.
3. Webhook-URL in die Konfiguration kopieren.
## Gotify
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="gotify"
NOTIFY_WEBHOOK_URL="https://gotify.example.com/message?token=xxx"
```
Gotify erhält `title`, `message` und `priority` als Formularwerte.
Token erstellen:
1. Gotify-Weboberfläche öffnen.
2. Apps auswählen.
3. App erstellen.
4. Token in die URL einsetzen.
## Generic Webhook
Für eigene Automatisierung:
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="generic"
NOTIFY_WEBHOOK_URL="https://your-server.com/webhook"
NOTIFY_WEBHOOK_URL="https://example.com/adguard-shield-webhook"
```
Sendet einen POST mit JSON-Body:
AdGuard Shield sendet einen `POST` mit JSON:
```json
{
"message": "🚫 AdGuard Shield Ban auf dns1\n---\nIP: 192.168.1.50\nHostname: client.local\nGrund: 45x microsoft.com in 60s via DNS, Rate-Limit\nDauer: 1h 0m\n\nWhois: https://www.whois.com/whois/192.168.1.50\nAbuseIPDB: https://www.abuseipdb.com/check/192.168.1.50",
"action": "ban",
"title": "AdGuard Shield",
"message": "AdGuard Shield Ban auf dns1\n---\nIP: 192.168.1.50\nHostname: client.local\nGrund: 45x example.com in 60s via DNS, Rate-Limit\nDauer: 1h 0m [Stufe 1/5]\n\nAbuseIPDB: https://www.abuseipdb.com/check/192.168.1.50",
"client": "192.168.1.50",
"domain": "microsoft.com"
"action": "ban"
}
```
## Benachrichtigungen und externe Blocklisten
Mögliche `action`-Werte:
Bei Sperren aus der **externen Blocklist** werden Benachrichtigungen separat über `EXTERNAL_BLOCKLIST_NOTIFY` gesteuert — unabhängig von `NOTIFY_ENABLED`.
| Aktion | Bedeutung |
|---|---|
| `ban` | Sperre |
| `unban` | Freigabe |
| `manual-flush` | Bulk-Freigabe |
| `geoip-flush` | Bulk-Freigabe von GeoIP-Sperren |
| `external-blocklist-flush` | Bulk-Freigabe externer Blocklist-Sperren |
| `service_start` | Service gestartet |
| `service_stop` | Service gestoppt |
| Parameter | Standard | Beschreibung |
|-----------|----------|--------------|
| `EXTERNAL_BLOCKLIST_NOTIFY` | `false` | Benachrichtigungen bei Blocklist-Sperren aktivieren |
## Externe Blocklist und Benachrichtigungen
> **Wichtig:** Bei großen Listen `EXTERNAL_BLOCKLIST_NOTIFY=false` belassen. Beim ersten Sync (oder nach einem `blocklist-flush`) werden alle IPs der Liste auf einmal gesperrt — mit `true` würde das zu einer Nachrichten-Flut im Notification-Channel führen. Nur auf `true` setzen, wenn die Liste sehr klein ist.
Für Sperren aus externen Blocklisten gibt es einen zusätzlichen Schalter:
## Beispiel-Nachrichten
```bash
EXTERNAL_BLOCKLIST_NOTIFY=false
```
Warum separat?
Eine große Blocklist kann beim ersten Sync hunderte oder tausende IPs sperren. Wenn dafür jede Sperre eine Nachricht erzeugt, wird dein Benachrichtigungskanal unbrauchbar.
Empfehlung:
```bash
EXTERNAL_BLOCKLIST_NOTIFY=false
```
Nur bei kleinen, kuratierten Listen:
```bash
EXTERNAL_BLOCKLIST_NOTIFY=true
```
## GeoIP-Benachrichtigungen
GeoIP hat ebenfalls einen eigenen Schalter:
```bash
GEOIP_NOTIFY=true
```
Wenn GeoIP aktiv ist, aber keine Nachrichten für GeoIP-Sperren gesendet werden sollen:
```bash
GEOIP_NOTIFY=false
```
## Bulk-Freigaben
Diese Befehle können viele IPs auf einmal freigeben:
```bash
sudo /opt/adguard-shield/adguard-shield flush
sudo /opt/adguard-shield/adguard-shield geoip-flush
sudo /opt/adguard-shield/adguard-shield blocklist-flush
```
AdGuard Shield sendet dafür nicht eine Nachricht pro IP, sondern eine zusammenfassende Meldung mit der Anzahl der freigegebenen Sperren.
## AbuseIPDB-Hinweis in Nachrichten
Bei permanenten Monitor-Sperren kann AdGuard Shield zusätzlich an AbuseIPDB melden.
Voraussetzungen:
```bash
ABUSEIPDB_ENABLED=true
ABUSEIPDB_API_KEY="..."
```
Wenn eine Meldung ausgelöst wurde, enthält die Ban-Nachricht einen entsprechenden Hinweis. Außerdem enthält jede Ban- und Unban-Nachricht einen Link zur AbuseIPDB-Check-Seite der IP.
AbuseIPDB wird nicht für GeoIP- oder externe Blocklist-Sperren verwendet.
## Beispielinhalte
### Service gestartet
**Überschrift:** ✅ AdGuard Shield
> 🟢 AdGuard Shield v0.9.0 wurde auf dns1 gestartet.
```text
AdGuard Shield v1.0.0 wurde auf dns1 gestartet.
```
### Service gestoppt
**Überschrift:** 🚨 🛡️ AdGuard Shield
> 🔴 AdGuard Shield v0.9.0 wurde auf dns1 gestoppt.
```text
AdGuard Shield v1.0.0 wurde auf dns1 gestoppt.
```
### Watchdog — Service wiederhergestellt
**Überschrift:** 🔄 AdGuard Shield Watchdog
### Rate-Limit-Sperre
> 🔄 AdGuard Shield Watchdog auf dns1
> ---
> Der Service war ausgefallen und wurde automatisch neu gestartet.
> Versuch: 1
```text
AdGuard Shield Ban auf dns1
---
IP: 192.0.2.50
Hostname: client.example.com
Grund: 45x example.com in 60s via DNS, Rate-Limit
Dauer: 1h 0m [Stufe 1/5]
### Watchdog — Recovery fehlgeschlagen
**Überschrift:** 🚨 AdGuard Shield Watchdog
AbuseIPDB: https://www.abuseipdb.com/check/192.0.2.50
```
> 🚨 AdGuard Shield Watchdog auf dns1
> ---
> Der Service konnte NICHT automatisch neu gestartet werden!
> Manuelles Eingreifen erforderlich.
> Fehlversuche: 1
> Letzter Fehler: (systemd Statusausgabe)
### Watchlist-Sperre
### Sperre (Ban)
**Überschrift:** 🚨 🛡️ AdGuard Shield
```text
AdGuard Shield Ban auf dns1
IP wurde an AbuseIPDB gemeldet
---
IP: 192.0.2.51
Hostname: unknown
Grund: 75x microsoft.com in 60s via DoH, DNS-Flood-Watchlist
Dauer: PERMANENT
> 🚫 AdGuard Shield Ban auf dns1
> ---
> IP: 95.71.42.116
> Hostname: example-host.provider.net
> Grund: 153x radioportal.techniverse.net in 60s via DNS, Rate-Limit
> Dauer: 1h 0m [Stufe 1/5]
>
> Whois: https://www.whois.com/whois/95.71.42.116
> AbuseIPDB: https://www.abuseipdb.com/check/95.71.42.116
AbuseIPDB: https://www.abuseipdb.com/check/192.0.2.51
```
Bei permanenter Sperre mit aktiviertem AbuseIPDB-Reporting erscheint zusätzlich:
### GeoIP-Sperre
> 🚫 AdGuard Shield Ban auf dns1
> ⚠️ IP wurde an AbuseIPDB gemeldet
> ---
> IP: 95.71.42.116
> Hostname: example-host.provider.net
> Grund: 153x radioportal.techniverse.net in 60s via DNS, Rate-Limit
> Dauer: PERMANENT [Stufe 5/5]
>
> Whois: https://www.whois.com/whois/95.71.42.116
> AbuseIPDB: https://www.abuseipdb.com/check/95.71.42.116
```text
AdGuard Shield GeoIP-Sperre auf dns1
---
IP: 203.0.113.10
Land: BR
Modus: Blocklist
Dauer: PERMANENT
Bei DNS-Flood-Watchlist-Treffer (sofort permanent, ohne Stufe):
AbuseIPDB: https://www.abuseipdb.com/check/203.0.113.10
```
> 🚫 AdGuard Shield Ban auf dns1
> ⚠️ IP wurde an AbuseIPDB gemeldet
> ---
> IP: 95.71.42.116
> Hostname: example-host.provider.net
> Grund: 45x microsoft.com in 60s via DNS, DNS-Flood-Watchlist
> Dauer: PERMANENT
>
> Whois: https://www.whois.com/whois/95.71.42.116
> AbuseIPDB: https://www.abuseipdb.com/check/95.71.42.116
### Freigabe
### Entsperrung (Unban)
**Überschrift:** ✅ AdGuard Shield
```text
AdGuard Shield Freigabe auf dns1
---
IP: 192.0.2.50
Hostname: client.example.com
> ✅ AdGuard Shield Freigabe auf dns1
> ---
> IP: 95.71.42.116
> Hostname: example-host.provider.net
>
> AbuseIPDB: https://www.abuseipdb.com/check/95.71.42.116
AbuseIPDB: https://www.abuseipdb.com/check/192.0.2.50
```
### Externe Blocklist Sperre
**Überschrift:** 🚨 🛡️ AdGuard Shield
### Bulk-Freigabe
> 🚫 AdGuard Shield Ban auf dns1 (Externe Blocklist)
> ---
> IP: 203.0.113.50
> Hostname: bad-actor.example.com
>
> Whois: https://www.whois.com/whois/203.0.113.50
> AbuseIPDB: https://www.abuseipdb.com/check/203.0.113.50
```text
AdGuard Shield Bulk-Freigabe auf dns1
---
Freigegebene IPs: 28
Aktion: Manual-Flush
```
### Externe Blocklist Entsperrung
**Überschrift:** ✅ AdGuard Shield
## Fehlersuche
> ✅ AdGuard Shield Freigabe auf dns1 (Externe Blocklist)
> ---
> IP: 203.0.113.50
> Hostname: bad-actor.example.com
>
> AbuseIPDB: https://www.abuseipdb.com/check/203.0.113.50
Wenn keine Benachrichtigung ankommt:
### Hinweise
```bash
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
sudo journalctl -u adguard-shield --no-pager -n 100
```
- Der **Hostname** der IP wird automatisch per Reverse-DNS aufgelöst (`dig`, `host` oder `getent`). Ist kein PTR-Record vorhanden, wird `(unbekannt)` angezeigt.
- Der **Servername** (`dns1` in den Beispielen) wird dynamisch über `$(hostname)` ermittelt und zeigt, auf welchem Server das Ereignis stattfand.
- Die **Überschrift** unterscheidet sich je nach Aktion:
- 🚨 🛡️ bei Sperren und Service-Stopp
- ✅ bei Freigaben und Service-Start
- Bei **permanenten Sperren** mit aktiviertem AbuseIPDB-Reporting wird ein Hinweis eingeblendet, dass die IP an AbuseIPDB gemeldet wurde.
Prüfe:
- `NOTIFY_ENABLED=true`
- `NOTIFY_TYPE` korrekt geschrieben
- Ziel-URL oder Ntfy-Topic gesetzt
- Token gültig
- Server kann den Webhook erreichen
- Firewall des Servers blockiert ausgehende HTTPS-Verbindungen nicht
Bei `generic` kannst du testweise einen lokalen HTTP-Empfänger oder einen Request-Inspector verwenden.
## Datenschutz
Benachrichtigungen können IP-Adressen, Domainnamen und Hostnamen enthalten. Sende sie nur an Dienste, denen du vertraust. Für öffentliche oder geteilte Kanäle ist Ntfy mit privatem Topic oder eine eigene Ntfy/Gotify-Instanz oft die bessere Wahl.

52
docs/docker.md Normal file
View File

@@ -0,0 +1,52 @@
# Docker-Installationen
AdGuard Shield liest weiterhin das Querylog von AdGuard Home. Der Unterschied zwischen klassisch und Docker betrifft nur die Stelle, an der die Firewall eine gesperrte Client-IP abfangen muss.
## Modus wählen
| Installation | Einstellung |
|---|---|
| AdGuard Home direkt auf dem Host | `FIREWALL_MODE="host"` |
| Docker mit `network_mode: host` | `FIREWALL_MODE="docker-host"` |
| Docker Bridge mit veröffentlichten Ports | `FIREWALL_MODE="docker-bridge"` |
| gemischtes Setup oder Migration | `FIREWALL_MODE="hybrid"` |
`docker-host` verhält sich technisch wie `host`: Die DNS-Pakete landen in der Host-`INPUT`-Chain.
Bei Docker Bridge mit `ports:` oder `-p` landen veröffentlichte Ports nach Dockers NAT-Regeln im Forwarding-Pfad. Deshalb nutzt AdGuard Shield dort `DOCKER-USER`. Diese Chain ist genau für eigene Admin-Regeln vor Dockers Container-Regeln vorgesehen.
## Beispiele
Klassisch oder Docker Host Network:
```bash
FIREWALL_MODE="host"
BLOCKED_PORTS="53 443 853"
```
Docker Bridge mit Port-Publishing:
```bash
FIREWALL_MODE="docker-bridge"
BLOCKED_PORTS="53 443 853"
```
Unklarer Übergangszustand:
```bash
FIREWALL_MODE="hybrid"
```
## Wichtige Details
- `docker-bridge` benötigt eine vorhandene IPv4-Chain `DOCKER-USER`. Wenn Docker nicht läuft oder iptables für Docker deaktiviert ist, meldet `firewall-create` einen Fehler.
- IPv6 über Docker wird nur eingehängt, wenn Docker auch eine `ip6tables`-Chain `DOCKER-USER` angelegt hat. Fehlt sie, wird IPv4 trotzdem geschützt.
- In `DOCKER-USER` wird nach Dockers DNAT gematcht. Wenn du ungewöhnliche Port-Mappings nutzt, sollten `BLOCKED_PORTS` die Container-Zielports enthalten.
- `hybrid` ist praktisch für Migrationen, kann aber mehr Verkehr treffen, weil sowohl Host-Ports als auch Docker-Forwarding geprüft werden.
Nach einer Änderung:
```bash
sudo systemctl restart adguard-shield
sudo /opt/adguard-shield/adguard-shield firewall-status
```

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,58 @@
# E-Mail Report
AdGuard Shield kann regelmäßig einen Statistik-Report per E-Mail versenden. Der Report enthält eine Übersicht über alle Sperren, die auffälligsten IPs, meistbetroffene Domains und weitere Statistiken.
AdGuard Shield kann Statistik-Reports direkt aus der SQLite-Datenbank erzeugen und per E-Mail versenden. Es gibt in der Go-Version keinen separaten `report-generator.sh` mehr.
## Voraussetzungen
## Was der Report enthält
Der Server muss E-Mails versenden können. Empfohlen wird **msmtp** als leichtgewichtiger SMTP-Client.
Der Report basiert auf:
**Anleitung zur Einrichtung von msmtp:**
👉 [Linux: Einfach E-Mails versenden mit msmtp](https://www.cleveradmin.de/blog/2024/12/linux-einfach-emails-versenden-mit-msmtp/)
```text
/var/lib/adguard-shield/adguard-shield.db
```
Alternativ funktioniert auch `sendmail`, `mail` oder ein anderer Befehl, der E-Mails über stdin entgegennimmt.
Ausgewertet werden vor allem:
## Aktivierung
- `ban_history`
- `active_bans`
In der Konfiguration (`adguard-shield.conf`):
Inhalte:
- Zeitraum des Reports
- Anzahl Sperren im Zeitraum
- Anzahl Freigaben im Zeitraum
- aktuell aktive Sperren
- Top-Clients
- Gründe der Sperren
- Quellen aktiver Sperren
- letzte Ereignisse aus der History
## Konfiguration
```bash
REPORT_ENABLED=false
REPORT_INTERVAL="weekly"
REPORT_TIME="08:00"
REPORT_EMAIL_TO="admin@example.com"
REPORT_EMAIL_FROM="adguard-shield@example.com"
REPORT_FORMAT="html"
REPORT_MAIL_CMD="msmtp"
REPORT_BUSIEST_DAY_RANGE=30
```
Parameter:
| Parameter | Bedeutung |
|---|---|
| `REPORT_ENABLED` | dokumentiert, ob Reports gewünscht sind; der Cron-Job wird über `report-install` angelegt |
| `REPORT_INTERVAL` | `daily`, `weekly`, `biweekly` oder `monthly` |
| `REPORT_TIME` | Uhrzeit im Format `HH:MM` |
| `REPORT_EMAIL_TO` | Empfängeradresse |
| `REPORT_EMAIL_FROM` | Absenderadresse |
| `REPORT_FORMAT` | `html` oder `txt` |
| `REPORT_MAIL_CMD` | Mailprogramm, z.B. `msmtp` |
| `REPORT_BUSIEST_DAY_RANGE` | Kompatibilitätsparameter für den Zeitraum "Aktivster Tag" |
Beispiel:
```bash
REPORT_ENABLED=true
@@ -25,252 +64,182 @@ REPORT_FORMAT="html"
REPORT_MAIL_CMD="msmtp"
```
Anschließend den Cron-Job einrichten:
```bash
sudo /opt/adguard-shield/report-generator.sh install
```
## Konfigurationsparameter
| Parameter | Standard | Beschreibung |
|-----------|----------|--------------|
| `REPORT_ENABLED` | `false` | Report-Funktion aktivieren |
| `REPORT_INTERVAL` | `weekly` | Versandintervall (siehe unten) |
| `REPORT_TIME` | `08:00` | Uhrzeit für den Versand (HH:MM, 24h) |
| `REPORT_EMAIL_TO` | *(leer)* | E-Mail-Empfänger |
| `REPORT_EMAIL_FROM` | `adguard-shield@hostname` | E-Mail-Absender |
| `REPORT_FORMAT` | `html` | Format: `html` oder `txt` |
| `REPORT_MAIL_CMD` | `msmtp` | Mail-Befehl (`msmtp`, `sendmail`, `mail`) |
| `REPORT_BUSIEST_DAY_RANGE` | `30` | Zeitraum in Tagen für „Aktivster Tag“ (0 = Berichtszeitraum) |
### Versandintervalle
| Wert | Beschreibung |
|------|-------------|
| `daily` | Täglich zur konfigurierten Uhrzeit |
| `weekly` | Wöchentlich am Montag |
| `biweekly` | Alle zwei Wochen am Montag |
| `monthly` | Monatlich am 1. des Monats |
## Report-Inhalte
Der Report enthält folgende Statistiken:
### Zeitraum-Schnellübersicht *(immer ganz oben)*
Eine Vergleichstabelle mit Live-Zahlen für vier feste Zeitfenster unabhängig vom konfigurierten `REPORT_INTERVAL`:
| Zeitraum | Sperren | Entsperrungen | Eindeutige IPs | Permanent gebannt |
|----------|---------|---------------|----------------|-------------------|
| Heute *(nur nach 20:00 Uhr)* | … | … | … | … |
| Gestern | … | … | … | … |
| Letzte 7 Tage | … | … | … | … |
| Letzte 14 Tage | … | … | … | … |
| Letzte 30 Tage | … | … | … | … |
Im HTML-Format wird **Gestern** grün hervorgehoben, **Heute** blau (erscheint nur ab 20:00 Uhr).
- **Gestern** umfasst exakt 00:00:00 23:59:59 des gestrigen Tages.
- **Heute** umfasst den laufenden Tag von 00:00:00 bis zum Zeitpunkt der Reportgenerierung und wird nur eingeblendet, wenn der Report nach 20:00 Uhr erstellt wird.
Die übrigen Zeiträume laufen vom Starttag 00:00 Uhr bis zum Zeitpunkt der Reportgenerierung.
> **Hinweis:** Die AbuseIPDB-Meldungen werden in der Schnellübersicht nicht mehr separat ausgewiesen, da sie immer mit einer Permanentsperre korrelieren der Wert „Permanent gebannt" ist daher ausreichend. Die Gesamtanzahl der AbuseIPDB-Reports im Berichtszeitraum ist weiterhin in der allgemeinen Übersicht sichtbar.
### Übersicht (Berichtszeitraum)
- Gesamtzahl der Sperren und Entsperrungen
- Anzahl eindeutiger gesperrter IPs
- Permanente Sperren
- Aktuell aktive Sperren
- AbuseIPDB-Reports
### Angriffsarten
- Rate-Limit Sperren
- Subdomain-Flood Sperren
- Externe Blocklist Sperren
- Aktivster Tag wird über einen konfigurierbaren Zeitraum ermittelt (Standard: letzte 30 Tage, `REPORT_BUSIEST_DAY_RANGE`). Zeigt zusätzlich die Anzahl der Sperren an diesem Tag. Bei `REPORT_BUSIEST_DAY_RANGE=0` wird nur der Berichtszeitraum betrachtet.
### Top 10 Listen
- **Auffälligste IPs** — Die 10 IPs mit den meisten Sperren (mit Balkendiagramm im HTML-Format)
- **Meistbetroffene Domains** — Die 10 am häufigsten betroffenen Domains
### Weitere Details
- **Protokoll-Verteilung** — Aufschlüsselung nach DNS, DoH, DoT, DoQ
- **Letzte 10 Sperren** — Die aktuellsten Sperrereignisse mit Zeitstempel, IP, Domain und Grund
## Befehle
```bash
# Report sofort generieren und versenden
sudo /opt/adguard-shield/report-generator.sh send
# Konfiguration und Cron-Status anzeigen
sudo /opt/adguard-shield/adguard-shield report-status
# Test-E-Mail senden (prüft alle Voraussetzungen + Mailversand)
sudo /opt/adguard-shield/report-generator.sh test
# HTML-Report in Datei schreiben
sudo /opt/adguard-shield/adguard-shield report-generate html /tmp/adguard-shield-report.html
# Report als Datei generieren (auf stdout ausgeben)
sudo /opt/adguard-shield/report-generator.sh generate
# Text-Report auf stdout ausgeben
sudo /opt/adguard-shield/adguard-shield report-generate txt
# Report im spezifischen Format generieren
sudo /opt/adguard-shield/report-generator.sh generate html > report.html
sudo /opt/adguard-shield/report-generator.sh generate txt > report.txt
# Testmail senden
sudo /opt/adguard-shield/adguard-shield report-test
# Cron-Job für automatischen Versand einrichten
sudo /opt/adguard-shield/report-generator.sh install
# aktuellen Report erzeugen und versenden
sudo /opt/adguard-shield/adguard-shield report-send
# Cron-Job installieren
sudo /opt/adguard-shield/adguard-shield report-install
# Cron-Job entfernen
sudo /opt/adguard-shield/report-generator.sh remove
# Report-Konfiguration und Cron-Status anzeigen
sudo /opt/adguard-shield/report-generator.sh status
sudo /opt/adguard-shield/adguard-shield report-remove
```
## Report-Intervall ändern
## Mailversand
Um das Intervall, die Uhrzeit oder andere Einstellungen zu ändern:
AdGuard Shield übergibt die fertige Mail an ein lokales Mailprogramm. Der Standard ist:
```bash
# 1. Konfiguration bearbeiten
sudo nano /opt/adguard-shield/adguard-shield.conf
# → z.B. REPORT_INTERVAL="weekly" auf "daily" ändern
# → z.B. REPORT_TIME="09:00"
# 2. Cron-Job neu einrichten (überschreibt den alten automatisch)
sudo /opt/adguard-shield/report-generator.sh install
REPORT_MAIL_CMD="msmtp"
```
> **Hinweis:** Der `install`-Befehl überschreibt den bestehenden Cron-Job mit den aktuellen Werten aus der Konfiguration. Ein vorheriges `remove` ist nicht nötig, schadet aber auch nicht.
Alternativ in zwei Schritten:
Minimaler Ablauf mit `msmtp`:
```bash
# Alten Cron-Job erst entfernen, dann neu anlegen
sudo /opt/adguard-shield/report-generator.sh remove
sudo nano /opt/adguard-shield/adguard-shield.conf
sudo /opt/adguard-shield/report-generator.sh install
```
## Templates
Die Report-Templates liegen unter:
```
/opt/adguard-shield/templates/report.html # HTML-Template
/opt/adguard-shield/templates/report.txt # TXT-Template
```
Die Templates verwenden Platzhalter (z.B. `{{TOTAL_BANS}}`, `{{TOP10_IPS_TABLE}}`), die beim Generieren durch die tatsächlichen Werte ersetzt werden. Die Templates können nach Bedarf angepasst werden.
### Verfügbare Platzhalter
| Platzhalter | Beschreibung |
|-------------|-------------|
| `{{REPORT_PERIOD}}` | Berichtszeitraum mit Label |
| `{{REPORT_DATE}}` | Erstellungsdatum des Reports |
| `{{HOSTNAME}}` | Server-Hostname |
| `{{VERSION}}` | AdGuard Shield Version |
| `{{TOTAL_BANS}}` | Gesamtzahl Sperren |
| `{{TOTAL_UNBANS}}` | Gesamtzahl Entsperrungen |
| `{{UNIQUE_IPS}}` | Anzahl eindeutiger IPs |
| `{{PERMANENT_BANS}}` | Permanente Sperren |
| `{{ACTIVE_BANS}}` | Aktuell aktive Sperren |
| `{{ABUSEIPDB_REPORTS}}` | Anzahl AbuseIPDB-Reports |
| `{{RATELIMIT_BANS}}` | Rate-Limit Sperren |
| `{{SUBDOMAIN_FLOOD_BANS}}` | Subdomain-Flood Sperren |
| `{{EXTERNAL_BLOCKLIST_BANS}}` | Externe Blocklist Sperren |
| `{{BUSIEST_DAY}}` | Aktivster Tag (Datum + Anzahl Sperren) |
| `{{BUSIEST_DAY_LABEL}}` | Dynamisches Label für den aktivsten Tag (z.B. „Aktivster Tag (30 Tage)“) |
| `{{TOP10_IPS_TABLE}}` | Top 10 IPs (HTML-Tabelle) |
| `{{TOP10_IPS_TEXT}}` | Top 10 IPs (Text-Tabelle) |
| `{{TOP10_DOMAINS_TABLE}}` | Top 10 Domains (HTML-Tabelle) |
| `{{TOP10_DOMAINS_TEXT}}` | Top 10 Domains (Text-Tabelle) |
| `{{PROTOCOL_TABLE}}` | Protokoll-Verteilung (HTML) |
| `{{PROTOCOL_TEXT}}` | Protokoll-Verteilung (Text) |
| `{{RECENT_BANS_TABLE}}` | Letzte Sperren (HTML) |
| `{{RECENT_BANS_TEXT}}` | Letzte Sperren (Text) |
## Beispiel: Schnellstart
```bash
# 1. msmtp installieren und konfigurieren
sudo apt install msmtp msmtp-mta
# Anleitung: https://www.cleveradmin.de/blog/2024/12/linux-einfach-emails-versenden-mit-msmtp/
# 2. Report-Konfiguration anpassen
sudo nano /opt/adguard-shield/adguard-shield.conf
# → REPORT_ENABLED=true
# → REPORT_EMAIL_TO="deine@email.de"
# 3. Test-Mail senden (prüft alle Voraussetzungen)
sudo /opt/adguard-shield/report-generator.sh test
# 4. Wenn die Test-Mail angekommen ist: echten Report testen
sudo /opt/adguard-shield/report-generator.sh send
# 5. Automatischen Versand einrichten
sudo /opt/adguard-shield/report-generator.sh install
# 6. Status prüfen
sudo /opt/adguard-shield/report-generator.sh status
sudo /opt/adguard-shield/adguard-shield report-test
```
## Test-Mail
`report-test` sendet eine einfache Testmail. Erst wenn diese funktioniert, lohnt sich die Fehlersuche am eigentlichen Report.
Bevor du den automatischen Versand einrichtest, kannst du mit dem `test`-Befehl prüfen, ob alles funktioniert:
Wenn dein Mailprogramm zusätzliche Argumente braucht, können sie in `REPORT_MAIL_CMD` stehen. AdGuard Shield hängt intern `-t` an, damit Empfänger und Header aus der generierten Mail gelesen werden.
Beispiel:
```bash
sudo /opt/adguard-shield/report-generator.sh test
REPORT_MAIL_CMD="msmtp --account=default"
```
Der Test prüft Schritt für Schritt:
## Automatischer Versand
1. **E-Mail-Empfänger** — Ist `REPORT_EMAIL_TO` konfiguriert?
2. **E-Mail-Absender** — Zeigt den konfigurierten Absender an
3. **Mail-Befehl** — Ist `msmtp` (oder der konfigurierte Befehl) installiert?
4. **Report-Template** — Existiert das HTML/TXT-Template?
5. **Ban-History** — Gibt es vorhandene Daten?
6. **Test-Versand** — Sendet eine Test-E-Mail und prüft den Exit-Code
Cron installieren:
Die Test-Mail enthält eine Übersicht der aktuellen Konfiguration und bestätigt, dass der Mailversand funktioniert.
```bash
sudo /opt/adguard-shield/adguard-shield report-install
```
## Troubleshooting
Dadurch wird diese Datei geschrieben:
### E-Mail wird nicht versendet
```text
/etc/cron.d/adguard-shield-report
```
1. Prüfe ob der Mail-Befehl installiert ist:
```bash
which msmtp
```
Der Cron-Eintrag ruft das installierte Binary mit der installierten Konfiguration auf:
2. Teste den Mailversand manuell:
```bash
echo "Test" | msmtp -t deine@email.de
```
```text
/opt/adguard-shield/adguard-shield -config /opt/adguard-shield/adguard-shield.conf report-send
```
3. Prüfe die msmtp-Konfiguration:
```bash
cat ~/.msmtprc
# oder
cat /etc/msmtprc
```
Zeitplan nach `REPORT_INTERVAL`:
4. Prüfe die Report-Konfiguration:
```bash
sudo /opt/adguard-shield/report-generator.sh status
```
| Intervall | Cron-Verhalten |
|---|---|
| `daily` | täglich zur Uhrzeit aus `REPORT_TIME` |
| `weekly` | montags zur Uhrzeit aus `REPORT_TIME` |
| `biweekly` | am 1. und 15. des Monats |
| `monthly` | am 1. des Monats |
### Report enthält keine Daten
Cron entfernen:
Der Report basiert auf der Ban-History in der SQLite-Datenbank (`/var/lib/adguard-shield/adguard-shield.db`). Wenn keine Sperren im Berichtszeitraum vorhanden sind, zeigt der Report „Keine Daten" an.
```bash
sudo /opt/adguard-shield/adguard-shield report-remove
```
### Cron-Job wird nicht ausgeführt
## Manuelle Prüfung
1. Prüfe ob der Cron-Job angelegt wurde:
```bash
cat /etc/cron.d/adguard-shield-report
```
Status:
2. Prüfe die Cron-Logs:
```bash
grep adguard-shield /var/log/syslog
# oder
journalctl -u cron
```
```bash
sudo /opt/adguard-shield/adguard-shield report-status
```
Report lokal erzeugen:
```bash
sudo /opt/adguard-shield/adguard-shield report-generate html /tmp/adguard-shield-report.html
sudo /opt/adguard-shield/adguard-shield report-generate txt
```
Versand testen:
```bash
sudo /opt/adguard-shield/adguard-shield report-test
sudo /opt/adguard-shield/adguard-shield report-send
```
Logs:
```bash
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
sudo journalctl -u cron --no-pager -n 100
```
Je nach Distribution heißt der Cron-Service auch `cron`, `crond` oder wird über das allgemeine Syslog protokolliert.
## Häufige Probleme
### `REPORT_EMAIL_TO ist leer`
Setze einen Empfänger:
```bash
REPORT_EMAIL_TO="admin@example.com"
```
### Mailprogramm nicht gefunden
Prüfen:
```bash
which msmtp
```
Installieren:
```bash
sudo apt install msmtp msmtp-mta
```
Oder `REPORT_MAIL_CMD` auf dein vorhandenes Mailprogramm setzen.
### Cron läuft, aber keine Mail kommt an
Prüfen:
```bash
sudo /opt/adguard-shield/adguard-shield report-send
sudo cat /etc/cron.d/adguard-shield-report
```
Achte darauf, dass:
- `REPORT_EMAIL_TO` stimmt
- `REPORT_MAIL_CMD` im Cron-PATH verfügbar ist
- der lokale Mailer für root konfiguriert ist
- Spam-Ordner geprüft wurde
- ausgehende SMTP-Verbindungen erlaubt sind
## HTML und TXT
HTML ist für normale E-Mail-Clients angenehmer zu lesen:
```bash
REPORT_FORMAT="html"
```
TXT ist robuster für sehr einfache Mail-Setups oder Log-Ablage:
```bash
REPORT_FORMAT="txt"
```
Du kannst das Format beim manuellen Generieren überschreiben:
```bash
sudo /opt/adguard-shield/adguard-shield report-generate txt
sudo /opt/adguard-shield/adguard-shield report-generate html /tmp/report.html
```

View File

@@ -1,287 +1,424 @@
# Tipps & Troubleshooting
## Best Practices
Dieses Dokument hilft beim Eingrenzen typischer Probleme im Betrieb. Die Reihenfolge ist bewusst praktisch: erst prüfen, ob der Dienst läuft, dann API, Firewall, Sperren, Listen und optionale Module.
- **Erst immer im Dry-Run testen**, bevor der scharfe Modus aktiviert wird
```bash
sudo /opt/adguard-shield/adguard-shield.sh dry-run
```
- **Whitelist großzügig pflegen**: Eigene IPs, Router, wichtige Server nicht vergessen
- **Sperrdauer anpassen**: Für DDoS-artige Muster ggf. länger sperren
- **Logs regelmäßig prüfen**: Falsche Positive erkennen und Whitelist anpassen
- **Ban-History nutzen**: `history`-Befehl zeigt alle vergangenen Sperren — hilfreich um Muster zu erkennen
- **Log-Level auf DEBUG** setzen wenn etwas nicht funktioniert
## Erste Diagnose
## Häufige Probleme
### API-Verbindung schlägt fehl
Diese Befehle liefern meistens schon genug Hinweise:
```bash
sudo /opt/adguard-shield/adguard-shield.sh test
sudo systemctl status adguard-shield
sudo journalctl -u adguard-shield --no-pager -n 100
sudo /opt/adguard-shield/adguard-shield test
sudo /opt/adguard-shield/adguard-shield status
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
```
**Mögliche Ursachen:**
- Falsche URL in `ADGUARD_URL` (Port prüfen!)
- Falsche Zugangsdaten (`ADGUARD_USER` / `ADGUARD_PASS`)
- AdGuard Home läuft nicht
- Firewall blockiert lokale Verbindung
- DNS-Auflösung des Hostnames fehlgeschlagen
- SSL/TLS-Zertifikatfehler (bei HTTPS)
Wenn du aktuelle Queries sehen willst:
#### Schritt-für-Schritt Diagnose
**1. Base-URL Erreichbarkeit prüfen (ohne Auth):**
```bash
# Vollständige Diagnose mit HTTP-Headern und Verbindungsdetails
curl -ikv https://dns1.domain.com 2>&1
# Nur HTTP-Statuscode prüfen (schnell)
curl -s -o /dev/null -w "%{http_code}\n" -k https://dns1.domain.com
sudo /opt/adguard-shield/adguard-shield live
```
> `-i` zeigt HTTP-Response-Header, `-k` ignoriert SSL-Fehler, `-v` zeigt Verbindungsdetails (DNS, TLS-Handshake, etc.)
## Service startet nicht
Prüfen:
**2. DNS-Auflösung testen:**
```bash
# Hostname auflösen
dig +short dns1.domain.com
# Oder mit nslookup
nslookup dns1.domain.com
sudo systemctl status adguard-shield
sudo journalctl -u adguard-shield --no-pager -n 100
```
**3. Port-Erreichbarkeit testen:**
```bash
# TCP-Verbindung zum Port prüfen (z.B. Port 3000)
nc -zv 127.0.0.1 3000
Typische Ursachen:
# Oder mit curl
curl -v telnet://127.0.0.1:3000
```
- Konfigurationsdatei fehlt oder hat falsche Rechte
- Binary fehlt oder ist nicht ausführbar
- `iptables`, `ip6tables` oder `ipset` fehlen
- AdGuard-Home-API ist nicht erreichbar
- alte Shell-Artefakte verursachen Konflikte
- systemd-Unit wurde manuell geändert, aber `daemon-reload` fehlt
**4. API-Endpunkt mit Authentifizierung testen:**
```bash
# Query-Log abfragen (mit Auth + Response-Header)
curl -i -u admin:passwort https://dns1.domain.com/control/querylog?limit=1
# Nur HTTP-Status zurückgeben
curl -s -o /dev/null -w "%{http_code}\n" -u admin:passwort https://dns1.domain.com/control/querylog?limit=1
```
**5. AdGuard Home Status-API prüfen:**
```bash
# Allgemeinen Status abfragen (benötigt keine Auth)
curl -ik https://dns1.domain.com/control/status
```
#### Typische Fehlercodes
| HTTP-Code | Bedeutung | Lösung |
|-----------|-----------|--------|
| `000` | Keine Verbindung | Host nicht erreichbar, DNS-Fehler oder Firewall |
| `200` | Erfolg | Alles in Ordnung ✅ |
| `301/302` | Weiterleitung | URL prüfen — evtl. fehlt `https://` oder Port |
| `401` | Nicht autorisiert | `ADGUARD_USER` / `ADGUARD_PASS` prüfen |
| `403` | Zugriff verweigert | Zugangsdaten oder IP-Beschränkung in AdGuard Home |
| `404` | Nicht gefunden | URL falsch oder AdGuard Home Version zu alt |
| `502/503` | Service nicht verfügbar | AdGuard Home läuft nicht oder wird gerade neu gestartet |
#### curl Exit-Codes
| Exit-Code | Bedeutung |
|-----------|-----------|
| `6` | DNS-Auflösung fehlgeschlagen — Hostname prüfen |
| `7` | Verbindung abgelehnt — Läuft AdGuard Home? Port korrekt? |
| `28` | Timeout — Host nicht erreichbar oder Firewall blockiert |
| `35` | SSL/TLS-Handshake fehlgeschlagen |
| `51` | SSL-Zertifikat: Hostname stimmt nicht überein |
| `60` | SSL-Zertifikat: nicht vertrauenswürdig (selbstsigniert?) |
> **Tipp:** Bei selbstsignierten Zertifikaten `-k` an curl anhängen, um SSL-Fehler zu ignorieren. AdGuard Shield verwendet intern automatisch `-k` bei der API-Kommunikation.
**Lösung:** URL und Zugangsdaten in der Konfiguration anpassen:
```bash
sudo nano /opt/adguard-shield/adguard-shield.conf
sudo systemctl restart adguard-shield
```
### iptables-Fehler: "Permission denied"
Das Script muss als **root** laufen, da iptables Root-Rechte benötigt.
Nützliche Prüfungen:
```bash
sudo /opt/adguard-shield/adguard-shield.sh start
```
### Client wird fälschlich gesperrt
1. Client sofort entsperren:
```bash
sudo /opt/adguard-shield/adguard-shield.sh unban 192.168.1.100
```
2. In der Ban-History prüfen, warum gesperrt wurde:
```bash
sudo /opt/adguard-shield/adguard-shield.sh history | grep 192.168.1.100
```
3. Offense-Zähler für die IP zurücksetzen (damit die progressive Sperre wieder bei Stufe 1 beginnt):
```bash
sudo /opt/adguard-shield/adguard-shield.sh reset-offenses 192.168.1.100
```
4. IP zur Whitelist hinzufügen in `adguard-shield.conf`
5. Service neustarten:
```bash
sudo systemctl restart adguard-shield
```
### Client wurde permanent gesperrt (Progressive Sperren)
Wenn eine IP die maximale Stufe der progressiven Sperren erreicht hat, wird sie permanent gesperrt und nicht automatisch aufgehoben.
1. IP entsperren:
```bash
sudo /opt/adguard-shield/adguard-shield.sh unban 192.168.1.100
```
2. Offense-Zähler zurücksetzen:
```bash
sudo /opt/adguard-shield/adguard-shield.sh reset-offenses 192.168.1.100
```
3. Prüfen ob die IP auf die Whitelist gehört, oder die Progressive-Ban-Einstellungen anpassen (`PROGRESSIVE_BAN_MAX_LEVEL` erhöhen oder auf `0` setzen für keine permanenten Sperren)
### Sperren überleben Reboot nicht
Das ist normal — iptables-Regeln sind flüchtig. Der **Service** erstellt die Chain beim Start automatisch neu. Aktive Sperren aus der SQLite-Datenbank werden aber nicht automatisch als iptables-Regeln wiederhergestellt.
**Optionen:**
- `iptables-persistent` installieren (`apt install iptables-persistent`)
- Oder den State beim Boot wiederherstellen lassen (Feature-Idee)
### Zu viele false positives
- `RATE_LIMIT_MAX_REQUESTS` erhöhen (z.B. 50 oder 100)
- `RATE_LIMIT_WINDOW` vergrößern (z.B. 120 Sekunden)
- Windows-Clients fragen manche Domains von Natur aus sehr oft an — Whitelist nutzen
### Subdomain-Flood-Erkennung sperrt legitime Clients
Manche Dienste (z.B. CDNs, Cloud-Dienste, Microsoft 365) nutzen von Natur aus viele verschiedene Subdomains. Falls ein legitimer Client fälschlicherweise durch die Subdomain-Flood-Erkennung gesperrt wird:
1. Client sofort entsperren:
```bash
sudo /opt/adguard-shield/adguard-shield.sh unban <IP>
```
2. Schwellwert erhöhen — z.B. von 50 auf 100 oder 150:
```bash
SUBDOMAIN_FLOOD_MAX_UNIQUE=100
```
3. Zeitfenster vergrößern — z.B. auf 120 Sekunden:
```bash
SUBDOMAIN_FLOOD_WINDOW=120
```
4. Oder die IP zur Whitelist hinzufügen
5. Im Zweifelsfall die Erkennung temporär deaktivieren:
```bash
SUBDOMAIN_FLOOD_ENABLED=false
```
> **Tipp:** Im Dry-Run-Modus (`sudo /opt/adguard-shield/adguard-shield.sh dry-run`) kann man beobachten, welche Clients die Subdomain-Flood-Erkennung auslösen würden, ohne sie wirklich zu sperren.
### Monitor startet nicht (PID-File)
```bash
# Altes PID-File entfernen
sudo rm -f /var/run/adguard-shield.pid
sudo systemctl start adguard-shield
```
### Service ist ausgefallen und startet nicht mehr
Wenn systemd das Restart-Limit erreicht hat (z.B. `"Start request repeated too quickly"`), hilft der **Watchdog** — er prüft alle 5 Minuten ob der Service läuft und startet ihn automatisch neu.
**Watchdog-Status prüfen:**
```bash
# Timer-Status anzeigen
sudo systemctl status adguard-shield-watchdog.timer
# Letzte Watchdog-Ausführungen anzeigen
sudo systemctl list-timers adguard-shield-watchdog.timer
# Watchdog-Logs prüfen
sudo journalctl -u adguard-shield-watchdog.service --no-pager -n 20
```
**Manuelles Recovery (sofort):**
```bash
# systemd-Fehlerzähler zurücksetzen und Service starten
sudo systemctl reset-failed adguard-shield.service
sudo systemctl start adguard-shield.service
```
**Watchdog nachträglich aktivieren:**
```bash
sudo systemctl enable adguard-shield-watchdog.timer
sudo systemctl start adguard-shield-watchdog.timer
```
> **Hinweis:** Der Watchdog sendet automatisch eine Benachrichtigung (falls `NOTIFY_ENABLED=true`), wenn er den Service wiederbeleben muss oder die Recovery fehlschlägt.
## Update durchführen
```bash
# Repository aktualisieren
cd /tmp/adguard-shield
git pull
# Update ausführen (Konfig wird automatisch migriert, Service neu gestartet)
sudo bash install.sh update
```
**Was passiert beim Update:**
- Alle Scripts werden aktualisiert
- Konfiguration wird als `adguard-shield.conf.old` gesichert
- Neue Konfigurationsparameter werden automatisch zur bestehenden Konfig ergänzt
- Bestehende Einstellungen bleiben erhalten
- Bestehende Flat-File-Daten werden einmalig in die SQLite-Datenbank migriert (mit Fortschrittsanzeige)
- Service wird per `daemon-reload` neu geladen und automatisch neu gestartet
## Deinstallation
Ab Version 0.6 gibt es einen eigenständigen Uninstaller im Installationsverzeichnis. Die Deinstallation kann daher jederzeit durchgeführt werden, **ohne die originalen Installationsdateien (install.sh) behalten zu müssen**:
```bash
# Empfohlen: direkt aus dem Installationsverzeichnis ausführen
sudo bash /opt/adguard-shield/uninstall.sh
# Alternativ: über den Installer (sofern noch vorhanden)
sudo bash install.sh uninstall
```
Beide Wege sind gleichwertig — `install.sh uninstall` delegiert intern an `/opt/adguard-shield/uninstall.sh`.
Oder manuell:
```bash
sudo systemctl stop adguard-shield
sudo systemctl disable adguard-shield
sudo systemctl stop adguard-shield-watchdog.timer
sudo systemctl disable adguard-shield-watchdog.timer
sudo /opt/adguard-shield/iptables-helper.sh remove
sudo rm -rf /opt/adguard-shield
sudo rm -f /etc/systemd/system/adguard-shield.service
sudo rm -f /etc/systemd/system/adguard-shield-watchdog.service
sudo rm -f /etc/systemd/system/adguard-shield-watchdog.timer
ls -l /opt/adguard-shield/adguard-shield
ls -l /opt/adguard-shield/adguard-shield.conf
which iptables ip6tables ipset systemctl
sudo systemctl daemon-reload
```
## Voraussetzungen
## Verbindung zu AdGuard Home schlägt fehl
Folgende Pakete werden für den Betrieb benötigt und bei der Installation automatisch installiert:
Test:
| Paket | Zweck |
|-------|-------|
| `curl` | API-Kommunikation mit AdGuard Home |
| `jq` | JSON-Verarbeitung der API-Antworten |
| `iptables` | Firewall-Regeln (IPv4 + IPv6) |
| `gawk` | Textverarbeitung in Scripts |
| `systemd` | Service-Management und Autostart |
| `sqlite3` | Datenbank für State-Management, Ban-History und Offense-Tracking |
```bash
sudo /opt/adguard-shield/adguard-shield test
```
Diese werden bei `sudo bash install.sh install` automatisch geprüft und bei Bedarf über den Paketmanager (`apt`, `dnf`, `yum`, `pacman`) nachinstalliert.
Prüfe in `/opt/adguard-shield/adguard-shield.conf`:
```bash
ADGUARD_URL="http://127.0.0.1:3000"
ADGUARD_USER="admin"
ADGUARD_PASS="..."
```
Häufige Fehler:
| Symptom | Mögliche Ursache |
|---|---|
| HTTP 401/403 | Benutzername oder Passwort falsch |
| HTTP 404 | falsche URL oder AdGuard Home nicht hinter dieser URL |
| Timeout | Firewall, DNS, falsche IP, Dienst nicht erreichbar |
| connection refused | AdGuard Home läuft nicht oder anderer Port |
| keine Querylog-Einträge | Querylog in AdGuard Home deaktiviert oder leer |
Direkt testen:
```bash
curl -k -u "admin:passwort" "http://127.0.0.1:3000/control/querylog?limit=1&response_status=all"
```
Passe URL und Zugangsdaten entsprechend an.
## Keine Sperren trotz vieler Anfragen
Prüfen:
```bash
sudo /opt/adguard-shield/adguard-shield live --once
sudo /opt/adguard-shield/adguard-shield history 50
sudo /opt/adguard-shield/adguard-shield logs --level debug --limit 100
```
Mögliche Ursachen:
- `RATE_LIMIT_MAX_REQUESTS` ist zu hoch
- `RATE_LIMIT_WINDOW` ist zu kurz
- `API_QUERY_LIMIT` ist zu niedrig und verpasst Spitzen
- Client steht in `WHITELIST`
- externe Whitelist enthält die IP
- AdGuard Home sieht nicht die echte Client-IP, sondern nur einen Proxy/Forwarder
- Querylog enthält die Anfragen nicht
- `DRY_RUN=true` ist gesetzt
Wichtig bei Proxies und Forwardern: Wenn AdGuard Home nur eine einzige interne IP sieht, zählt AdGuard Shield auch nur diese IP. In solchen Setups muss die Architektur geprüft oder der Forwarder gewhitelistet werden.
## Zu viele Sperren
Erst Übersicht:
```bash
sudo /opt/adguard-shield/adguard-shield status
sudo /opt/adguard-shield/adguard-shield history 100
```
Dann Ursachen einordnen:
| Ursache | Gegenmaßnahme |
|---|---|
| legitimer Client fragt häufig dieselbe Domain | Client whitelisten oder Limit erhöhen |
| Router/Resolver bündelt viele Clients | Router/Resolver whitelisten |
| CDN/App erzeugt viele Subdomains | `SUBDOMAIN_FLOOD_MAX_UNIQUE` erhöhen |
| externe Blocklist ist sehr groß | `blocklist-status` prüfen und Benachrichtigungen deaktiviert lassen |
| GeoIP Allowlist zu eng | Länder prüfen oder `GEOIP_MODE` ändern |
Falsch gesperrte IP freigeben:
```bash
sudo /opt/adguard-shield/adguard-shield unban 192.168.1.100
sudo /opt/adguard-shield/adguard-shield reset-offenses 192.168.1.100
```
Dauerhaft ausnehmen:
```bash
WHITELIST="127.0.0.1,::1,192.168.1.1,192.168.1.100"
```
Danach:
```bash
sudo systemctl restart adguard-shield
```
## Firewall prüfen
Status:
```bash
sudo /opt/adguard-shield/adguard-shield firewall-status
```
Direkt prüfen:
```bash
sudo ipset list adguard_shield_v4
sudo ipset list adguard_shield_v6
sudo iptables -n -L ADGUARD_SHIELD --line-numbers -v
sudo ip6tables -n -L ADGUARD_SHIELD --line-numbers -v
```
Firewall neu aufbauen:
```bash
sudo /opt/adguard-shield/adguard-shield firewall-remove
sudo /opt/adguard-shield/adguard-shield firewall-create
sudo systemctl restart adguard-shield
```
Nach dem Neustart werden aktive Sperren aus SQLite wieder in die ipsets geschrieben.
## Sperren bleiben nach Ablauf aktiv
Prüfen:
```bash
sudo /opt/adguard-shield/adguard-shield status
sudo /opt/adguard-shield/adguard-shield history 100
```
Temporäre Sperren werden beim Start und während des Pollings auf Ablauf geprüft. Wenn eine Sperre permanent ist, wird sie nicht automatisch freigegeben.
Permanent sind typischerweise:
- DNS-Flood-Watchlist-Treffer
- Progressive-Ban-Maximalstufe
- manuelle `ban`-Sperren
- GeoIP-Sperren
- externe Blocklist mit `EXTERNAL_BLOCKLIST_BAN_DURATION=0`
Manuell freigeben:
```bash
sudo /opt/adguard-shield/adguard-shield unban 192.168.1.100
```
## Dry-Run verwenden
Dry-Run ist ideal für neue Regeln:
```bash
sudo /opt/adguard-shield/adguard-shield dry-run
```
Währenddessen:
```bash
sudo /opt/adguard-shield/adguard-shield history 50
```
Im Dry-Run werden mögliche Sperren als `DRY` protokolliert. Es entstehen keine aktiven Sperren und keine Firewall-Änderungen.
## Externe Whitelist
Status:
```bash
sudo /opt/adguard-shield/adguard-shield whitelist-status
```
Manuell synchronisieren:
```bash
sudo /opt/adguard-shield/adguard-shield whitelist-sync
```
Typische Probleme:
- URL nicht erreichbar
- Datei enthält Windows-Zeilenenden oder BOM
- Hostname ist nicht auflösbar
- Einträge enthalten Ports oder URLs statt IP/Hostname
- DNS-Auflösung liefert `0.0.0.0`, weil AdGuard den Host blockiert
Format prüfen:
```text
192.168.1.100
10.0.0.0/24
trusted.example.com
# Kommentare sind erlaubt
```
## Externe Blocklist
Status:
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-status
```
Manuell synchronisieren:
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-sync
```
Alle externen Blocklist-Sperren freigeben:
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-flush
```
Wenn zu viele IPs gesperrt werden:
1. `EXTERNAL_BLOCKLIST_URLS` prüfen.
2. Liste manuell ansehen.
3. Whitelist für eigene IPs ergänzen.
4. `EXTERNAL_BLOCKLIST_NOTIFY=false` lassen.
5. Bei Bedarf `EXTERNAL_BLOCKLIST_AUTO_UNBAN=true` setzen.
## GeoIP
Status:
```bash
sudo /opt/adguard-shield/adguard-shield geoip-status
```
Einzelne IP prüfen:
```bash
sudo /opt/adguard-shield/adguard-shield geoip-lookup 8.8.8.8
```
Cache leeren:
```bash
sudo /opt/adguard-shield/adguard-shield geoip-flush-cache
```
Alle GeoIP-Sperren freigeben:
```bash
sudo /opt/adguard-shield/adguard-shield geoip-flush
```
Typische Ursachen:
| Problem | Lösung |
|---|---|
| keine Länder erkannt | MaxMind-Key, MMDB-Pfad oder `geoiplookup` prüfen |
| private IPs werden nicht geprüft | `GEOIP_SKIP_PRIVATE=true` ist aktiv, das ist Standard |
| zu viele Länder gesperrt | `GEOIP_MODE` und `GEOIP_COUNTRIES` prüfen |
| Allowlist sperrt fast alles | im Allowlist-Modus sind nur genannte Länder erlaubt |
## Reports
Status:
```bash
sudo /opt/adguard-shield/adguard-shield report-status
```
Test:
```bash
sudo /opt/adguard-shield/adguard-shield report-test
sudo /opt/adguard-shield/adguard-shield report-generate txt
```
Wenn keine Mail ankommt:
- `REPORT_EMAIL_TO` gesetzt?
- `REPORT_MAIL_CMD` vorhanden?
- Mailer für root konfiguriert?
- Cron installiert?
- Spam-Ordner geprüft?
Cron prüfen:
```bash
sudo cat /etc/cron.d/adguard-shield-report
sudo /opt/adguard-shield/adguard-shield report-send
```
## Benachrichtigungen
Prüfen:
```bash
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
```
Häufige Ursachen:
- `NOTIFY_ENABLED=false`
- falscher `NOTIFY_TYPE`
- Webhook-URL leer
- Ntfy-Topic leer
- Token ungültig
- ausgehende HTTPS-Verbindung blockiert
- externe Blocklist meldet nichts, weil `EXTERNAL_BLOCKLIST_NOTIFY=false`
- GeoIP meldet nichts, weil `GEOIP_NOTIFY=false`
## SQLite direkt auswerten
Für tiefergehende Analysen:
```bash
sudo sqlite3 /var/lib/adguard-shield/adguard-shield.db \
"select source, reason, count(*) from active_bans group by source, reason order by count(*) desc;"
```
Letzte History:
```bash
sudo sqlite3 /var/lib/adguard-shield/adguard-shield.db \
"select timestamp_text, action, client_ip, domain, reason from ban_history order by id desc limit 20;"
```
Offense-Zähler:
```bash
sudo sqlite3 /var/lib/adguard-shield/adguard-shield.db \
"select client_ip, offense_level, last_offense from offense_tracking order by offense_level desc;"
```
## Alte Shell-Artefakte entfernen
Wenn der Installer alte Dateien meldet, zuerst sauber migrieren. Typische alte Dateien:
```text
adguard-shield.sh
iptables-helper.sh
external-blocklist-worker.sh
external-whitelist-worker.sh
geoip-worker.sh
offense-cleanup-worker.sh
report-generator.sh
unban-expired.sh
adguard-shield-watchdog.sh
```
Die Go-Version ersetzt diese Funktionen durch das eine Binary. Alte Worker sollten nicht parallel laufen.
## Service hart zurücksetzen
Wenn der Zustand unklar ist:
```bash
sudo systemctl stop adguard-shield
sudo /opt/adguard-shield/adguard-shield firewall-remove
sudo systemctl start adguard-shield
sudo /opt/adguard-shield/adguard-shield status
```
Das entfernt die Firewall-Struktur und lässt den Daemon sie beim Start wieder aus SQLite aufbauen.
## Deinstallation
Konfiguration behalten:
```bash
sudo /opt/adguard-shield/adguard-shield uninstall --keep-config
```
Alles entfernen:
```bash
sudo /opt/adguard-shield/adguard-shield uninstall
```
Ohne `--keep-config` werden Installationsverzeichnis, State-Verzeichnis und Logdatei entfernt.

View File

@@ -1,78 +1,238 @@
# Update-Anleitung
## Voraussetzungen
AdGuard Shield wird in der Go-Version über das Binary selbst installiert und aktualisiert. Es gibt kein `install.sh` und kein `update`-Shellskript mehr.
- AdGuard Shield ist bereits installiert (`/opt/adguard-shield/`)
- Git ist installiert (`sudo apt install git`)
- Zugriff auf den Server per SSH mit Root-Rechten
## Update durchführen
### 1. Git-Repository aktualisieren
Wechsle in das Verzeichnis, in dem du das Repository geklont hast, und hole die neueste Version:
## Kurzfassung
```bash
cd /pfad/zum/adguard-shield
git pull
# neues Linux-Binary bereitstellen
chmod +x ./adguard-shield
# Update durchführen
sudo ./adguard-shield update
```
> **Hinweis:** Falls du das Repository z.B. nach `/opt/adguard-shield-repo` geklont hast:
> ```bash
> cd /opt/adguard-shield-repo
> git pull
> ```
Am Ende fragt der Updater, ob AdGuard Shield direkt neu gestartet werden soll.
### 2. Update-Script ausführen
Danach prüfen:
```bash
sudo bash install.sh update
sudo /opt/adguard-shield/adguard-shield install-status
sudo /opt/adguard-shield/adguard-shield status
sudo journalctl -u adguard-shield --no-pager -n 50
```
Das Update-Script macht automatisch folgendes:
## Woher kommt das neue Binary?
1. **Abhängigkeiten prüfen** — Fehlende Pakete (inkl. `sqlite3`) werden nachinstalliert
2. **Scripts aktualisieren** — Alle `.sh`-Dateien werden nach `/opt/adguard-shield/` kopiert
3. **Konfigurations-Migration** — Neue Parameter werden automatisch zur bestehenden Konfiguration hinzugefügt, bestehende Einstellungen bleiben **unverändert**
4. **Backup erstellen** — Die alte Konfiguration wird als `adguard-shield.conf.old` gesichert
5. **Datenbank-Migration (in der v1.0.0)** — Bestehende Flat-File-Daten (`.ban`, `.offenses`, Ban-History-Log) werden einmalig in die SQLite-Datenbank migriert. Die alten Dateien werden als Backup gesichert. Der Fortschritt und das Ergebnis werden im Terminal angezeigt.
6. **Service aktualisieren** — Die systemd Service-Datei und Watchdog-Dateien werden aktualisiert und `daemon-reload` ausgeführt
7. **Watchdog aktivieren** — Der Watchdog-Timer wird automatisch aktiviert (falls noch nicht aktiv)
8. **Service neustarten** — Der Service wird automatisch neu gestartet (falls er vorher lief)
Du brauchst ein fertiges Linux-Binary. Das kann aus einem Release, aus CI oder aus einem lokalen Build kommen.
### 3. Neue Parameter prüfen (optional)
Nach dem Update empfiehlt es sich, eventuell neu hinzugefügte Konfigurationsparameter zu prüfen:
Release-Binary für v1.0.0 herunterladen:
```bash
sudo nano /opt/adguard-shield/adguard-shield.conf
curl -fL -o adguard-shield-linux-amd64.tar.gz \
https://git.techniverse.net/scriptos/adguard-shield/releases/download/v1.0.0/adguard-shield-linux-amd64.tar.gz
tar -xzf adguard-shield-linux-amd64.tar.gz
chmod +x ./adguard-shield
```
Falls etwas nicht stimmt, kann das Backup wiederhergestellt werden:
Build mit lokal installiertem Go:
```bash
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o adguard-shield ./cmd/adguard-shieldd
```
Build ohne lokale Go-Installation mit Docker:
```bash
docker run --rm -v "$PWD":/src -w /src \
-e GOOS=linux -e GOARCH=amd64 -e CGO_ENABLED=0 \
golang:1.22 go build -o adguard-shield ./cmd/adguard-shieldd
```
Auf dem Zielserver muss Go nicht installiert sein, wenn dort nur das fertige Binary ausgeführt wird.
## Was `update` macht
Der Update-Befehl nutzt intern dieselbe Routine wie die Installation:
1. Linux- und root-Rechte prüfen.
2. Auf alte Shell-Artefakte prüfen.
3. Systemabhängigkeiten prüfen, sofern nicht `--skip-deps` gesetzt ist.
4. Installationsverzeichnis sicherstellen.
5. neues Binary nach `/opt/adguard-shield/adguard-shield` kopieren.
6. Konfiguration migrieren.
7. systemd-Service neu schreiben.
8. `systemctl daemon-reload` ausführen.
9. Autostart aktivieren, sofern nicht `--no-enable` gesetzt ist.
10. fragen, ob der Service direkt neu gestartet werden soll.
## Konfigurationsmigration
Vorhandene Werte bleiben erhalten. Neue Parameter werden ergänzt.
Wenn eine Migration nötig ist:
```text
/opt/adguard-shield/adguard-shield.conf # aktualisierte Konfiguration
/opt/adguard-shield/adguard-shield.conf.old # Backup der vorherigen Datei
```
Nach dem Update solltest du prüfen:
```bash
sudo diff -u /opt/adguard-shield/adguard-shield.conf.old /opt/adguard-shield/adguard-shield.conf
```
Falls `diff` keine Datei findet, war keine Konfigurationsmigration nötig.
## Update mit Service-Neustart
Wenn der Service nach dem Update direkt laufen soll, bestätige die Nachfrage am Ende mit `j`.
Wenn du vorher manuell prüfen möchtest:
```bash
sudo ./adguard-shield update
sudo /opt/adguard-shield/adguard-shield test
sudo /opt/adguard-shield/adguard-shield dry-run
sudo systemctl restart adguard-shield
```
## Update ohne Paketprüfung
```bash
sudo ./adguard-shield update --skip-deps
```
Das ist sinnvoll, wenn du sicher weißt, dass `iptables`, `ip6tables`, `ipset` und `systemctl` vorhanden sind oder wenn Paketinstallation auf deinem System nicht über `apt-get` laufen soll.
## Update in anderem Installationsverzeichnis
```bash
sudo ./adguard-shield update --install-dir /opt/adguard-shield-test
```
Beachte: Die systemd-Unit heißt weiterhin `adguard-shield.service`. Mehrere parallele produktive Installationen über dieselbe Unit sind nicht vorgesehen.
## Migration von der alten Shell-Version
Die Go-Version erkennt alte Shell-Artefakte und bricht ab, wenn sie noch vorhanden sind.
Typische Funde:
```text
/opt/adguard-shield/adguard-shield.sh
/opt/adguard-shield/iptables-helper.sh
/opt/adguard-shield/external-blocklist-worker.sh
/opt/adguard-shield/external-whitelist-worker.sh
/opt/adguard-shield/geoip-worker.sh
/opt/adguard-shield/offense-cleanup-worker.sh
/opt/adguard-shield/report-generator.sh
/opt/adguard-shield/unban-expired.sh
/etc/systemd/system/adguard-shield-watchdog.service
/etc/systemd/system/adguard-shield-watchdog.timer
```
Warum Abbruch?
Die alte und die neue Version würden sonst dieselbe Firewall, dieselbe Konfiguration und dieselben Sperren verwalten. Das kann zu schwer nachvollziehbaren Zuständen führen.
Empfohlener Migrationsablauf:
```bash
# Konfiguration sichern
sudo cp /opt/adguard-shield/adguard-shield.conf /root/adguard-shield.conf.backup
# alte Shell-Version mit deren Uninstaller entfernen
# dabei Konfiguration behalten, falls der alte Uninstaller diese Option anbietet
# neues Go-Binary installieren und alte Konfiguration als Quelle nutzen
sudo ./adguard-shield install --config-source /root/adguard-shield.conf.backup
# prüfen
sudo /opt/adguard-shield/adguard-shield test
sudo /opt/adguard-shield/adguard-shield dry-run
```
Wenn der Go-Installer Legacy-Dateien meldet, entferne nur die gemeldeten alten Artefakte der Shell-Version. Keine fremden Firewall-Regeln oder unrelated Dateien löschen.
## Nach dem Update prüfen
Installation:
```bash
sudo /opt/adguard-shield/adguard-shield install-status
```
Service:
```bash
sudo systemctl status adguard-shield
sudo journalctl -u adguard-shield --no-pager -n 100
```
API:
```bash
sudo /opt/adguard-shield/adguard-shield test
```
Runtime:
```bash
sudo /opt/adguard-shield/adguard-shield status
sudo /opt/adguard-shield/adguard-shield live --once
```
Firewall:
```bash
sudo /opt/adguard-shield/adguard-shield firewall-status
```
## Rollback
Ein Rollback besteht aus zwei Teilen: altes Binary wieder bereitstellen und passende Konfiguration verwenden.
Vorgehen:
1. Service stoppen.
2. altes Binary nach `/opt/adguard-shield/adguard-shield` kopieren.
3. optional `adguard-shield.conf.old` zurückkopieren.
4. Service starten.
Beispiel:
```bash
sudo systemctl stop adguard-shield
sudo cp ./adguard-shield-alte-version /opt/adguard-shield/adguard-shield
sudo chmod +x /opt/adguard-shield/adguard-shield
sudo systemctl start adguard-shield
```
Wenn die Konfiguration zurückgesetzt werden soll:
```bash
sudo cp /opt/adguard-shield/adguard-shield.conf.old /opt/adguard-shield/adguard-shield.conf
sudo systemctl restart adguard-shield
```
## Kurzfassung (Copy & Paste)
Hinweis: SQLite-Schema-Migrationen sind aktuell sehr konservativ. Trotzdem solltest du vor größeren Updates ein Backup von `/var/lib/adguard-shield/adguard-shield.db` erstellen, wenn dir History und aktive Sperren wichtig sind.
## Backup vor größeren Updates
```bash
cd /pfad/zum/adguard-shield
git pull
sudo bash install.sh update
sudo systemctl stop adguard-shield
sudo cp /opt/adguard-shield/adguard-shield.conf /root/adguard-shield.conf.$(date +%F)
sudo cp /var/lib/adguard-shield/adguard-shield.db /root/adguard-shield.db.$(date +%F)
sudo systemctl start adguard-shield
```
## Versionsprüfung
Bei laufendem SQLite mit WAL können zusätzliche Dateien existieren:
Installierte Version anzeigen:
```bash
sudo /opt/adguard-shield/adguard-shield.sh status
```text
adguard-shield.db-wal
adguard-shield.db-shm
```
Oder über den Installer:
```bash
sudo bash install.sh status
```
Am saubersten ist ein kurzer Service-Stop während des Backups.