docs: Dokumentation umfassend überarbeitet

This commit is contained in:
Patrick Asmus
2026-05-01 01:17:05 +02:00
parent a7f7dbdb71
commit 7bbdb104c4
10 changed files with 1970 additions and 1167 deletions

330
README.md
View File

@@ -24,164 +24,310 @@
## ✨ Was ist AdGuard Shield?
AdGuard Shield überwacht das Query Log deiner AdGuard-Home-Instanz und erkennt Clients, die eine Domain oder viele zufällige Subdomains in kurzer Zeit übermäßig oft anfragen. Auffällige Clients werden über eine eigene `iptables`/`ip6tables`-Chain auf DNS-relevanten Ports blockiert.
AdGuard Shield ist ein Go-basierter Sicherheitsdaemon, der das Query Log deiner AdGuard-Home-Instanz kontinuierlich überwacht. Er erkennt Clients, die eine Domain oder viele zufällige Subdomains in kurzer Zeit übermäßig oft anfragen, und sperrt sie automatisch über eine eigene `iptables`/`ip6tables`-Chain auf DNS-relevanten Ports.
Das schützt klassische DNS-Anfragen genauso wie DoH, DoT und DoQ, ohne deine bestehenden Firewall-Regeln unnötig anzufassen.
Das Projekt schützt klassische DNS-Anfragen genauso wie DNS-over-HTTPS (DoH), DNS-over-TLS (DoT), DNS-over-QUIC (DoQ) und DNSCrypt, ohne deine bestehenden Firewall-Regeln anzufassen. AdGuard Shield arbeitet nicht direkt am Netzwerkverkehr, sondern wertet das Querylog von AdGuard Home über dessen API aus. Dadurch werden auch verschlüsselte DNS-Protokolle zuverlässig erfasst, solange sie in AdGuard Home sichtbar sind.
Das gesamte Projekt ist als einzelnes, statisch kompiliertes Go-Binary realisiert, das gleichzeitig als Daemon, CLI-Werkzeug, Installer und Report-Generator fungiert. Es ersetzt die frühere Shell-basierte Implementierung mit mehreren Skripten, Cron-Jobs und einem separaten Watchdog.
## 🚀 Highlights
- Automatische Sperren bei Rate-Limit-Verstößen
- Erkennung von Random-Subdomain-Floods, z.B. `abc123.example.com`
- DNS-Flood-Watchlist: sofortiger permanenter Ban + AbuseIPDB-Meldung für definierte Domains
- Progressive Sperren für Wiederholungstäter, ähnlich wie bei fail2ban
- Unterstützung für DNS, DoH, DoT, DoQ und DNSCrypt
- IPv4 und IPv6
- Go-Daemon mit einem zentralen Querylog-Poller statt mehrerer Shell-Worker
- Eigene Firewall-Chain mit `ipset`-Sets für schnelle Sperren bei vielen IPs
- Firewall-Modi für klassische Installation, Docker Host Network und Docker mit veröffentlichten Ports
- Externe Blocklisten und dynamische externe Whitelists
- GeoIP-Länderfilter mit Blocklist- oder Allowlist-Modus
- AbuseIPDB-Reporting für permanent gesperrte IPs
- Benachrichtigungen über Ntfy, Discord, Slack, Gotify oder Generic Webhook
- E-Mail-Reports als HTML oder Text direkt aus dem Go-Binary
- systemd-Service mit Restart-Policy, ohne Shell-Worker
| Bereich | Funktionen |
|---|---|
| **Erkennung** | Rate-Limit-Überwachung pro Client und Domain, Random-Subdomain-Flood-Erkennung (z.B. `abc123.example.com`), DNS-Flood-Watchlist für sofortigen Permanent-Ban |
| **Sperren** | Progressive Sperren für Wiederholungstäter (fail2ban-ähnlich), temporäre und permanente Sperren, automatische Freigabe abgelaufener Sperren |
| **Protokolle** | DNS, DoH, DoT, DoQ und DNSCrypt, IPv4 und IPv6 |
| **Firewall** | Eigene Chain mit `ipset`-Sets für performante Sperren, Firewall-Modi für Host, Docker Host Network, Docker Bridge und Hybrid |
| **Listen** | Externe Blocklisten und dynamische externe Whitelists mit automatischer DNS-Auflösung |
| **GeoIP** | Länderbasierte Filterung mit Blocklist- oder Allowlist-Modus über MaxMind GeoLite2 |
| **Meldungen** | AbuseIPDB-Reporting für permanent gesperrte IPs |
| **Benachrichtigungen** | Ntfy, Discord, Slack, Gotify oder Generic Webhook |
| **Reports** | E-Mail-Reports als HTML oder Text mit konfigurierbarem Versandintervall |
| **Betrieb** | systemd-Service mit Restart-Policy, Terminal-Live-Ansicht, Dry-Run-Modus, SQLite-State |
## ✅ Voraussetzungen
- Linux-Server mit AdGuard Home
- Root-Zugriff per `sudo`
- Erreichbare AdGuard Home Web-API, standardmäßig `http://127.0.0.1:3000`
- `iptables`, `ip6tables`, `ipset` und `systemd`
| Komponente | Beschreibung |
|---|---|
| **Betriebssystem** | Linux-Server (Debian, Ubuntu oder kompatible Distribution) |
| **AdGuard Home** | Laufende Instanz mit erreichbarer Web-API (Standard: `http://127.0.0.1:3000`) |
| **Root-Zugriff** | Erforderlich für Firewall-Steuerung und Service-Management |
| **Systempakete** | `iptables`, `ip6tables`, `ipset` und `systemd` |
| **Optional** | `msmtp` für E-Mail-Reports, MaxMind-Account für GeoIP-Daten |
Die benötigten Pakete werden vom Go-Installer auf Ubuntu/Debian automatisch installiert.
Die benötigten Pakete werden vom Installer auf Ubuntu/Debian automatisch installiert, sofern `apt-get` verfügbar ist.
Wichtig: Go wird auf dem Server nicht benötigt, wenn du ein fertiges Linux-Binary installierst. Zum Erzeugen dieses Binarys brauchst du Go aber auf dem Rechner, auf dem du baust, oder alternativ Docker/CI/Release-Artefakte.
> **Hinweis:** Go wird auf dem Server nicht benötigt, wenn du ein fertiges Linux-Binary verwendest. Zum Erzeugen des Binarys brauchst du Go auf dem Build-Rechner oder alternativ Docker/CI/Release-Artefakte.
## ⚡ Schnellstart
```bash
git clone https://git.techniverse.net/scriptos/adguard-shield.git /tmp/adguard-shield
cd /tmp/adguard-shield
### Variante A: Fertiges Release-Binary
# Variante A: fertiges Release-Binary laden
```bash
# Release-Archiv herunterladen und entpacken
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
```
# Variante B: Linux-Binary lokal bauen, wenn Go installiert ist
### Variante B: Lokal mit Go bauen
```bash
git clone https://git.techniverse.net/scriptos/adguard-shield.git
cd adguard-shield
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o adguard-shield ./cmd/adguard-shieldd
```
# Variante C: ohne lokale Go-Installation per Docker bauen
### Variante C: Ohne lokales Go per Docker bauen
```bash
git clone https://git.techniverse.net/scriptos/adguard-shield.git
cd adguard-shield
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
```
# Fertiges Binary auf dem Server installieren
chmod +x ./adguard-shield
### Installation und erster Start
```bash
# Binary auf dem Server installieren
sudo ./adguard-shield install
# Der Installer fragt am Ende, ob AdGuard Shield direkt gestartet werden soll.
# Bestehende Shell-Installation?
# Der Go-Installer bricht ab und meldet die gefundenen Script-Artefakte.
# Die alte Version zuerst deinstallieren und die adguard-shield.conf behalten.
# Konfiguration anpassen (mindestens API-Zugangsdaten und Whitelist)
sudo nano /opt/adguard-shield/adguard-shield.conf
# Vor dem produktiven Start testen: loggt nur, sperrt nichts
# API-Verbindung testen
sudo /opt/adguard-shield/adguard-shield test
# Dry-Run: loggt Erkennungen, sperrt aber nicht
sudo /opt/adguard-shield/adguard-shield dry-run
# Service starten, falls du die Nachfrage verneint hast, und prüfen
# Service starten und prüfen
sudo systemctl start adguard-shield
sudo systemctl status adguard-shield
```
> Beim Installieren wird der systemd-Service für den Autostart registriert und am Ende nach dem direkten Start gefragt. Die Go-Version nutzt `Restart=on-failure`; einen separaten Watchdog-Timer wie in der alten Shell-Version gibt es nicht mehr.
> **Bestehende Shell-Installation?** Der Go-Installer bricht ab und meldet die gefundenen Script-Artefakte. Die alte Version muss zuerst deinstalliert werden (Konfiguration behalten). Details unter [docs/update.md](docs/update.md).
[![asciicast](https://asciinema.techniverse.net/a/77.svg)](https://asciinema.techniverse.net/a/77)
## 🔧 Wichtigste Befehle
## 🔧 Befehlsübersicht
AdGuard Shield wird über ein einzelnes Binary bedient. Die Grundform lautet:
```bash
sudo /opt/adguard-shield/adguard-shield <befehl>
```
### Installation & Updates
```bash
sudo ./adguard-shield install # Go-Binary installieren
sudo ./adguard-shield update # Binary, Service und Config-Migration aktualisieren
sudo ./adguard-shield install-status # Installationsstatus prüfen
sudo /opt/adguard-shield/adguard-shield uninstall --keep-config
```
| Befehl | Beschreibung |
|---|---|
| `install` | Binary, Konfiguration und systemd-Service installieren |
| `install --skip-deps` | Installation ohne automatische Paketprüfung |
| `install --no-enable` | Installation ohne systemd-Autostart |
| `install --config-source <pfad>` | Bestehende Konfiguration als Vorlage übernehmen |
| `update` | Binary, Service und Konfiguration aktualisieren |
| `install-status` | Installationsstatus anzeigen (Binary, Service, Version) |
| `uninstall` | Vollständige Deinstallation |
| `uninstall --keep-config` | Deinstallation mit Erhalt der Konfiguration |
### Betrieb & Diagnose
### Daemon & Service
```bash
sudo systemctl status adguard-shield
sudo systemctl restart adguard-shield
sudo journalctl -u adguard-shield -f
| Befehl | Beschreibung |
|---|---|
| `run` / `start` | Daemon im Vordergrund starten |
| `dry-run` | Daemon starten, der nur loggt aber nicht sperrt |
| `stop` | Laufenden Daemon über PID-Datei stoppen |
| `test` | API-Verbindung zu AdGuard Home testen |
| `version` | Installierte Version anzeigen |
sudo /opt/adguard-shield/adguard-shield status
sudo /opt/adguard-shield/adguard-shield live
sudo /opt/adguard-shield/adguard-shield history
sudo /opt/adguard-shield/adguard-shield logs --level warn
sudo /opt/adguard-shield/adguard-shield test
sudo /opt/adguard-shield/adguard-shield unban 192.0.2.10
sudo /opt/adguard-shield/adguard-shield flush
```
### Status & Monitoring
`live` zeigt eine Terminal-Ansicht mit aktuellen Queries, Top-Client/Domain-Zählungen, Subdomain-Flood-Kandidaten, aktiven Sperren und Systemereignissen. Query-Inhalte werden dabei nicht dauerhaft ins Systemlog geschrieben; `logs` und `logs-follow` sind für Daemon-, Worker- und Fehlerereignisse gedacht.
| Befehl | Beschreibung |
|---|---|
| `status` | Aktive Sperren und Konfigurationsübersicht anzeigen |
| `live` / `watch` | Terminal-Live-Ansicht mit Queries, Top-Clients, Sperren und Logs |
| `live --interval 2` | Live-Ansicht mit benutzerdefiniertem Aktualisierungsintervall |
| `live --top 20` | Live-Ansicht mit mehr Top-Einträgen |
| `live --recent 25` | Mehr letzte Queries und Logs anzeigen |
| `live --logs debug` | DEBUG-Logs in der Live-Ansicht einblenden |
| `live --logs off` | Log-Bereich in der Live-Ansicht ausblenden |
| `live --once` | Einmaligen Snapshot ausgeben |
| `history [N]` | Ban-History anzeigen (Standard: 50 Einträge) |
| `logs` | Daemon-Logeinträge anzeigen |
| `logs --level warn --limit 100` | Gefilterte Logs anzeigen |
| `logs-follow` | Logs in Echtzeit verfolgen |
### Optionale Module
### Sperren & Freigaben
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-status
sudo /opt/adguard-shield/adguard-shield whitelist-status
sudo /opt/adguard-shield/adguard-shield geoip-status
| Befehl | Beschreibung |
|---|---|
| `ban <IP>` | IP-Adresse manuell permanent sperren |
| `unban <IP>` | Sperre für eine IP-Adresse aufheben |
| `flush` | Alle aktiven Sperren aufheben |
sudo /opt/adguard-shield/adguard-shield report-status
sudo /opt/adguard-shield/adguard-shield report-generate html /tmp/adguard-shield-report.html
sudo /opt/adguard-shield/adguard-shield report-send
```
### Progressive Sperren (Offense-Tracking)
Die vollständige Befehlsreferenz steht in [docs/befehle.md](docs/befehle.md).
| Befehl | Beschreibung |
|---|---|
| `offense-status` | Offense-Zähler und Statistik anzeigen |
| `offense-cleanup` | Abgelaufene Offense-Zähler entfernen |
| `reset-offenses` | Alle Offense-Zähler zurücksetzen |
| `reset-offenses <IP>` | Offense-Zähler für eine bestimmte IP zurücksetzen |
### Firewall
| Befehl | Beschreibung |
|---|---|
| `firewall-create` | Firewall-Chain und ipsets anlegen |
| `firewall-status` | Aktuelle Firewall-Regeln und ipsets anzeigen |
| `firewall-flush` | ipsets leeren (Sperren entfernen, Struktur bleibt) |
| `firewall-remove` | Chain, Regeln und ipsets vollständig entfernen |
| `firewall-save` | Aktuelle iptables-Regeln in Datei sichern |
| `firewall-restore` | Gesicherte Regeln wiederherstellen |
### GeoIP
| Befehl | Beschreibung |
|---|---|
| `geoip-status` | GeoIP-Konfiguration und Status anzeigen |
| `geoip-lookup <IP>` | Land einer IP-Adresse nachschlagen |
| `geoip-sync` | Aktuelle Querylog-Clients einmalig gegen GeoIP prüfen |
| `geoip-flush` | Alle GeoIP-Sperren aufheben |
| `geoip-flush-cache` | GeoIP-Cache leeren |
### Externe Listen
| Befehl | Beschreibung |
|---|---|
| `blocklist-status` | Status der externen Blocklist anzeigen |
| `blocklist-sync` | Externe Blocklist sofort synchronisieren |
| `blocklist-flush` | Alle Sperren aus externer Blocklist aufheben |
| `whitelist-status` | Status der externen Whitelist anzeigen |
| `whitelist-sync` | Externe Whitelist sofort synchronisieren |
| `whitelist-flush` | Aufgelöste externe Whitelist-Einträge entfernen |
### E-Mail-Reports
| Befehl | Beschreibung |
|---|---|
| `report-status` | Report-Konfiguration und Cron-Status anzeigen |
| `report-generate html <datei>` | HTML-Report in Datei schreiben |
| `report-generate txt` | Text-Report auf stdout ausgeben |
| `report-test` | Testmail senden |
| `report-send` | Aktuellen Report erzeugen und per E-Mail versenden |
| `report-install` | Cron-Job für automatischen Versand installieren |
| `report-remove` | Cron-Job entfernen |
Die vollständige Befehlsreferenz mit Beispielen und typischen Betriebsabläufen steht in [docs/befehle.md](docs/befehle.md).
## ⚙️ Konfiguration
Die zentrale Konfiguration liegt nach der Installation hier:
Die zentrale Konfigurationsdatei liegt nach der Installation hier:
```text
/opt/adguard-shield/adguard-shield.conf
```
Wichtige Startpunkte:
Die Datei verwendet ein einfaches Shell-ähnliches Key-Value-Format. Nach Änderungen muss der Service neu gestartet werden:
- `ADGUARD_URL`, `ADGUARD_USER`, `ADGUARD_PASS` für die AdGuard-Home-API
- `RATE_LIMIT_MAX_REQUESTS`, `RATE_LIMIT_WINDOW` und `CHECK_INTERVAL` für die Erkennung
- `BAN_DURATION` und `PROGRESSIVE_BAN_*` für temporäre und progressive Sperren
- `FIREWALL_MODE` für klassische Installationen, Docker Host Network oder Docker Bridge
- `WHITELIST` für vertrauenswürdige Clients wie Router, Management-IPs oder lokale Resolver
- `DNS_FLOOD_WATCHLIST_*` für sofortigen Permanent-Ban bei bekannten Flood-Domains
- `NOTIFY_*`, `REPORT_*`, `GEOIP_*`, `EXTERNAL_BLOCKLIST_*` und `EXTERNAL_WHITELIST_*` für optionale Funktionen
```bash
sudo systemctl restart adguard-shield
```
### Wichtigste Parameter
| Parameter | Standard | Beschreibung |
|---|---|---|
| `ADGUARD_URL` | `https://dns1.domain.com` | URL der AdGuard-Home-API |
| `ADGUARD_USER` | `admin` | API-Benutzername |
| `ADGUARD_PASS` | `changeme` | API-Passwort |
| `RATE_LIMIT_MAX_REQUESTS` | `30` | Maximale Anfragen pro Client/Domain im Zeitfenster |
| `RATE_LIMIT_WINDOW` | `60` | Zeitfenster in Sekunden |
| `CHECK_INTERVAL` | `10` | Abstand zwischen Querylog-Abfragen in Sekunden |
| `BAN_DURATION` | `3600` | Basis-Sperrdauer in Sekunden (1 Stunde) |
| `FIREWALL_MODE` | `host` | `host`, `docker-host`, `docker-bridge` oder `hybrid` |
| `WHITELIST` | `127.0.0.1,::1` | IPs, die nie gesperrt werden (kommagetrennt) |
| `DRY_RUN` | `false` | Testmodus: nur loggen, nicht sperren |
### Optionale Module
| Modul | Aktivierung | Beschreibung |
|---|---|---|
| Subdomain-Flood | `SUBDOMAIN_FLOOD_ENABLED=true` | Erkennung von Random-Subdomain-Angriffen |
| DNS-Flood-Watchlist | `DNS_FLOOD_WATCHLIST_ENABLED=true` | Sofortiger Permanent-Ban für definierte Domains |
| Progressive Sperren | `PROGRESSIVE_BAN_ENABLED=true` | Stufenweise längere Sperren für Wiederholungstäter |
| GeoIP-Länderfilter | `GEOIP_ENABLED=true` | Ländersperre per MaxMind-Datenbank |
| Externe Blocklist | `EXTERNAL_BLOCKLIST_ENABLED=true` | IP-Sperren aus externen Listen |
| Externe Whitelist | `EXTERNAL_WHITELIST_ENABLED=true` | Dynamische Whitelist mit DNS-Auflösung |
| Benachrichtigungen | `NOTIFY_ENABLED=true` | Push-Benachrichtigungen bei Sperrereignissen |
| E-Mail-Reports | `REPORT_ENABLED=true` | Periodische Statistik-Reports per E-Mail |
| AbuseIPDB | `ABUSEIPDB_ENABLED=true` | Automatische Meldung permanenter Sperren |
Bei Updates migriert der Installer die bestehende Konfiguration automatisch: vorhandene Werte bleiben erhalten, neue Parameter werden ergänzt und die alte Datei wird als `adguard-shield.conf.old` gesichert.
Mehr Details findest du in [docs/konfiguration.md](docs/konfiguration.md).
Die vollständige Parameterbeschreibung mit Beispielkonfigurationen findest du in [docs/konfiguration.md](docs/konfiguration.md).
## 🧭 Dokumentation
## 🧩 Wie AdGuard Shield arbeitet
| Thema | Link |
|---|---|
| Architektur & Funktionsweise | [docs/architektur.md](docs/architektur.md) |
| Befehle & Nutzung | [docs/befehle.md](docs/befehle.md) |
| Konfiguration | [docs/konfiguration.md](docs/konfiguration.md) |
| Docker-Installationen | [docs/docker.md](docs/docker.md) |
| Benachrichtigungen | [docs/benachrichtigungen.md](docs/benachrichtigungen.md) |
| E-Mail Report | [docs/report.md](docs/report.md) |
| Updates | [docs/update.md](docs/update.md) |
| Tipps & Troubleshooting | [docs/tipps-und-troubleshooting.md](docs/tipps-und-troubleshooting.md) |
## 🧩 Wie es arbeitet
```text
DNS-Clients
│ DNS, DoH, DoT, DoQ, DNSCrypt
AdGuard Home
│ /control/querylog API
AdGuard Shield Daemon (pollt alle CHECK_INTERVAL Sekunden)
├── Rate-Limit-Prüfung (Client + Domain)
├── Subdomain-Flood-Erkennung (Client + Basisdomain)
├── DNS-Flood-Watchlist-Abgleich
├── Whitelist-Prüfung (statisch + extern)
├── GeoIP-Prüfung (falls aktiviert)
├── Progressive Ban-Berechnung
└── History-Protokollierung
SQLite-Datenbank (active_bans, ban_history, offense_tracking)
ipset + iptables/ip6tables
DNS-relevante Ports (53, 443, 853) werden für gesperrte Clients blockiert
```
1. AdGuard Shield liest regelmäßig das AdGuard-Home-Query-Log über die API.
2. Anfragen werden pro Client, Domain und Protokoll ausgewertet.
3. Überschreitet ein Client die konfigurierten Limits, wird er gegen Whitelist und Sonderregeln geprüft.
4. Die Sperre landet in der eigenen Firewall-Chain `ADGUARD_SHIELD`.
3. Überschreitet ein Client die konfigurierten Limits, wird er gegen Whitelist, GeoIP und Sonderregeln geprüft.
4. Die Sperre landet in der eigenen Firewall-Chain `ADGUARD_SHIELD` und wird in SQLite gespeichert.
5. Ban-History, Logs und optionale Benachrichtigungen dokumentieren das Ereignis.
6. Temporäre Sperren werden automatisch entfernt, permanente Sperren bleiben bis zur manuellen Freigabe aktiv.
7. Bei einem Neustart werden alle aktiven Sperren aus SQLite wieder in die Firewall übertragen.
## 🧭 Dokumentation
| Thema | Link | Beschreibung |
|---|---|---|
| Architektur & Funktionsweise | [docs/architektur.md](docs/architektur.md) | Aufbau, Datenfluss, Firewall-Modell, SQLite-Schema, Hintergrundjobs und Sperrlogik |
| Befehle & Nutzung | [docs/befehle.md](docs/befehle.md) | Vollständige CLI-Referenz mit Beispielen und typischen Betriebsabläufen |
| Konfiguration | [docs/konfiguration.md](docs/konfiguration.md) | Alle Parameter aus `adguard-shield.conf` mit Beispielen und Empfehlungen |
| Docker-Installationen | [docs/docker.md](docs/docker.md) | Firewall-Modi für klassische Installation, Docker Host Network und Docker Bridge |
| Benachrichtigungen | [docs/benachrichtigungen.md](docs/benachrichtigungen.md) | Einrichtung von Ntfy, Discord, Slack, Gotify und Generic Webhooks |
| E-Mail Report | [docs/report.md](docs/report.md) | Report-Inhalte, Mailversand, Cron-Job und manuelle Tests |
| Updates | [docs/update.md](docs/update.md) | Update-Ablauf, Konfigurationsmigration und Migration von der Shell-Version |
| Tipps & Troubleshooting | [docs/tipps-und-troubleshooting.md](docs/tipps-und-troubleshooting.md) | Diagnosewege für API, Firewall, GeoIP, Reports, Listen und falsche Sperren |
## 📜 Lizenz
Dieses Projekt steht unter der [MIT-Lizenz](./LICENSE).
<br><br>
<p align="center">

View File

@@ -8,18 +8,18 @@ AdGuard Shield ist ein Go-Daemon, der das Query Log von AdGuard Home auswertet,
| Dokument | Wofür es gedacht ist |
|---|---|
| [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 |
| [Architektur & Funktionsweise](architektur.md) | Erklärt den Aufbau, den Datenfluss, Firewall-Modell, SQLite-Schema, Hintergrundjobs und Sperrlogik |
| [Befehle & Nutzung](befehle.md) | Vollständige CLI-Referenz mit Beispielen und typischen Betriebsabläufen |
| [Konfiguration](konfiguration.md) | Alle Parameter aus `adguard-shield.conf` mit Beispielen, Empfehlungen und Beispielkonfigurationen |
| [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 |
| [Benachrichtigungen](benachrichtigungen.md) | Einrichtung von Ntfy, Discord, Slack, Gotify und Generic Webhooks mit Beispielinhalten |
| [E-Mail Report](report.md) | Report-Inhalte, Formate, Mailversand, Cron-Job und manuelle Tests |
| [Update-Anleitung](update.md) | Update der Go-Version, Konfigurationsmigration und Migration von alten Shell-Installationen |
| [Tipps & Troubleshooting](tipps-und-troubleshooting.md) | Diagnosewege für API, Firewall, GeoIP, Reports, externe Listen und falsch gesetzte Sperren |
## Wichtigster Unterschied zur alten Shell-Version
## Das Binary
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:
Die Go-Version bündelt alle Aufgaben in einem einzelnen Binary:
```text
/opt/adguard-shield/adguard-shield
@@ -27,11 +27,11 @@ Die frühere Version bestand aus mehreren Shell-Skripten, Hilfs-Workern, Cron-Jo
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
- **Daemon** für den produktiven Betrieb (Querylog-Polling, Erkennung, Sperren)
- **CLI** für Status, History, Logs, Firewall, Listen, GeoIP und Reports
- **Installer**, **Updater** und **Uninstaller**
- **Report-Generator** für HTML- und Text-Reports
- **Hintergrundprozess** für externe Whitelist, externe Blocklist, GeoIP und Offense-Cleanup
Die meisten Befehle beginnen daher mit:
@@ -48,12 +48,35 @@ sudo ./adguard-shield update
## Empfohlener Lesefluss
Wenn du AdGuard Shield neu einrichtest:
### Neueinrichtung
1. Lies zuerst [Architektur & Funktionsweise](architektur.md), damit klar ist, was genau gesperrt wird.
1. Lies zuerst [Architektur & Funktionsweise](architektur.md), damit klar ist, was genau gesperrt wird und wie der Datenfluss aussieht.
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).
### Migration von der Shell-Version
Wenn du von der alten Shell-Version kommst, beginne mit [Update-Anleitung](update.md). Dort findest du den empfohlenen Migrationsablauf und Hinweise zu den erkannten Legacy-Artefakten.
### Docker-Setups
Wenn AdGuard Home in Docker läuft, lies [Docker-Installationen](docker.md) zusätzlich zur Grundkonfiguration. Der Firewall-Modus bestimmt, in welcher Chain die Sperren greifen.
## Wichtigster Unterschied zur alten Shell-Version
Die frühere Version bestand aus mehreren Shell-Skripten, Hilfs-Workern, Cron-Jobs und einem separaten Watchdog:
| Alte Shell-Version | Go-Version |
|---|---|
| `adguard-shield.sh` (Hauptskript) | Ein Binary für alles |
| `iptables-helper.sh` | Integriert im Binary |
| `external-blocklist-worker.sh` | Goroutine im Daemon |
| `external-whitelist-worker.sh` | Goroutine im Daemon |
| `geoip-worker.sh` | Goroutine im Daemon |
| `offense-cleanup-worker.sh` | Goroutine im Daemon |
| `report-generator.sh` | Integriert im Binary |
| `unban-expired.sh` | Integriert im Daemon |
| Watchdog-Service + Timer | `Restart=on-failure` in systemd |
| Mehrere Cron-Jobs | Ein optionaler Cron-Job für Reports |

View File

@@ -1,6 +1,6 @@
# Architektur & Funktionsweise
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.
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 und die Logik hinter jeder Erkennungsmethode.
## Kurzüberblick
@@ -29,32 +29,33 @@ Das Binary übernimmt alle Aufgaben, die früher auf mehrere Shell-Skripte verte
```text
Clients
|
| DNS, DoH, DoT, DoQ, DNSCrypt
v
DNS, DoH, DoT, DoQ, DNSCrypt
AdGuard Home
|
| /control/querylog
v
/control/querylog
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
├── Rate-Limit-Prüfung pro Client + Domain
├── Subdomain-Flood-Prüfung pro Client + Basisdomain
├── Watchlist-Prüfung
├── Whitelist-Prüfung (statisch + extern)
├── GeoIP-Prüfung
├── Progressive Ban-Berechnung
├── externe Listen-Abgleich
SQLite State
|
v
ipset + iptables/ip6tables
|
v
DNS-relevante Ports werden für gesperrte Clients blockiert
```
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.
**Wichtig:** AdGuard Shield analysiert nicht den Netzwerkverkehr direkt. Es liest das Querylog von AdGuard Home. Dadurch erkennt es auch Anfragen über verschlüsselte DNS-Protokolle (DoH, DoT, DoQ, DNSCrypt), solange diese in AdGuard Home sichtbar sind.
## Laufzeit im produktiven Betrieb
@@ -66,18 +67,20 @@ Der systemd-Service startet den Daemon so:
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.
| Schritt | Aktion | Beschreibung |
|---:|---|---|
| 1 | Konfiguration laden | Liest `adguard-shield.conf` und validiert alle Parameter |
| 2 | SQLite-Datenbank öffnen | Öffnet oder erstellt die Datenbank unter `STATE_DIR` im WAL-Modus |
| 3 | Logdatei öffnen | Initialisiert die Datei unter `LOG_FILE` |
| 4 | Firewall vorbereiten | Erstellt Chain und ipsets, falls nicht vorhanden |
| 5 | GeoIP öffnen | Lädt die MaxMind-Datenbank, falls GeoIP aktiviert ist |
| 6 | Whitelist-Cache laden | Liest aufgelöste externe Whitelist-IPs aus SQLite |
| 7 | GeoIP-Reconcile | Prüft bestehende GeoIP-Sperren gegen aktuelle Konfiguration |
| 8 | Firewall-Reconcile | Überträgt aktive Sperren aus SQLite wieder in die Firewall |
| 9 | Hintergrundjobs starten | Startet Goroutines für externe Listen und Offense-Cleanup |
| 10 | Querylog-Poller starten | Beginnt mit der regelmäßigen Auswertung des Querylogs |
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.
Das Reconcile beim Start ist besonders wichtig: Wenn der Server neu startet oder `iptables`-Regeln verloren gehen (z.B. durch einen Reboot), bleiben die Sperren in SQLite erhalten und werden beim nächsten Start wieder in die Firewall übertragen.
## Querylog-Poller
@@ -90,8 +93,8 @@ Der Daemon ruft regelmäßig den AdGuard-Home-Endpunkt ab:
Gesteuert wird das über:
```bash
CHECK_INTERVAL=10
API_QUERY_LIMIT=500
CHECK_INTERVAL=10 # Abstand zwischen Abfragen in Sekunden
API_QUERY_LIMIT=500 # Maximale Einträge pro API-Abfrage
```
Aus jedem Querylog-Eintrag werden diese Informationen extrahiert:
@@ -103,20 +106,22 @@ Aus jedem Querylog-Eintrag werden diese Informationen extrahiert:
| 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.
Bereits gesehene Querylog-Einträge werden im Speicher dedupliziert. Der Daemon hält nur Ereignisse aus dem relevanten Zeitfenster plus kleinem Puffer vor, sodass der Speicherverbrauch auch bei hohem DNS-Aufkommen stabil bleibt.
## Rate-Limit-Sperre
## Erkennungsmethoden im Detail
### Rate-Limit-Sperre
Eine Rate-Limit-Sperre entsteht, wenn ein Client dieselbe Domain innerhalb des konfigurierten Fensters zu oft abfragt.
Beispiel:
**Konfiguration:**
```bash
RATE_LIMIT_MAX_REQUESTS=30
RATE_LIMIT_WINDOW=60
RATE_LIMIT_MAX_REQUESTS=30 # Maximale Anfragen pro Client und Domain
RATE_LIMIT_WINDOW=60 # Zeitfenster in Sekunden
```
Ablauf:
**Ablauf am Beispiel:**
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.
@@ -128,134 +133,153 @@ Ablauf:
8. Die IP wird in SQLite gespeichert und per Firewall blockiert.
9. History, Log und optionale Benachrichtigung werden geschrieben.
## Subdomain-Flood-Erkennung
### 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:
Random-Subdomain-Floods sehen anders aus als normale Wiederholungen. Ein Client fragt nicht eine Domain ständig ab, sondern erzeugt viele verschiedene, oft zufällige Subdomains:
```text
a8f3.example.com
k29x.example.com
z9p1.example.com
m7q2.example.com
```
AdGuard Shield extrahiert daraus die Basisdomain `example.com` und zählt pro Client, wie viele unterschiedliche Subdomains im Fenster vorkommen.
AdGuard Shield extrahiert daraus die Basisdomain `example.com` und zählt pro Client, wie viele **unterschiedliche** Subdomains im Fenster vorkommen. Direkte Anfragen an `example.com` selbst werden bei dieser Erkennung nicht mitgezählt.
Gesteuert wird das über:
**Konfiguration:**
```bash
SUBDOMAIN_FLOOD_ENABLED=true
SUBDOMAIN_FLOOD_MAX_UNIQUE=50
SUBDOMAIN_FLOOD_WINDOW=60
SUBDOMAIN_FLOOD_MAX_UNIQUE=50 # Maximale eindeutige Subdomains
SUBDOMAIN_FLOOD_WINDOW=60 # Zeitfenster in Sekunden
```
Ablauf:
**Ablauf am Beispiel:**
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.
2. Sobald mehr als `SUBDOMAIN_FLOOD_MAX_UNIQUE` eindeutige Subdomains erkannt werden, wird gesperrt.
3. In der History erscheint die Domain als `*.example.com`.
4. Der Grund lautet `subdomain-flood`, außer die Basisdomain steht auf der DNS-Flood-Watchlist.
## DNS-Flood-Watchlist
**Hinweise:**
- Multi-Part-TLDs wie `.co.uk` werden korrekt als Basisdomain erkannt.
- CDNs und manche Apps erzeugen legitim viele Subdomains. In solchen Fällen den Grenzwert erhöhen oder den Client whitelisten.
### 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.
**Konfiguration:**
```bash
DNS_FLOOD_WATCHLIST_ENABLED=true
DNS_FLOOD_WATCHLIST="microsoft.com,google.com"
```
Matching:
**Matching-Logik:**
- `microsoft.com` matcht `microsoft.com`
- `login.microsoft.com` matcht ebenfalls `microsoft.com`
- `evil-microsoft.com` matcht nicht
| Anfrage | Watchlist-Eintrag | Treffer? |
|---|---|---|
| `microsoft.com` | `microsoft.com` | Ja |
| `login.microsoft.com` | `microsoft.com` | Ja |
| `evil-microsoft.com` | `microsoft.com` | Nein |
Bei einem Treffer:
**Bei einem Treffer:**
- Reason wird `dns-flood-watchlist`
- Sperre ist permanent
- Sperre ist immer 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
- AbuseIPDB-Reporting wird ausgelöst, wenn aktiviert und ein API-Key vorhanden ist
## Progressive Sperren
### Progressive Sperren
Progressive Sperren erhöhen die Sperrdauer bei wiederholten Monitor-Sperren. Das Verhalten ähnelt fail2ban.
Progressive Sperren erhöhen die Sperrdauer bei wiederholten Verstößen. Das Verhalten ähnelt fail2ban.
Standard:
**Konfiguration:**
```bash
BAN_DURATION=3600
BAN_DURATION=3600 # Basis-Sperrdauer: 1 Stunde
PROGRESSIVE_BAN_ENABLED=true
PROGRESSIVE_BAN_MULTIPLIER=2
PROGRESSIVE_BAN_MAX_LEVEL=5
PROGRESSIVE_BAN_RESET_AFTER=86400
PROGRESSIVE_BAN_MULTIPLIER=2 # Verdopplung pro Stufe
PROGRESSIVE_BAN_MAX_LEVEL=5 # Ab Stufe 5 permanent
PROGRESSIVE_BAN_RESET_AFTER=86400 # Zähler-Reset nach 24h ohne Vergehen
```
Beispiel:
**Stufenverlauf mit Standardwerten:**
| Vergehen | Stufe | Dauer |
|---|---:|---|
| 1 | 1 | 1 Stunde |
| 2 | 2 | 2 Stunden |
| 3 | 3 | 4 Stunden |
| 4 | 4 | 8 Stunden |
| 5 | 5 | permanent |
| Vergehen | Stufe | Berechnung | Sperrdauer |
|---:|---:|---|---|
| 1 | 1 | 3600 × 2⁰ | 1 Stunde |
| 2 | 2 | 3600 × 2¹ | 2 Stunden |
| 3 | 3 | 3600 × 2² | 4 Stunden |
| 4 | 4 | 3600 × 2³ | 8 Stunden |
| 5 | 5 | Max-Level erreicht | 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.
Der Offense-Zähler wird in SQLite gespeichert. Wenn eine IP länger als `PROGRESSIVE_BAN_RESET_AFTER` (Standard: 24 Stunden) nicht auffällig war, wird der Zähler vom Cleanup-Job entfernt.
Progressive Sperren gelten für Monitor-Sperren. GeoIP- und externe Blocklist-Sperren haben eigene Regeln.
**Geltungsbereich:** Progressive Sperren gelten nur für Monitor-Sperren (`rate-limit`, `subdomain-flood`). Watchlist-Treffer sind sofort permanent. GeoIP- und externe Blocklist-Sperren haben eigene Regeln.
## Firewall-Modell
AdGuard Shield nutzt eine eigene Chain und zwei ipsets:
AdGuard Shield nutzt eine eigene Chain und zwei ipsets, um gesperrte IPs effizient zu verwalten:
```text
ADGUARD_SHIELD
adguard_shield_v4
adguard_shield_v6
Chain: ADGUARD_SHIELD
IPv4: adguard_shield_v4
IPv6: adguard_shield_v6
```
### Chain-Einbindung
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` |
| Modus | Parent-Chain | Einsatzgebiet |
|---|---|---|
| `host` / `docker-host` | `INPUT` | Klassische Installation oder Docker mit Host-Netzwerk |
| `docker-bridge` | `DOCKER-USER` | Docker mit veröffentlichten Ports (`-p 53:53`) |
| `hybrid` | `INPUT` und `DOCKER-USER` | Gemischte Setups oder Migrationsphasen |
Für klassische Installationen und Docker mit Host-Netzwerk sieht das so aus:
### Regelstruktur im Host-Modus
```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
├── 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
├── 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.
Bei Docker Bridge mit veröffentlichten Ports ersetzt `DOCKER-USER` die `INPUT`-Chain. Docker leitet solche Pakete nach DNAT über `FORWARD`; die `INPUT`-Chain sieht sie dort nicht zuverlässig.
Die Ports kommen aus:
### Blockierte Ports
Die Ports werden über `BLOCKED_PORTS` konfiguriert:
```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.
| Port | Protokoll | Zweck |
|---:|---|---|
| 53 | UDP/TCP | Klassisches DNS |
| 443 | TCP | DNS-over-HTTPS (DoH) |
| 853 | TCP/UDP | DNS-over-TLS (DoT) und DNS-over-QUIC (DoQ) |
Warum `ipset`?
Die Erkennung basiert auf dem AdGuard-Home-Querylog, die Sperre blockiert aber alle konfigurierten Ports, unabhängig davon, welches Protokoll den Verstoß ausgelöst hat.
- viele gesperrte IPs erzeugen nicht tausende einzelne iptables-Regeln
### 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
- Sperren und Freigaben sind performant, auch bei hunderten IPs
- Die eigene Chain bleibt übersichtlich und beeinträchtigt bestehende Regeln nicht
## SQLite-State
@@ -265,17 +289,25 @@ Der zentrale Zustand liegt standardmäßig hier:
/var/lib/adguard-shield/adguard-shield.db
```
Wichtige Tabellen:
### Tabellen
| Tabelle | Inhalt |
| Tabelle | Inhalt | Beschreibung |
|---|---|---|
| `active_bans` | Aktive Sperren | IP, Grund, Dauer, Quelle, Ablaufzeit, Offense-Level, GeoIP-Metadaten |
| `ban_history` | Dauerhafte Historie | Zeitstempel, Aktion (BAN/UNBAN/DRY), Client-IP, Domain, Protokoll, Grund |
| `offense_tracking` | Progressive-Ban-Stufen | Client-IP, aktuelle Offense-Stufe, letzter Verstoß |
| `whitelist_cache` | Externe Whitelist | Aufgelöste IPs aus externen Whitelist-URLs mit Quellzuordnung |
| `geoip_cache` | GeoIP-Ergebnisse | IP, Ländercode, Zeitstempel der Abfrage, DB-Änderungszeitpunkt |
Die Datenbank nutzt WAL-Modus (Write-Ahead Logging) und einen Busy-Timeout, damit Daemon und CLI-Befehle gleichzeitig lesen und schreiben können, ohne sich gegenseitig zu blockieren.
### History-Aktionen
| Aktion | Bedeutung |
|---|---|
| `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 |
Die Datenbank nutzt WAL-Modus und einen Busy-Timeout, damit Daemon und CLI-Befehle gleichzeitig lesen können.
| `BAN` | Aktive Sperre gesetzt (Firewall-Regel erstellt) |
| `UNBAN` | Sperre aufgehoben (manuell, abgelaufen oder durch Whitelist) |
| `DRY` | Sperre wäre gesetzt worden, wurde aber im Dry-Run nur protokolliert |
## Verzeichnisstruktur
@@ -292,116 +324,155 @@ Nach einer Standardinstallation sieht die Struktur so aus:
└── adguard-shield.service
/var/lib/adguard-shield/
├── adguard-shield.db
├── external-blocklist/
├── external-whitelist/
├── iptables-rules.v4
── iptables-rules.v6
├── adguard-shield.db # SQLite State-Datenbank
├── adguard-shield.db-wal # WAL-Datei (im laufenden Betrieb)
├── adguard-shield.db-shm # Shared-Memory-Datei (im laufenden Betrieb)
├── external-blocklist/ # Cache für heruntergeladene Blocklisten
── external-whitelist/ # Cache für heruntergeladene Whitelists
├── iptables-rules.v4 # Gesicherte IPv4-Regeln (nach firewall-save)
└── iptables-rules.v6 # Gesicherte IPv6-Regeln (nach firewall-save)
/var/log/
└── adguard-shield.log
└── adguard-shield.log # Daemon-Logdatei
/etc/cron.d/
└── adguard-shield-report # Cron-Job für Reports (optional)
```
## Hintergrundjobs im Daemon
Es gibt in der Go-Version keine separaten Worker-Skripte mehr. Diese Aufgaben laufen als Goroutines im Daemon:
| 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 |
| Aufgabe | Wann aktiv | Intervall | Zweck |
|---|---|---|---|
| Querylog-Poller | Immer | `CHECK_INTERVAL` | Liest und analysiert AdGuard-Home-Querylogs |
| Externe Whitelist | `EXTERNAL_WHITELIST_ENABLED=true` | `EXTERNAL_WHITELIST_INTERVAL` | Lädt Listen, löst Hostnamen auf, aktualisiert Whitelist-Cache |
| Externe Blocklist | `EXTERNAL_BLOCKLIST_ENABLED=true` | `EXTERNAL_BLOCKLIST_INTERVAL` | Lädt Listen, sperrt neue IPs, hebt entfernte IPs optional auf |
| Offense-Cleanup | `PROGRESSIVE_BAN_ENABLED=true` | Stündlich | Entfernt abgelaufene Offense-Zähler |
| GeoIP-Lookups | `GEOIP_ENABLED=true` | Mit jedem Poll | Prüft neue öffentliche Client-IPs gegen Länderregeln |
Externe Whitelist und Blocklist laufen sofort beim Start einmalig und danach im jeweiligen Intervall.
Externe Whitelist und Blocklist laufen sofort beim Start einmalig und danach im jeweiligen Intervall. Die Sperren-Freigabe abgelaufener Bans wird bei jedem Querylog-Poll mit geprüft.
## Whitelist-Logik
Vor jeder Sperre wird geprüft, ob die IP vertrauenswürdig ist.
Quellen:
**Quellen (in Prüfreihenfolge):**
- statische `WHITELIST` aus der Konfiguration
- aufgelöste IPs aus externen Whitelists
1. Statische `WHITELIST` aus der Konfiguration (kommagetrennt)
2. Aufgelöste IPs aus externen Whitelists (gespeichert in SQLite)
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.
**Verhalten:**
- Eine gewhitelistete IP wird nie gesperrt, unabhängig von der Sperrquelle.
- Dies gilt für automatische Sperren, manuelle Sperren, GeoIP-Sperren und externe Blocklist-Sperren.
- 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.
GeoIP arbeitet mit der MaxMind GeoLite2-Datenbank und filtert DNS-Clients nach ihrem geografischen Herkunftsland.
Modi:
### Private IPs
Wenn `GEOIP_SKIP_PRIVATE=true` gesetzt ist (Standard), werden folgende Adressbereiche übersprungen:
- Private Netze (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- Loopback (127.0.0.0/8, ::1)
- Link-Local (169.254.0.0/16, fe80::/10)
- CGNAT (100.64.0.0/10)
### 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 |
| `blocklist` | Nur die in `GEOIP_COUNTRIES` genannten Länder werden gesperrt. Alle anderen sind erlaubt. |
| `allowlist` | Nur die in `GEOIP_COUNTRIES` genannten Länder sind erlaubt. Alle anderen öffentlichen IPs 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.
Die Ländercodes folgen dem Standard ISO 3166-1 Alpha-2 (siehe [ISO-3166-1-Kodierliste auf Wikipedia](https://de.wikipedia.org/wiki/ISO-3166-1-Kodierliste)).
### GeoIP-Datenquellen (Priorität)
| Priorität | Quelle | Konfiguration |
|---:|---|---|
| 1 | Manueller MMDB-Pfad | `GEOIP_MMDB_PATH="/pfad/zur/GeoLite2-Country.mmdb"` |
| 2 | Automatischer MaxMind-Download | `GEOIP_LICENSE_KEY="dein_key"` |
| 3 | Legacy-Fallback | `geoiplookup` / `geoiplookup6` (Systembefehle) |
**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, wird die Sperre automatisch aufgehoben.
## AbuseIPDB-Reporting
AbuseIPDB wird nur für permanente Monitor-Sperren genutzt:
AbuseIPDB wird nur für **permanente** Monitor-Sperren genutzt:
- DNS-Flood-Watchlist-Treffer
- Progressive-Ban-Sperren, die die maximale Stufe erreicht haben
| Wird gemeldet | Wird nicht gemeldet |
|---|---|
| DNS-Flood-Watchlist-Treffer | Temporäre Rate-Limit-Sperren |
| Progressive-Ban auf Maximalstufe | Manuelle Sperren |
| | GeoIP-Sperren |
| | Externe Blocklist-Sperren |
Nicht gemeldet werden:
- temporäre Rate-Limit-Sperren
- manuelle Sperren
- GeoIP-Sperren
- externe Blocklist-Sperren
Voraussetzung:
**Konfiguration:**
```bash
ABUSEIPDB_ENABLED=true
ABUSEIPDB_API_KEY="..."
ABUSEIPDB_CATEGORIES="4" # 4 = DDoS Attack
```
Die Kategorie-Nummern sind auf [abuseipdb.com/categories](https://www.abuseipdb.com/categories) dokumentiert.
## Protokollerkennung
AdGuard Shield liest das Feld `client_proto` aus der AdGuard-Home-API und zeigt das Protokoll in History, Logs und Benachrichtigungen an:
| API-Wert | Anzeige | Beschreibung |
|---|---|---|
| leer oder `dns` | `DNS` | Klassisches DNS über UDP/TCP |
| `doh` | `DoH` | DNS-over-HTTPS |
| `dot` | `DoT` | DNS-over-TLS |
| `doq` | `DoQ` | DNS-over-QUIC |
| `dnscrypt` | `DNSCrypt` | DNSCrypt-Protokoll |
Die Sperre blockiert die konfigurierten Ports unabhängig davon, welches Protokoll den Verstoß ausgelöst hat. So wird verhindert, dass ein gesperrter Client einfach auf ein anderes DNS-Protokoll ausweicht.
## History und Logs
Es gibt zwei unterschiedliche Blickwinkel:
Es gibt zwei unterschiedliche Blickwinkel auf das Geschehen:
| Quelle | Inhalt |
| Quelle | Inhalt | Befehl |
|---|---|---|
| `ban_history` in SQLite | Sperren, Freigaben und Dry-Run-Ereignisse | `history [N]` |
| `LOG_FILE` | Daemon-Ereignisse, Worker-Läufe, Warnungen, Fehler | `logs`, `logs-follow` |
| Live-Ansicht | Aktuelle Queries, Top-Clients, Sperren, Systemereignisse | `live` |
**Wichtig:** Query-Inhalte werden nicht dauerhaft in die Logdatei geschrieben. Für aktuelle Queries ist die Live-Ansicht (`live`) gedacht.
### History-Gründe
| Grund | Bedeutung |
|---|---|
| `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
```
| `rate-limit` | Gleiche Domain zu oft angefragt |
| `subdomain-flood` | Zu viele eindeutige Subdomains einer Basisdomain |
| `dns-flood-watchlist` | Watchlist-Treffer mit sofortigem Permanent-Ban |
| `external-blocklist` | Sperre aus externer Blocklist |
| `geoip` | GeoIP-Länderfilter |
| `manual` | Manueller Ban oder Unban |
| `manual-flush` | Freigabe aller Sperren durch `flush` |
| `expired` | Temporäre Sperre ist abgelaufen |
| `external-whitelist` | Freigabe durch externe Whitelist |
## 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
- `adguard-shield.sh` (Hauptskript)
- `iptables-helper.sh` (Firewall-Management)
- `external-blocklist-worker.sh` (Blocklist-Synchronisation)
- `external-whitelist-worker.sh` (Whitelist-Synchronisation)
- `geoip-worker.sh` (GeoIP-Prüfung)
- `offense-cleanup-worker.sh` (Offense-Bereinigung)
- `report-generator.sh` (Report-Erstellung)
- `unban-expired.sh` (Ablauf temporärer Sperren)
- Watchdog-Service und Watchdog-Timer (Überwachung)
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.
In der Go-Version gibt es diese Skripte nicht mehr. Der systemd-Service nutzt `Restart=on-failure`; die eigentlichen Worker laufen als Goroutines im Daemon. Alte Artefakte werden vom Installer erkannt und müssen vor der Go-Installation entfernt werden, damit nicht zwei Implementierungen parallel dieselbe Firewall und dieselben Dateien verwalten.

File diff suppressed because it is too large Load Diff

View File

@@ -2,33 +2,36 @@
AdGuard Shield kann Ereignisse an Ntfy, Discord, Slack, Gotify oder einen eigenen Webhook senden. Benachrichtigungen sind optional und werden über `adguard-shield.conf` gesteuert.
Typische Ereignisse:
## Unterstützte Ereignisse
- Service gestartet
- Service gestoppt
- automatische Sperre
- manuelle Sperre
- GeoIP-Sperre
- externe Blocklist-Sperre, falls separat aktiviert
- Freigabe
- Bulk-Freigabe, zum Beispiel durch `flush`
| Ereignis | Beschreibung |
|---|---|
| Service gestartet | Daemon wurde gestartet |
| Service gestoppt | Daemon wurde gestoppt |
| Automatische Sperre | Rate-Limit- oder Subdomain-Flood-Erkennung |
| Watchlist-Sperre | DNS-Flood-Watchlist-Treffer (permanent) |
| Manuelle Sperre | IP wurde manuell per `ban` gesperrt |
| GeoIP-Sperre | Ländersperre ausgelöst (wenn `GEOIP_NOTIFY=true`) |
| Blocklist-Sperre | Externe Blocklist (wenn `EXTERNAL_BLOCKLIST_NOTIFY=true`) |
| Freigabe | IP wurde entsperrt (manuell, abgelaufen oder durch Whitelist) |
| Bulk-Freigabe | `flush`, `geoip-flush` oder `blocklist-flush` |
## Grundkonfiguration
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="ntfy"
NOTIFY_TYPE="ntfy" # ntfy, discord, slack, gotify oder generic
```
Mögliche Typen:
### Mögliche Typen
```text
ntfy
discord
slack
gotify
generic
```
| Typ | Protokoll | Beschreibung |
|---|---|---|
| `ntfy` | HTTP POST | Push-Benachrichtigungen über ntfy.sh oder selbst gehostete Instanz |
| `discord` | Webhook | Discord-Kanal-Webhook |
| `slack` | Webhook | Slack Incoming Webhook |
| `gotify` | HTTP POST | Gotify-Server mit App-Token |
| `generic` | HTTP POST (JSON) | Eigener Webhook-Endpunkt |
Nach Änderungen:
@@ -36,12 +39,14 @@ Nach Änderungen:
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.
### Konfiguration
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="ntfy"
@@ -51,7 +56,7 @@ NTFY_TOKEN=""
NTFY_PRIORITY="4"
```
Eigene Ntfy-Instanz:
### Eigene Ntfy-Instanz
```bash
NTFY_SERVER_URL="https://ntfy.example.com"
@@ -59,77 +64,91 @@ NTFY_TOPIC="dns-security"
NTFY_TOKEN="tk_geheimer_token"
```
Prioritäten:
### Prioritäten
| Wert | Bedeutung |
|---:|---|
| `1` | Minimum |
| `2` | Niedrig |
| `3` | Standard |
| `4` | Hoch |
| `5` | Maximum |
| Wert | Bedeutung | Beschreibung |
|---:|---|---|
| `1` | Minimum | Keine Benachrichtigung auf dem Gerät |
| `2` | Niedrig | Leise Benachrichtigung |
| `3` | Standard | Normale Benachrichtigung |
| `4` | Hoch | Benachrichtigung mit Ton |
| `5` | Maximum | Dringende Benachrichtigung |
Hinweise:
### 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.
- Der Topic-Name sollte nicht öffentlich erratbar sein, um Fremdzugriff zu verhindern.
---
## Discord
### Konfiguration
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="discord"
NOTIFY_WEBHOOK_URL="https://discord.com/api/webhooks/xxx/yyy"
```
Webhook erstellen:
### Webhook erstellen
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.
2. Servereinstellungen > Integrationen > Webhooks.
3. Neuen Webhook erstellen.
4. Gewünschten Kanal auswählen.
5. URL kopieren und in `NOTIFY_WEBHOOK_URL` eintragen.
Discord erhält den Inhalt als `content`.
Discord erhält den Inhalt als `content`-Feld im JSON-Body.
---
## Slack
### Konfiguration
```bash
NOTIFY_ENABLED=true
NOTIFY_TYPE="slack"
NOTIFY_WEBHOOK_URL="https://hooks.slack.com/services/xxx/yyy/zzz"
```
Slack erhält den Inhalt als `text`.
### Webhook einrichten
Einrichtung grob:
1. Slack-App mit Incoming Webhooks einrichten.
1. Slack-App mit Incoming Webhooks erstellen oder vorhandene App verwenden.
2. Webhook für den gewünschten Channel aktivieren.
3. Webhook-URL in die Konfiguration kopieren.
Slack erhält den Inhalt als `text`-Feld im JSON-Body.
---
## Gotify
### Konfiguration
```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:
### Token erstellen
1. Gotify-Weboberfläche öffnen.
2. Apps auswählen.
3. App erstellen.
4. Token in die URL einsetzen.
2. Apps > App erstellen.
3. Token aus der App kopieren und in die URL einsetzen.
Gotify erhält `title`, `message` und `priority` als Formularwerte.
---
## Generic Webhook
Für eigene Automatisierung:
Für eigene Automatisierung oder Anbindung an andere Systeme.
### Konfiguration
```bash
NOTIFY_ENABLED=true
@@ -137,7 +156,9 @@ NOTIFY_TYPE="generic"
NOTIFY_WEBHOOK_URL="https://example.com/adguard-shield-webhook"
```
AdGuard Shield sendet einen `POST` mit JSON:
### JSON-Payload
AdGuard Shield sendet einen `POST` mit folgendem JSON-Body:
```json
{
@@ -148,45 +169,36 @@ AdGuard Shield sendet einen `POST` mit JSON:
}
```
Mögliche `action`-Werte:
### Mögliche `action`-Werte
| 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 |
| `ban` | Sperre wurde gesetzt |
| `unban` | Sperre wurde aufgehoben |
| `manual-flush` | Bulk-Freigabe aller Sperren |
| `geoip-flush` | Bulk-Freigabe aller GeoIP-Sperren |
| `external-blocklist-flush` | Bulk-Freigabe aller externen Blocklist-Sperren |
| `service_start` | Service wurde gestartet |
| `service_stop` | Service wurde gestoppt |
## Externe Blocklist und Benachrichtigungen
---
Für Sperren aus externen Blocklisten gibt es einen zusätzlichen Schalter:
## Separate Steuerung für Module
### Externe Blocklist
```bash
EXTERNAL_BLOCKLIST_NOTIFY=false
```
Warum separat?
**Warum separat?** Eine große Blocklist kann beim ersten Sync hunderte oder tausende IPs sperren. Wenn jede Sperre eine Nachricht erzeugt, wird der Benachrichtigungskanal unbrauchbar.
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.
| Listengröße | Empfehlung |
|---|---|
| Große Listen (>100 IPs) | `EXTERNAL_BLOCKLIST_NOTIFY=false` (Standard) |
| Kleine, kuratierte Listen (<50 IPs) | `EXTERNAL_BLOCKLIST_NOTIFY=true` möglich |
Empfehlung:
```bash
EXTERNAL_BLOCKLIST_NOTIFY=false
```
Nur bei kleinen, kuratierten Listen:
```bash
EXTERNAL_BLOCKLIST_NOTIFY=true
```
## GeoIP-Benachrichtigungen
GeoIP hat ebenfalls einen eigenen Schalter:
### GeoIP
```bash
GEOIP_NOTIFY=true
@@ -198,6 +210,8 @@ Wenn GeoIP aktiv ist, aber keine Nachrichten für GeoIP-Sperren gesendet werden
GEOIP_NOTIFY=false
```
---
## Bulk-Freigaben
Diese Befehle können viele IPs auf einmal freigeben:
@@ -208,22 +222,28 @@ 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.
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:
**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.
**Verhalten:**
AbuseIPDB wird nicht für GeoIP- oder externe Blocklist-Sperren verwendet.
- Wenn eine AbuseIPDB-Meldung ausgelöst wurde, enthält die Ban-Nachricht einen entsprechenden Hinweis.
- Jede Ban- und Unban-Nachricht enthält einen Link zur AbuseIPDB-Check-Seite der IP.
- AbuseIPDB wird nicht für GeoIP- oder externe Blocklist-Sperren verwendet.
---
## Beispielinhalte
@@ -299,6 +319,8 @@ Freigegebene IPs: 28
Aktion: Manual-Flush
```
---
## Fehlersuche
Wenn keine Benachrichtigung ankommt:
@@ -308,17 +330,24 @@ sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
sudo journalctl -u adguard-shield --no-pager -n 100
```
Prüfe:
### Checkliste
- `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
| Prüfpunkt | Was zu prüfen ist |
|---|---|
| Aktiviert | `NOTIFY_ENABLED=true` gesetzt? |
| Typ | `NOTIFY_TYPE` korrekt geschrieben? |
| Ziel | Webhook-URL oder Ntfy-Topic gesetzt? |
| Token | Token gültig und nicht abgelaufen? |
| Netzwerk | Server kann ausgehende HTTPS-Verbindungen aufbauen? |
| Firewall | Keine Firewall blockiert ausgehende Verbindungen? |
| Modul-Schalter | `EXTERNAL_BLOCKLIST_NOTIFY` oder `GEOIP_NOTIFY` separat deaktiviert? |
Bei `generic` kannst du testweise einen lokalen HTTP-Empfänger oder einen Request-Inspector verwenden.
Bei `generic` kannst du testweise einen lokalen HTTP-Empfänger oder einen Request-Inspector verwenden, um den gesendeten Payload zu sehen.
---
## 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.
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 eine eigene Ntfy- oder Gotify-Instanz mit privatem Topic oft die bessere Wahl als ein öffentlicher Kanal.

View File

@@ -1,52 +1,160 @@
# 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.
AdGuard Shield läuft auf dem Host und liest weiterhin das Querylog von AdGuard Home über die API. Der Unterschied zwischen klassischer Installation und Docker-Setup 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"` |
Die Wahl des Firewall-Modus hängt davon ab, wie AdGuard Home betrieben wird:
`docker-host` verhält sich technisch wie `host`: Die DNS-Pakete landen in der Host-`INPUT`-Chain.
| Installation | Einstellung | Parent-Chain |
|---|---|---|
| AdGuard Home direkt auf dem Host | `FIREWALL_MODE="host"` | `INPUT` |
| Docker mit `network_mode: host` | `FIREWALL_MODE="docker-host"` | `INPUT` |
| Docker Bridge mit veröffentlichten Ports | `FIREWALL_MODE="docker-bridge"` | `DOCKER-USER` |
| Gemischtes Setup oder Migration | `FIREWALL_MODE="hybrid"` | `INPUT` + `DOCKER-USER` |
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.
### Warum verschiedene Modi?
## Beispiele
**Host und Docker Host Network:** DNS-Pakete landen direkt in der `INPUT`-Chain des Hosts. Die Firewall-Regeln werden dort eingehängt.
Klassisch oder Docker Host Network:
**Docker Bridge mit Port-Publishing:** Docker veröffentlicht Ports über NAT (DNAT). Die Pakete durchlaufen nach dem DNAT die `FORWARD`-Chain, nicht die `INPUT`-Chain. Docker stellt dafür die Chain `DOCKER-USER` bereit, die genau für eigene Admin-Regeln vor Dockers Container-Regeln vorgesehen ist.
**Hybrid:** Hängt Regeln in beide Chains ein. Nützlich bei Migrationen oder wenn unklar ist, welcher Weg die Pakete nehmen.
---
## Konfigurationsbeispiele
### Klassisch oder Docker Host Network
```bash
FIREWALL_MODE="host"
BLOCKED_PORTS="53 443 853"
```
Docker Bridge mit Port-Publishing:
`docker-host` verhält sich technisch identisch zu `host`:
```bash
FIREWALL_MODE="docker-host"
BLOCKED_PORTS="53 443 853"
```
### Docker Bridge mit Port-Publishing
```bash
FIREWALL_MODE="docker-bridge"
BLOCKED_PORTS="53 443 853"
```
Unklarer Übergangszustand:
### Unklarer Übergangszustand
```bash
FIREWALL_MODE="hybrid"
BLOCKED_PORTS="53 443 853"
```
---
## Regelstruktur nach Modus
### Host / Docker Host Network
```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
```
### Docker Bridge
```text
DOCKER-USER
├── 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
```
### Hybrid
Beide Strukturen gleichzeitig: `INPUT` und `DOCKER-USER` springen in `ADGUARD_SHIELD`.
---
## 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.
| Thema | Beschreibung |
|---|---|
| **DOCKER-USER Chain** | `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 in Docker** | IPv6 über Docker wird nur eingehängt, wenn Docker auch eine `ip6tables`-Chain `DOCKER-USER` angelegt hat. Fehlt sie, wird IPv4 trotzdem geschützt. |
| **Port-Mapping** | In `DOCKER-USER` wird nach Dockers DNAT gematcht. Bei ungewöhnlichen Port-Mappings sollten `BLOCKED_PORTS` die Container-Zielports enthalten (nicht die Host-Ports). |
| **Hybrid-Warnung** | `hybrid` kann mehr Verkehr treffen, weil sowohl Host-Ports als auch Docker-Forwarding geprüft werden. Nur bei Migrationen oder unklaren Setups verwenden. |
| **API-URL** | Die `ADGUARD_URL` muss vom Host aus erreichbar sein. Bei Docker Bridge ist das oft `http://127.0.0.1:<host-port>`. |
Nach einer Änderung:
---
## Typisches Docker-Bridge-Setup
### docker-compose.yml (AdGuard Home)
```yaml
services:
adguardhome:
image: adguard/adguardhome
ports:
- "53:53/tcp"
- "53:53/udp"
- "443:443/tcp"
- "853:853/tcp"
- "3000:3000/tcp"
volumes:
- ./data:/opt/adguardhome/work
- ./conf:/opt/adguardhome/conf
restart: unless-stopped
```
### adguard-shield.conf
```bash
ADGUARD_URL="http://127.0.0.1:3000"
ADGUARD_USER="admin"
ADGUARD_PASS="geheim"
FIREWALL_MODE="docker-bridge"
BLOCKED_PORTS="53 443 853"
```
---
## Nach einer Änderung prüfen
```bash
sudo systemctl restart adguard-shield
sudo /opt/adguard-shield/adguard-shield firewall-status
sudo /opt/adguard-shield/adguard-shield status
```
## Firewall neu aufbauen
Falls der Modus gewechselt wurde:
```bash
sudo /opt/adguard-shield/adguard-shield firewall-remove
sudo systemctl restart adguard-shield
sudo /opt/adguard-shield/adguard-shield firewall-status
```
Der Daemon erstellt die Firewall-Struktur beim Start automatisch neu und überträgt aktive Sperren aus SQLite.

View File

@@ -16,7 +16,7 @@ RATE_LIMIT_MAX_REQUESTS=30
WHITELIST="127.0.0.1,::1,192.168.1.1"
```
Nach Änderungen solltest du den Service neu starten:
Nach Änderungen muss der Service neu gestartet werden:
```bash
sudo systemctl restart adguard-shield
@@ -41,21 +41,24 @@ Das ist besonders wichtig beim Umstieg von der Shell-Version auf die Go-Version.
Nach dem Bearbeiten der Konfiguration:
```bash
# API-Verbindung testen
sudo /opt/adguard-shield/adguard-shield test
# Dry-Run: zeigt, was gesperrt würde, ohne die Firewall zu verändern
sudo /opt/adguard-shield/adguard-shield dry-run
```
`test` prüft die AdGuard-Home-API. `dry-run` zeigt, was AdGuard Shield sperren würde, ohne die Firewall zu verändern.
---
## AdGuard Home API
| Parameter | Standard | Beschreibung |
|---|---|---|
| `ADGUARD_URL` | `https://dns1.domain.com` | URL der AdGuard-Home-Weboberfläche/API |
| `ADGUARD_USER` | `admin` | Benutzername für die API |
| `ADGUARD_PASS` | `changeme` | Passwort für die API |
| `ADGUARD_USER` | `admin` | Benutzername für die API-Authentifizierung |
| `ADGUARD_PASS` | `changeme` | Passwort für die API-Authentifizierung |
Beispiel lokal:
### Beispiel: Lokale Instanz
```bash
ADGUARD_URL="http://127.0.0.1:3000"
@@ -63,10 +66,12 @@ ADGUARD_USER="admin"
ADGUARD_PASS="sehr-geheim"
```
Beispiel mit HTTPS:
### Beispiel: Entfernte Instanz mit HTTPS
```bash
ADGUARD_URL="https://dns.example.com"
ADGUARD_USER="admin"
ADGUARD_PASS="geheim"
```
AdGuard Shield ruft intern diesen Endpunkt ab:
@@ -75,54 +80,55 @@ AdGuard Shield ruft intern diesen Endpunkt ab:
/control/querylog?limit=<API_QUERY_LIMIT>&response_status=all
```
Hinweis: Der HTTP-Client akzeptiert auch selbstsignierte TLS-Zertifikate. Das erleichtert lokale Setups, ersetzt aber keine saubere Absicherung der AdGuard-Home-Oberfläche.
**Hinweis:** Der HTTP-Client akzeptiert auch selbstsignierte TLS-Zertifikate. Das erleichtert lokale Setups, ersetzt aber keine saubere Absicherung der AdGuard-Home-Oberfläche.
---
## Querylog und Polling
| Parameter | Standard | Beschreibung |
|---|---:|---|
| `CHECK_INTERVAL` | `10` | Abstand zwischen Querylog-Abfragen in Sekunden |
| `API_QUERY_LIMIT` | `500` | Anzahl der Querylog-Einträge pro API-Abfrage |
| `API_QUERY_LIMIT` | `500` | Anzahl der Querylog-Einträge pro API-Abfrage (max. 5000) |
Empfehlung:
### Empfehlungen
- `CHECK_INTERVAL=10` ist ein guter Standard.
- Bei sehr hohem DNS-Aufkommen kann `API_QUERY_LIMIT` erhöht werden.
- Wenn `API_QUERY_LIMIT` zu niedrig ist, können Spitzen im Querylog zwischen zwei Polls teilweise verpasst werden.
- Sehr kurze Intervalle erzeugen mehr API-Last auf AdGuard Home.
| Situation | Empfehlung |
|---|---|
| Normaler Betrieb | `CHECK_INTERVAL=10` ist ein guter Standard |
| Hohes DNS-Aufkommen | `API_QUERY_LIMIT` auf 10002000 erhöhen |
| `API_QUERY_LIMIT` zu niedrig | Spitzen im Querylog können zwischen zwei Polls verpasst werden |
| Sehr kurze Intervalle | Erzeugen mehr API-Last auf AdGuard Home |
---
## Rate-Limit
| Parameter | Standard | Beschreibung |
|---|---:|---|
| `RATE_LIMIT_MAX_REQUESTS` | `30` | maximale Anfragen pro Client und Domain im Zeitfenster |
| `RATE_LIMIT_MAX_REQUESTS` | `30` | Maximale Anfragen pro Client und Domain im Zeitfenster |
| `RATE_LIMIT_WINDOW` | `60` | Zeitfenster in Sekunden |
Beispiel:
Das bedeutet: Wenn ein Client dieselbe Domain mehr als 30-mal innerhalb von 60 Sekunden abfragt, wird er als auffällig erkannt und gesperrt.
```bash
RATE_LIMIT_MAX_REQUESTS=30
RATE_LIMIT_WINDOW=60
```
### Empfohlene Startwerte
Das bedeutet: Wenn ein Client dieselbe Domain mehr als 30-mal innerhalb von 60 Sekunden abfragt, wird er auffällig.
| Umgebung | `MAX_REQUESTS` | `WINDOW` | Hinweis |
|---|---:|---:|---|
| Kleines Heimnetz | `30` | `60` | Standardwerte |
| Viele Clients | `60``120` | `60` | Höherer Grenzwert für mehr Grundlast |
| Aktive Resolver/Forwarder | nach Bedarf | `60` | Zuerst Forwarder whitelisten |
Gute Startwerte:
**Wichtig:** Wenn ein Router, Reverse Proxy oder lokaler DNS-Forwarder stellvertretend für viele Clients fragt, sollte dieser Client in die Whitelist. Sonst sieht AdGuard Shield nur eine sehr aktive IP und sperrt den Forwarder statt der eigentlichen Verursacher.
| Umgebung | Vorschlag |
|---|---|
| kleines Heimnetz | `30` in `60s` |
| viele Clients | `60` bis `120` in `60s` |
| sehr aktive Resolver/Forwarder | zuerst Whitelist prüfen, dann höher setzen |
Wichtig: Wenn ein Router, Reverse Proxy oder lokaler DNS-Forwarder stellvertretend für viele Clients fragt, sollte dieser Client in die Whitelist. Sonst sieht AdGuard Shield nur eine sehr aktive IP.
---
## Subdomain-Flood-Erkennung
| Parameter | Standard | Beschreibung |
|---|---:|---|
| `SUBDOMAIN_FLOOD_ENABLED` | `true` | aktiviert die Erkennung zufälliger Subdomains |
| `SUBDOMAIN_FLOOD_MAX_UNIQUE` | `50` | maximale Anzahl eindeutiger Subdomains pro Client und Basisdomain |
| `SUBDOMAIN_FLOOD_ENABLED` | `true` | Erkennung zufälliger Subdomains aktivieren |
| `SUBDOMAIN_FLOOD_MAX_UNIQUE` | `50` | Maximale eindeutige Subdomains pro Client und Basisdomain |
| `SUBDOMAIN_FLOOD_WINDOW` | `60` | Zeitfenster in Sekunden |
Diese Erkennung zielt auf Muster wie:
@@ -133,148 +139,154 @@ f8x9.example.com
zz12.example.com
```
Dabei zählt AdGuard Shield nicht die Gesamtzahl der Anfragen, sondern die Anzahl unterschiedlicher Subdomains unter derselben Basisdomain.
Dabei zählt AdGuard Shield nicht die Gesamtzahl der Anfragen, sondern die Anzahl **unterschiedlicher** Subdomains unter derselben Basisdomain. Direkte Anfragen an `example.com` selbst zählen nicht.
Beispiel:
### Hinweise
```bash
SUBDOMAIN_FLOOD_ENABLED=true
SUBDOMAIN_FLOOD_MAX_UNIQUE=50
SUBDOMAIN_FLOOD_WINDOW=60
```
- Multi-Part-TLDs wie `.co.uk` werden korrekt als Basisdomain erkannt.
- CDNs und manche Apps nutzen legitim viele Subdomains. Betroffene Clients whitelisten oder Grenzwert erhöhen.
Wenn ein Client innerhalb von 60 Sekunden mehr als 50 unterschiedliche Subdomains von `example.com` abfragt, wird er gesperrt.
Hinweise:
- Direkte Anfragen an `example.com` zählen hier nicht.
- Multi-Part-TLDs wie `.co.uk` werden berücksichtigt.
- CDNs und manche Apps nutzen viele Subdomains. Wenn legitime Clients betroffen sind, den Grenzwert erhöhen oder passende Clients whitelisten.
---
## DNS-Flood-Watchlist
| Parameter | Standard | Beschreibung |
|---|---|---|
| `DNS_FLOOD_WATCHLIST_ENABLED` | `false` | aktiviert die Watchlist |
| `DNS_FLOOD_WATCHLIST` | leer | kommagetrennte Domainliste |
| `DNS_FLOOD_WATCHLIST_ENABLED` | `false` | Watchlist aktivieren |
| `DNS_FLOOD_WATCHLIST` | leer | Kommagetrennte Domainliste |
Die Watchlist ist für Domains gedacht, bei denen eine Überschreitung sofort hart behandelt werden soll.
Die Watchlist ist für Domains gedacht, bei denen eine Überschreitung sofort hart behandelt werden soll, ohne progressive Stufen.
Beispiel:
### Beispiel
```bash
DNS_FLOOD_WATCHLIST_ENABLED=true
DNS_FLOOD_WATCHLIST="microsoft.com,google.com,apple.com"
```
Wenn ein Client dann `login.microsoft.com` über das Rate-Limit bringt, wird sofort permanent gesperrt, weil `login.microsoft.com` zur Watchlist-Domain `microsoft.com` gehört.
### Matching-Logik
Folgen:
Wenn ein Client `login.microsoft.com` über das Rate-Limit bringt, wird sofort permanent gesperrt, weil `login.microsoft.com` zur Watchlist-Domain `microsoft.com` gehört. `evil-microsoft.com` würde dagegen **nicht** matchen.
- Grund: `dns-flood-watchlist`
- Sperrdauer: permanent
- Progressive-Ban-Dauer wird übersprungen
- AbuseIPDB-Reporting kann ausgelöst werden, wenn aktiviert
### Folgen eines Watchlist-Treffers
| Aspekt | Verhalten |
|---|---|
| Grund | `dns-flood-watchlist` |
| Sperrdauer | Permanent |
| Progressive Sperren | Werden übersprungen |
| AbuseIPDB | Wird gemeldet, falls aktiviert |
---
## Sperrdauer und Firewall
| Parameter | Standard | Beschreibung |
|---|---|---|
| `BAN_DURATION` | `3600` | Basisdauer temporärer Monitor-Sperren in Sekunden |
| `BAN_DURATION` | `3600` | Basisdauer temporärer Monitor-Sperren in Sekunden (1 Stunde) |
| `IPTABLES_CHAIN` | `ADGUARD_SHIELD` | Name der eigenen Firewall-Chain |
| `BLOCKED_PORTS` | `53 443 853` | Ports, die für gesperrte Clients blockiert werden |
| `FIREWALL_BACKEND` | `ipset` | Firewall-Backend der Go-Version |
| `BLOCKED_PORTS` | `53 443 853` | Ports, die für gesperrte Clients blockiert werden (Leerzeichen-getrennt) |
| `FIREWALL_BACKEND` | `ipset` | Firewall-Backend (ipset + iptables) |
| `FIREWALL_MODE` | `host` | Verkehrsweg der AdGuard-Home-Installation |
| `DRY_RUN` | `false` | Konfigurationsweiter Testmodus ohne echte Sperren |
Standardports:
### Blockierte Ports
| Port | Zweck |
|---:|---|
| `53` | klassisches DNS über UDP/TCP |
| `443` | DNS-over-HTTPS, sofern AdGuard Home darüber erreichbar ist |
| `853` | DNS-over-TLS und DNS-over-QUIC |
| `53` | Klassisches DNS über UDP/TCP |
| `443` | DNS-over-HTTPS (DoH), sofern AdGuard Home darüber erreichbar ist |
| `853` | DNS-over-TLS (DoT) und DNS-over-QUIC (DoQ) |
Die Firewall wird über `ipset` und `iptables`/`ip6tables` gesteuert. Für IPv4 und IPv6 gibt es getrennte Sets:
### Firewall-Modi
```text
adguard_shield_v4
adguard_shield_v6
```
| Modus | Einsatz | Parent-Chain |
|---|---|---|
| `host` | Klassische AdGuard-Home-Installation direkt auf dem Host | `INPUT` |
| `docker-host` | Docker mit `network_mode: host` (Alias von `host`) | `INPUT` |
| `docker-bridge` | Docker mit veröffentlichten Ports, z.B. `-p 53:53` | `DOCKER-USER` |
| `hybrid` | Schützt Host-Ports und Docker-Forwarding gleichzeitig | `INPUT` + `DOCKER-USER` |
`FIREWALL_MODE` legt fest, in welche Host-Chain AdGuard Shield die Schutzregeln einhängt:
Details zu den Docker-Modi stehen in [Docker-Installationen](docker.md).
| Modus | Einsatz |
|---|---|
| `host` | klassische AdGuard-Home-Installation direkt auf dem Host |
| `docker-host` | AdGuard Home läuft in Docker mit `network_mode: host`; Alias von `host` |
| `docker-bridge` | AdGuard Home läuft in Docker mit veröffentlichten Ports, z.B. `53:53` |
| `hybrid` | schützt Host-Ports und Docker-Forwarding gleichzeitig |
Bei `host`/`docker-host` wird die eigene Chain aus `INPUT` angesprungen. Bei `docker-bridge` wird sie aus `DOCKER-USER` angesprungen, weil Docker veröffentlichte Ports über NAT und `FORWARD` verarbeitet. Details stehen in [Docker-Installationen](docker.md).
---
## Whitelist
| Parameter | Standard | Beschreibung |
|---|---|---|
| `WHITELIST` | `127.0.0.1,::1` | IPs, die nie gesperrt werden |
| `WHITELIST` | `127.0.0.1,::1` | IPs, die nie gesperrt werden (kommagetrennt) |
Beispiel:
### Beispiel
```bash
WHITELIST="127.0.0.1,::1,192.168.1.1,192.168.1.10,fd00::1"
```
Empfohlen sind:
### Empfohlene Whitelist-Einträge
- Localhost: `127.0.0.1`, `::1`
- Router/Gateway
- Admin- oder Management-IPs
- Monitoring-Systeme
- interne Resolver oder Forwarder
- eigene VPN-Endpunkte, falls sie viele Anfragen bündeln
| Typ | Beispiel | Grund |
|---|---|---|
| Localhost | `127.0.0.1`, `::1` | Lokale Anfragen |
| Router/Gateway | `192.168.1.1` | Bündelt oft DNS für alle Clients |
| Admin-IPs | `192.168.1.10` | Eigene Management-Geräte |
| Monitoring | Monitoring-IP | Regelmäßige DNS-Checks |
| Interne Resolver | Resolver-IP | Fragt stellvertretend für viele Clients |
| VPN-Endpunkte | VPN-IP | Bündeln DNS-Anfragen vieler Nutzer |
Wichtig: Die Whitelist wird vor jeder Sperre geprüft. Das gilt für automatische, manuelle, GeoIP- und externe Blocklist-Sperren.
**Wichtig:** Die Whitelist wird vor jeder Sperre geprüft. Das gilt für automatische, manuelle, GeoIP- und externe Blocklist-Sperren.
---
## Progressive Sperren
| Parameter | Standard | Beschreibung |
|---|---:|---|
| `PROGRESSIVE_BAN_ENABLED` | `true` | Wiederholungstäter stufenweise länger sperren |
| `PROGRESSIVE_BAN_MULTIPLIER` | `2` | Multiplikator pro Stufe |
| `PROGRESSIVE_BAN_MAX_LEVEL` | `5` | ab dieser Stufe permanent sperren, `0` bedeutet nie permanent durch Stufe |
| `PROGRESSIVE_BAN_MULTIPLIER` | `2` | Multiplikator pro Stufe (2 = Verdopplung) |
| `PROGRESSIVE_BAN_MAX_LEVEL` | `5` | Ab dieser Stufe permanent sperren (`0` = nie permanent durch Stufe) |
| `PROGRESSIVE_BAN_RESET_AFTER` | `86400` | Offense-Zähler nach so vielen Sekunden ohne neues Vergehen zurücksetzen |
Beispiel mit Standardwerten:
### Stufenverlauf mit Standardwerten
| Vergehen | Stufe | Dauer |
|---:|---:|---|
| 1 | 1 | 1 Stunde |
| 2 | 2 | 2 Stunden |
| 3 | 3 | 4 Stunden |
| 4 | 4 | 8 Stunden |
| 5 | 5 | permanent |
| Vergehen | Stufe | Berechnung | Sperrdauer |
|---:|---:|---|---|
| 1 | 1 | 3600 × 2⁰ | 1 Stunde |
| 2 | 2 | 3600 × 2¹ | 2 Stunden |
| 3 | 3 | 3600 × 2² | 4 Stunden |
| 4 | 4 | 3600 × 2³ | 8 Stunden |
| 5 | 5 | Max-Level erreicht | Permanent |
Progressive Sperren gelten für Monitor-Sperren wie `rate-limit` und `subdomain-flood`. Watchlist-Treffer sind sofort permanent. GeoIP und externe Blocklisten haben eigene Regeln.
Wartung:
### Verwaltungsbefehle
```bash
sudo /opt/adguard-shield/adguard-shield offense-status
sudo /opt/adguard-shield/adguard-shield offense-cleanup
sudo /opt/adguard-shield/adguard-shield reset-offenses 192.168.1.100
sudo /opt/adguard-shield/adguard-shield offense-status # Zähler anzeigen
sudo /opt/adguard-shield/adguard-shield offense-cleanup # Abgelaufene entfernen
sudo /opt/adguard-shield/adguard-shield reset-offenses # Alle zurücksetzen
sudo /opt/adguard-shield/adguard-shield reset-offenses <IP> # Eine IP zurücksetzen
```
---
## Logging
| Parameter | Standard | Beschreibung |
|---|---|---|
| `LOG_FILE` | `/var/log/adguard-shield.log` | Datei für Daemon-Ereignisse |
| `LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARN` oder `ERROR` |
| `LOG_LEVEL` | `INFO` | Minimales Log-Level |
`LOG_FILE` enthält Start/Stop, Worker-Läufe, Sperren, Freigaben, Warnungen und Fehler. Query-Inhalte werden nicht dauerhaft ins Log geschrieben.
### Verfügbare Log-Level
CLI:
| Level | Beschreibung | Empfehlung |
|---|---|---|
| `DEBUG` | Detaillierte Informationen, z.B. einzelne API-Ergebnisse | Nur kurzzeitig für Fehlersuche |
| `INFO` | Normale Betriebsmeldungen (Start, Sperren, Freigaben) | Empfohlen für den produktiven Betrieb |
| `WARN` | Warnungen (API-Fehler, fehlende Dateien, Konfigurationsprobleme) | |
| `ERROR` | Fehler, die den Betrieb beeinträchtigen | |
### CLI-Befehle
```bash
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
@@ -282,7 +294,9 @@ sudo /opt/adguard-shield/adguard-shield logs-follow debug
sudo /opt/adguard-shield/adguard-shield live
```
Für produktiven Betrieb ist `INFO` sinnvoll. Für Fehlersuche kurzzeitig `DEBUG` verwenden.
**Hinweis:** Query-Inhalte werden nicht dauerhaft ins Log geschrieben. Für Query-nahe Diagnose ist die Live-Ansicht gedacht.
---
## State und Runtime
@@ -291,31 +305,49 @@ Für produktiven Betrieb ist `INFO` sinnvoll. Für Fehlersuche kurzzeitig `DEBUG
| `STATE_DIR` | `/var/lib/adguard-shield` | Verzeichnis für SQLite-Datenbank und Caches |
| `PID_FILE` | `/var/run/adguard-shield.pid` | PID-Datei für direkten Vordergrundlauf |
SQLite-Datei:
### SQLite-Datei
```text
${STATE_DIR}/adguard-shield.db
```
Weitere Dateien in `STATE_DIR`:
### Weitere Dateien in STATE_DIR
- Caches für externe Listen
- gespeicherte Firewall-Regeln bei `firewall-save`
- SQLite-WAL-Dateien
| Datei/Verzeichnis | Inhalt |
|---|---|
| `adguard-shield.db` | Hauptdatenbank (Sperren, History, Offenses, Caches) |
| `adguard-shield.db-wal` | WAL-Datei (im laufenden Betrieb) |
| `adguard-shield.db-shm` | Shared-Memory-Datei (im laufenden Betrieb) |
| `external-blocklist/` | Cache für heruntergeladene Blocklisten |
| `external-whitelist/` | Cache für heruntergeladene Whitelists |
| `iptables-rules.v4` | Gesicherte IPv4-Firewall-Regeln |
| `iptables-rules.v6` | Gesicherte IPv6-Firewall-Regeln |
---
## Benachrichtigungen
| Parameter | Standard | Beschreibung |
|---|---|---|
| `NOTIFY_ENABLED` | `false` | Benachrichtigungen aktivieren |
| `NOTIFY_TYPE` | `ntfy` | `ntfy`, `discord`, `slack`, `gotify` oder `generic` |
| `NOTIFY_WEBHOOK_URL` | leer | Webhook-URL für Discord, Slack, Gotify oder Generic |
| `NOTIFY_TYPE` | `ntfy` | Benachrichtigungskanal |
| `NOTIFY_WEBHOOK_URL` | leer | Webhook-URL (nicht für ntfy) |
| `NTFY_SERVER_URL` | `https://ntfy.sh` | Ntfy-Server |
| `NTFY_TOPIC` | leer | Ntfy-Topic |
| `NTFY_TOKEN` | leer | optionaler Access-Token |
| `NTFY_PRIORITY` | `4` | Ntfy-Priorität von 1 bis 5 |
| `NTFY_TOKEN` | leer | Optionaler Ntfy-Access-Token |
| `NTFY_PRIORITY` | `4` | Ntfy-Priorität (15) |
Ntfy-Beispiel:
### Verfügbare Typen
| Typ | Beschreibung |
|---|---|
| `ntfy` | Ntfy Push-Benachrichtigungen (öffentlich oder selbst gehostet) |
| `discord` | Discord-Webhook |
| `slack` | Slack-Webhook |
| `gotify` | Gotify-Server |
| `generic` | Eigener Webhook-Endpunkt (JSON POST) |
### Beispiel: Ntfy
```bash
NOTIFY_ENABLED=true
@@ -325,7 +357,7 @@ NTFY_TOPIC="mein-adguard-shield"
NTFY_PRIORITY="4"
```
Discord-Beispiel:
### Beispiel: Discord
```bash
NOTIFY_ENABLED=true
@@ -333,22 +365,40 @@ NOTIFY_TYPE="discord"
NOTIFY_WEBHOOK_URL="https://discord.com/api/webhooks/..."
```
Details stehen in [Benachrichtigungen](benachrichtigungen.md).
Details zu allen Kanälen stehen in [Benachrichtigungen](benachrichtigungen.md).
---
## E-Mail-Reports
| Parameter | Standard | Beschreibung |
|---|---|---|
| `REPORT_ENABLED` | `false` | Report-Funktion logisch aktivieren |
| `REPORT_INTERVAL` | `weekly` | `daily`, `weekly`, `biweekly` oder `monthly` |
| `REPORT_INTERVAL` | `weekly` | Versandintervall |
| `REPORT_TIME` | `08:00` | Versandzeit im Format `HH:MM` |
| `REPORT_EMAIL_TO` | `admin@example.com` | Empfänger |
| `REPORT_EMAIL_FROM` | `adguard-shield@example.com` | Absender |
| `REPORT_FORMAT` | `html` | `html` oder `txt` |
| `REPORT_MAIL_CMD` | `msmtp` | Mailprogramm |
| `REPORT_BUSIEST_DAY_RANGE` | `30` | Zeitraum in Tagen für "Aktivster Tag"; aktuell als Kompatibilitätsparameter vorhanden |
| `REPORT_EMAIL_TO` | `admin@example.com` | Empfängeradresse |
| `REPORT_EMAIL_FROM` | `adguard-shield@example.com` | Absenderadresse |
| `REPORT_FORMAT` | `html` | Report-Format |
| `REPORT_MAIL_CMD` | `msmtp` | Mailprogramm für den Versand |
| `REPORT_BUSIEST_DAY_RANGE` | `30` | Zeitraum für "Aktivster Tag" (Kompatibilitätsparameter) |
Beispiel:
### Verfügbare Intervalle
| Intervall | Versand |
|---|---|
| `daily` | Täglich zur konfigurierten Uhrzeit |
| `weekly` | Montags zur konfigurierten Uhrzeit |
| `biweekly` | Am 1. und 15. des Monats |
| `monthly` | Am 1. des Monats |
### Verfügbare Formate
| Format | Beschreibung |
|---|---|
| `html` | HTML-formatierte E-Mail (empfohlen für Standard-Mail-Clients) |
| `txt` | Reiner Text (robuster für einfache Mail-Setups) |
### Beispiel
```bash
REPORT_ENABLED=true
@@ -360,7 +410,7 @@ REPORT_FORMAT="html"
REPORT_MAIL_CMD="msmtp"
```
Cron installieren:
### Cron-Job installieren
```bash
sudo /opt/adguard-shield/adguard-shield report-install
@@ -368,16 +418,18 @@ sudo /opt/adguard-shield/adguard-shield report-install
Details stehen in [E-Mail Report](report.md).
---
## Externe Whitelist
| Parameter | Standard | Beschreibung |
|---|---|---|
| `EXTERNAL_WHITELIST_ENABLED` | `false` | externe Whitelist aktivieren |
| `EXTERNAL_WHITELIST_URLS` | leer | kommagetrennte URLs |
| `EXTERNAL_WHITELIST_ENABLED` | `false` | Externe Whitelist aktivieren |
| `EXTERNAL_WHITELIST_URLS` | leer | Kommagetrennte URLs zu den Whitelist-Dateien |
| `EXTERNAL_WHITELIST_INTERVAL` | `300` | Synchronisationsintervall in Sekunden |
| `EXTERNAL_WHITELIST_CACHE_DIR` | `/var/lib/adguard-shield/external-whitelist` | Cache-Verzeichnis |
Beispiel:
### Beispiel
```bash
EXTERNAL_WHITELIST_ENABLED=true
@@ -385,51 +437,47 @@ EXTERNAL_WHITELIST_URLS="https://example.com/trusted.txt"
EXTERNAL_WHITELIST_INTERVAL=300
```
Listenformat:
### Listenformat
```text
# Hostnamen werden regelmäßig aufgelöst
# Hostnamen werden regelmäßig per DNS aufgelöst
mein-router.dyndns.org
vpn.example.com
# IPs und Netze
# IPs und Netze direkt
192.168.1.10
10.0.0.0/24
2001:db8::1
```
Mehrere Listen:
### Mehrere Listen
```bash
EXTERNAL_WHITELIST_URLS="https://example.com/a.txt,https://example.net/b.txt"
```
Verhalten:
### Verhalten
- Hostnamen werden per DNS aufgelöst.
- Aufgelöste IPs landen in SQLite.
- Bereits aktive Sperren werden aufgehoben, wenn die IP später in der Whitelist auftaucht.
- Kommentare und Inline-Kommentare werden unterstützt.
- Hostnamen werden per DNS aufgelöst und als IPs in SQLite gespeichert.
- Aufgelöste IPs werden bei jedem Sync aktualisiert.
- Bereits aktive Sperren werden aufgehoben, wenn die IP in der Whitelist auftaucht.
- Kommentare (`#`) und Inline-Kommentare werden unterstützt.
Manuell synchronisieren:
```bash
sudo /opt/adguard-shield/adguard-shield whitelist-sync
```
---
## Externe Blocklist
| Parameter | Standard | Beschreibung |
|---|---|---|
| `EXTERNAL_BLOCKLIST_ENABLED` | `false` | externe Blocklist aktivieren |
| `EXTERNAL_BLOCKLIST_URLS` | leer | kommagetrennte URLs |
| `EXTERNAL_BLOCKLIST_ENABLED` | `false` | Externe Blocklist aktivieren |
| `EXTERNAL_BLOCKLIST_URLS` | leer | Kommagetrennte URLs |
| `EXTERNAL_BLOCKLIST_INTERVAL` | `300` | Synchronisationsintervall in Sekunden |
| `EXTERNAL_BLOCKLIST_BAN_DURATION` | `0` | Sperrdauer in Sekunden, `0` = permanent |
| `EXTERNAL_BLOCKLIST_BAN_DURATION` | `0` | Sperrdauer in Sekunden (`0` = permanent bis IP aus Liste entfernt) |
| `EXTERNAL_BLOCKLIST_AUTO_UNBAN` | `true` | IPs freigeben, wenn sie nicht mehr in der Liste stehen |
| `EXTERNAL_BLOCKLIST_NOTIFY` | `false` | Benachrichtigungen für Blocklist-Sperren senden |
| `EXTERNAL_BLOCKLIST_CACHE_DIR` | `/var/lib/adguard-shield/external-blocklist` | Cache-Verzeichnis |
Beispiel:
### Beispiel
```bash
EXTERNAL_BLOCKLIST_ENABLED=true
@@ -440,26 +488,7 @@ EXTERNAL_BLOCKLIST_AUTO_UNBAN=true
EXTERNAL_BLOCKLIST_NOTIFY=false
```
Listenformat:
```text
# IPv4
203.0.113.50
198.51.100.0/24
# IPv6
2001:db8::dead:beef
2001:db8::/32
# Hostnamen
bad-actor.example.com
# Hosts-Datei-Format wird erkannt
0.0.0.0 malware.example.net
127.0.0.1 tracker.example.org
```
Unterstützt:
### Unterstützte Listenformate
| Format | Beispiel |
|---|---|
@@ -472,42 +501,38 @@ Unterstützt:
| Kommentar | `# Text` |
| Inline-Kommentar | `203.0.113.50 # Grund` |
Nicht sinnvoll und wird übersprungen:
### Ignorierte Einträge
- URLs wie `https://...`
- IP:Port wie `203.0.113.50:8443`
- Hostnamen ohne Punkt oder mit ungültigen Zeichen
- nicht auflösbare Hostnamen
- Nicht auflösbare Hostnamen
- Blocking-Antworten wie `0.0.0.0` oder `::`
Hinweise:
### Hinweise
- Große Listen können viele Sperren erzeugen. `EXTERNAL_BLOCKLIST_NOTIFY=false` ist deshalb der sichere Standard.
- Wenn ein Hostname mehrere IPs liefert, werden alle aufgelösten IPs verarbeitet.
- Hostnamen mit mehreren IPs: Alle aufgelösten IPs werden verarbeitet.
- IPs aus der Whitelist werden nicht gesperrt.
- Bei `EXTERNAL_BLOCKLIST_AUTO_UNBAN=true` werden entfernte Einträge wieder freigegeben.
- Bei `EXTERNAL_BLOCKLIST_AUTO_UNBAN=true` werden entfernte Einträge automatisch wieder freigegeben.
Manuell synchronisieren:
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-sync
```
Dateiformat-Empfehlungen:
### Dateiformat-Empfehlungen
- UTF-8 ohne BOM
- Unix-Zeilenenden `LF`
- Unix-Zeilenenden (`LF`)
- IP-Listen und Hostname-Listen möglichst getrennt pflegen
---
## AbuseIPDB
| Parameter | Standard | Beschreibung |
|---|---|---|
| `ABUSEIPDB_ENABLED` | `false` | AbuseIPDB-Reporting aktivieren |
| `ABUSEIPDB_API_KEY` | leer | API-Key |
| `ABUSEIPDB_CATEGORIES` | `4` | Kategorien, kommagetrennt möglich |
| `ABUSEIPDB_API_KEY` | leer | API-Key von abuseipdb.com |
| `ABUSEIPDB_CATEGORIES` | `4` | Kategorien, kommagetrennt (siehe [abuseipdb.com/categories](https://www.abuseipdb.com/categories)) |
Beispiel:
### Beispiel
```bash
ABUSEIPDB_ENABLED=true
@@ -515,33 +540,55 @@ ABUSEIPDB_API_KEY="dein-api-key"
ABUSEIPDB_CATEGORIES="4"
```
Gemeldet werden nur permanente Monitor-Sperren:
### Was gemeldet wird
- Watchlist-Treffer
- Progressive-Ban-Sperren auf Maximalstufe
| Wird gemeldet | Wird nicht gemeldet |
|---|---|
| Watchlist-Treffer (permanent) | Temporäre Sperren |
| Progressive-Ban auf Maximalstufe (permanent) | GeoIP-Sperren |
| | Externe Blocklist-Sperren |
| | Manuelle Sperren |
Nicht gemeldet werden:
- temporäre Sperren
- GeoIP-Sperren
- externe Blocklist-Sperren
- manuelle Sperren
---
## GeoIP-Länderfilter
| Parameter | Standard | Beschreibung |
|---|---|---|
| `GEOIP_ENABLED` | `false` | GeoIP-Filter aktivieren |
| `GEOIP_MODE` | `blocklist` | `blocklist` oder `allowlist` |
| `GEOIP_COUNTRIES` | leer | ISO-3166-1-Alpha-2-Ländercodes |
| `GEOIP_CHECK_INTERVAL` | `0` | Legacy-Parameter; die Go-Version nutzt den zentralen Query-Poller |
| `GEOIP_NOTIFY` | `true` | Benachrichtigungen bei GeoIP-Sperren |
| `GEOIP_SKIP_PRIVATE` | `true` | private/lokale IPs überspringen |
| `GEOIP_LICENSE_KEY` | leer | MaxMind-License-Key für Auto-Download |
| `GEOIP_MMDB_PATH` | leer | manueller Pfad zur MaxMind-MMDB |
| `GEOIP_CACHE_TTL` | `86400` | Cache-Zeit in Sekunden |
| `GEOIP_MODE` | `blocklist` | Filtermodus |
| `GEOIP_COUNTRIES` | leer | Ländercodes nach ISO 3166-1 Alpha-2 |
| `GEOIP_CHECK_INTERVAL` | `0` | Legacy-Parameter (Go-Version nutzt den zentralen Poller) |
| `GEOIP_NOTIFY` | `true` | Benachrichtigungen bei GeoIP-Sperren senden |
| `GEOIP_SKIP_PRIVATE` | `true` | Private/lokale IPs überspringen |
| `GEOIP_LICENSE_KEY` | leer | MaxMind-License-Key für automatischen Download |
| `GEOIP_MMDB_PATH` | leer | Manueller Pfad zur MaxMind-MMDB-Datei (hat Vorrang) |
| `GEOIP_CACHE_TTL` | `86400` | GeoIP-Cache-Dauer in Sekunden (Standard: 24 Stunden) |
Blocklist-Modus:
### Modi
| Modus | Beschreibung |
|---|---|
| `blocklist` | Nur die genannten Länder werden gesperrt. Alle anderen sind erlaubt. |
| `allowlist` | Nur die genannten Länder sind erlaubt. Alle anderen öffentlichen IPs werden gesperrt. |
### Ländercodes
Die Ländercodes folgen dem Standard **ISO 3166-1 Alpha-2**. Eine vollständige Liste aller Ländercodes findest du in der [ISO-3166-1-Kodierliste auf Wikipedia](https://de.wikipedia.org/wiki/ISO-3166-1-Kodierliste).
Häufig verwendete Codes:
| Code | Land | | Code | Land |
|---|---|---|---|---|
| `DE` | Deutschland | | `CN` | China |
| `AT` | Österreich | | `RU` | Russland |
| `CH` | Schweiz | | `KP` | Nordkorea |
| `US` | Vereinigte Staaten | | `IR` | Iran |
| `GB` | Vereinigtes Königreich | | `BR` | Brasilien |
| `FR` | Frankreich | | `IN` | Indien |
| `NL` | Niederlande | | `VN` | Vietnam |
### Beispiel: Blocklist-Modus
```bash
GEOIP_ENABLED=true
@@ -549,9 +596,9 @@ GEOIP_MODE="blocklist"
GEOIP_COUNTRIES="CN,RU,KP,IR"
```
Damit werden öffentliche Clients aus diesen Ländern gesperrt.
Damit werden öffentliche DNS-Clients aus China, Russland, Nordkorea und dem Iran gesperrt.
Allowlist-Modus:
### Beispiel: Allowlist-Modus
```bash
GEOIP_ENABLED=true
@@ -559,62 +606,66 @@ GEOIP_MODE="allowlist"
GEOIP_COUNTRIES="DE,AT,CH"
```
Damit werden nur diese Länder erlaubt. Andere öffentliche Länder werden gesperrt.
Damit werden nur Clients aus Deutschland, Österreich und der Schweiz erlaubt. Alle anderen öffentlichen Länder werden gesperrt.
Private IPs:
### Private IPs
```bash
GEOIP_SKIP_PRIVATE=true
```
Damit werden unter anderem private Netze, Loopback, Link-Local und CGNAT übersprungen.
Damit werden folgende Adressbereiche übersprungen:
- Private Netze (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- Loopback (127.0.0.0/8, ::1)
- Link-Local (169.254.0.0/16, fe80::/10)
- CGNAT (100.64.0.0/10)
### GeoIP-Datenquellen
Priorität:
| Priorität | Quelle | Konfiguration |
|---:|---|---|
| 1 | Manueller MMDB-Pfad | `GEOIP_MMDB_PATH="/usr/share/GeoIP/GeoLite2-Country.mmdb"` |
| 2 | Automatischer MaxMind-Download | `GEOIP_LICENSE_KEY="dein_maxmind_license_key"` |
| 3 | Legacy-Fallback | `geoiplookup` / `geoiplookup6` Systembefehle |
1. `GEOIP_MMDB_PATH`, wenn gesetzt
2. automatisch geladene MaxMind-Datenbank, wenn `GEOIP_LICENSE_KEY` gesetzt ist
3. Legacy-Fallback über `geoiplookup` oder `geoiplookup6`
Automatischer MaxMind-Download:
### Automatischer MaxMind-Download
```bash
GEOIP_LICENSE_KEY="dein_maxmind_license_key"
```
Die Datenbank wird unter `/opt/adguard-shield/geoip/` gespeichert und nach 24 Stunden erneuert.
Die Datenbank wird unter `/opt/adguard-shield/geoip/` gespeichert und nach 24 Stunden automatisch erneuert.
Manueller Pfad:
### GeoIP-Befehle
```bash
GEOIP_MMDB_PATH="/usr/share/GeoIP/GeoLite2-Country.mmdb"
sudo /opt/adguard-shield/adguard-shield geoip-status # Status anzeigen
sudo /opt/adguard-shield/adguard-shield geoip-lookup 8.8.8.8 # IP nachschlagen
sudo /opt/adguard-shield/adguard-shield geoip-sync # Clients prüfen
sudo /opt/adguard-shield/adguard-shield geoip-flush-cache # Cache leeren
sudo /opt/adguard-shield/adguard-shield geoip-flush # Alle GeoIP-Sperren aufheben
```
Nützliche Befehle:
```bash
sudo /opt/adguard-shield/adguard-shield geoip-status
sudo /opt/adguard-shield/adguard-shield geoip-lookup 8.8.8.8
sudo /opt/adguard-shield/adguard-shield geoip-sync
sudo /opt/adguard-shield/adguard-shield geoip-flush-cache
```
---
## Protokollerkennung
AdGuard Shield liest das Feld `client_proto` aus der AdGuard-Home-API.
AdGuard Shield liest das Feld `client_proto` aus der AdGuard-Home-API und zeigt das verwendete DNS-Protokoll an.
| API-Wert | Anzeige | Bedeutung |
|---|---|---|
| leer oder `dns` | `DNS` | klassisches DNS |
| leer oder `dns` | `DNS` | Klassisches DNS |
| `doh` | `DoH` | DNS-over-HTTPS |
| `dot` | `DoT` | DNS-over-TLS |
| `doq` | `DoQ` | DNS-over-QUIC |
| `dnscrypt` | `DNSCrypt` | DNSCrypt |
| `dnscrypt` | `DNSCrypt` | DNSCrypt-Protokoll |
Die Sperre blockiert die konfigurierten Ports unabhängig davon, welches Protokoll den Verstoß ausgelöst hat.
Die Sperre blockiert immer alle konfigurierten Ports, unabhängig davon, welches Protokoll den Verstoß ausgelöst hat.
## Beispielkonfiguration für ein Heimnetz
---
## Beispielkonfiguration: Heimnetz
```bash
ADGUARD_URL="http://127.0.0.1:3000"
@@ -646,7 +697,7 @@ EXTERNAL_BLOCKLIST_ENABLED=false
EXTERNAL_WHITELIST_ENABLED=false
```
## Beispielkonfiguration für einen öffentlichen Resolver
## Beispielkonfiguration: Öffentlicher Resolver
```bash
ADGUARD_URL="https://dns.example.com"
@@ -670,6 +721,11 @@ PROGRESSIVE_BAN_ENABLED=true
PROGRESSIVE_BAN_MULTIPLIER=2
PROGRESSIVE_BAN_MAX_LEVEL=5
GEOIP_ENABLED=true
GEOIP_MODE="blocklist"
GEOIP_COUNTRIES="CN,RU,KP,IR"
GEOIP_LICENSE_KEY="..."
ABUSEIPDB_ENABLED=true
ABUSEIPDB_API_KEY="..."
@@ -678,7 +734,7 @@ NOTIFY_TYPE="ntfy"
NTFY_TOPIC="adguard-shield-prod"
```
Vor produktiver Aktivierung:
### Vor produktiver Aktivierung
```bash
sudo /opt/adguard-shield/adguard-shield test

View File

@@ -4,55 +4,57 @@ AdGuard Shield kann Statistik-Reports direkt aus der SQLite-Datenbank erzeugen u
## Was der Report enthält
Der Report basiert auf:
Der Report basiert auf der SQLite-Datenbank:
```text
/var/lib/adguard-shield/adguard-shield.db
```
Ausgewertet werden vor allem:
### Ausgewertete Daten
- `ban_history`
- `active_bans`
| Bereich | Inhalt |
|---|---|
| Zeitraum | Start- und Enddatum des Berichtszeitraums |
| Sperren | Anzahl der Sperren im Zeitraum |
| Freigaben | Anzahl der Freigaben im Zeitraum |
| Aktive Sperren | Derzeit aktive Sperren zum Zeitpunkt der Report-Erstellung |
| Top-Clients | Die am häufigsten gesperrten Client-IPs |
| Sperrgründe | Aufschlüsselung nach Grund (Rate-Limit, Subdomain-Flood, GeoIP usw.) |
| Sperrquellen | Aufschlüsselung nach Quelle (Monitor, GeoIP, Blocklist, manuell) |
| Letzte Ereignisse | Die letzten 20 Einträge aus der Ban-History |
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 | Standard | Beschreibung |
|---|---|---|
| `REPORT_ENABLED` | `false` | Report-Funktion logisch aktivieren |
| `REPORT_INTERVAL` | `weekly` | Versandintervall |
| `REPORT_TIME` | `08:00` | Versandzeit im Format `HH:MM` |
| `REPORT_EMAIL_TO` | `admin@example.com` | Empfängeradresse |
| `REPORT_EMAIL_FROM` | `adguard-shield@example.com` | Absenderadresse |
| `REPORT_FORMAT` | `html` | Report-Format (`html` oder `txt`) |
| `REPORT_MAIL_CMD` | `msmtp` | Mailprogramm für den Versand |
| `REPORT_BUSIEST_DAY_RANGE` | `30` | Kompatibilitätsparameter für den Zeitraum "Aktivster Tag" |
Parameter:
### Versandintervalle
| Parameter | Bedeutung |
| Intervall | Versandzeitpunkt |
|---|---|
| `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" |
| `daily` | Täglich zur Uhrzeit aus `REPORT_TIME` |
| `weekly` | Montags zur Uhrzeit aus `REPORT_TIME` |
| `biweekly` | Am 1. und 15. des Monats zur Uhrzeit aus `REPORT_TIME` |
| `monthly` | Am 1. des Monats zur Uhrzeit aus `REPORT_TIME` |
Beispiel:
### Formate
| Format | Beschreibung | Empfehlung |
|---|---|---|
| `html` | HTML-formatierte E-Mail mit Tabellen und Formatierung | Standard-Mail-Clients |
| `txt` | Reiner Text ohne Formatierung | Einfache Mail-Setups, Log-Ablage |
### Beispielkonfiguration
```bash
REPORT_ENABLED=true
@@ -64,31 +66,58 @@ REPORT_FORMAT="html"
REPORT_MAIL_CMD="msmtp"
```
---
## Befehle
### Konfiguration und Cron-Status anzeigen
```bash
# Konfiguration und Cron-Status anzeigen
sudo /opt/adguard-shield/adguard-shield report-status
```
# HTML-Report in Datei schreiben
### HTML-Report in Datei schreiben
```bash
sudo /opt/adguard-shield/adguard-shield report-generate html /tmp/adguard-shield-report.html
```
# Text-Report auf stdout ausgeben
Die Datei kann im Browser geöffnet werden, um das Ergebnis zu prüfen.
### Text-Report auf stdout ausgeben
```bash
sudo /opt/adguard-shield/adguard-shield report-generate txt
```
# Testmail senden
### Testmail senden
```bash
sudo /opt/adguard-shield/adguard-shield report-test
```
# aktuellen Report erzeugen und versenden
Sendet eine einfache Testmail. Erst wenn diese ankommt, lohnt sich die Fehlersuche am eigentlichen Report.
### Aktuellen Report erzeugen und versenden
```bash
sudo /opt/adguard-shield/adguard-shield report-send
```
# Cron-Job installieren
### Cron-Job installieren
```bash
sudo /opt/adguard-shield/adguard-shield report-install
```
# Cron-Job entfernen
### Cron-Job entfernen
```bash
sudo /opt/adguard-shield/adguard-shield report-remove
```
---
## Mailversand
AdGuard Shield übergibt die fertige Mail an ein lokales Mailprogramm. Der Standard ist:
@@ -97,26 +126,38 @@ AdGuard Shield übergibt die fertige Mail an ein lokales Mailprogramm. Der Stand
REPORT_MAIL_CMD="msmtp"
```
Minimaler Ablauf mit `msmtp`:
### Einrichtung mit msmtp
```bash
# msmtp installieren
sudo apt install msmtp msmtp-mta
# Testmail senden
sudo /opt/adguard-shield/adguard-shield report-test
```
`report-test` sendet eine einfache Testmail. Erst wenn diese funktioniert, lohnt sich die Fehlersuche am eigentlichen Report.
### Eigene Mailprogramm-Argumente
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
REPORT_MAIL_CMD="msmtp --account=default"
```
### Alternativen zu msmtp
| Programm | `REPORT_MAIL_CMD` |
|---|---|
| msmtp | `msmtp` |
| sendmail | `sendmail` |
| ssmtp | `ssmtp` |
| Benutzerdefiniert | Vollständiger Pfad zum Programm |
---
## Automatischer Versand
Cron installieren:
### Cron-Job installieren
```bash
sudo /opt/adguard-shield/adguard-shield report-install
@@ -134,57 +175,67 @@ Der Cron-Eintrag ruft das installierte Binary mit der installierten Konfiguratio
/opt/adguard-shield/adguard-shield -config /opt/adguard-shield/adguard-shield.conf report-send
```
Zeitplan nach `REPORT_INTERVAL`:
### Zeitplan nach Intervall
| 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 |
| `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 |
Cron entfernen:
### Cron-Job entfernen
```bash
sudo /opt/adguard-shield/adguard-shield report-remove
```
---
## Manuelle Prüfung
Status:
### Schritt 1: Status prüfen
```bash
sudo /opt/adguard-shield/adguard-shield report-status
```
Report lokal erzeugen:
### Schritt 2: Report lokal erzeugen
```bash
# HTML-Report zum Ansehen im Browser
sudo /opt/adguard-shield/adguard-shield report-generate html /tmp/adguard-shield-report.html
# Text-Report in der Konsole
sudo /opt/adguard-shield/adguard-shield report-generate txt
```
Versand testen:
### Schritt 3: Versand testen
```bash
# Einfache Testmail
sudo /opt/adguard-shield/adguard-shield report-test
# Vollständigen Report senden
sudo /opt/adguard-shield/adguard-shield report-send
```
Logs:
### Schritt 4: Logs prüfen
```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.
Je nach Distribution heißt der Cron-Service `cron`, `crond` oder wird über das allgemeine Syslog protokolliert.
---
## Häufige Probleme
### `REPORT_EMAIL_TO ist leer`
Setze einen Empfänger:
Setze einen Empfänger in der Konfiguration:
```bash
REPORT_EMAIL_TO="admin@example.com"
@@ -192,52 +243,42 @@ REPORT_EMAIL_TO="admin@example.com"
### Mailprogramm nicht gefunden
Prüfen:
Prüfe, ob das Mailprogramm installiert ist:
```bash
which msmtp
```
Installieren:
Installiere es bei Bedarf:
```bash
sudo apt install msmtp msmtp-mta
```
Oder `REPORT_MAIL_CMD` auf dein vorhandenes Mailprogramm setzen.
Oder setze `REPORT_MAIL_CMD` auf dein vorhandenes Mailprogramm.
### Cron läuft, aber keine Mail kommt an
Prüfen:
Prüfe die Konfiguration und den Cron-Job:
```bash
sudo /opt/adguard-shield/adguard-shield report-send
sudo cat /etc/cron.d/adguard-shield-report
```
Achte darauf, dass:
**Checkliste:**
- `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
| Prüfpunkt | Beschreibung |
|---|---|
| Empfänger | `REPORT_EMAIL_TO` korrekt gesetzt? |
| Mailprogramm | `REPORT_MAIL_CMD` im Cron-PATH verfügbar? |
| Root-Konfiguration | Mailer für root konfiguriert? (msmtp benötigt `/root/.msmtprc` oder `/etc/msmtprc`) |
| Spam | Spam-Ordner geprüft? |
| SMTP | Ausgehende SMTP-Verbindungen erlaubt? (Port 587/465) |
## HTML und TXT
### Format beim Generieren überschreiben
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:
Du kannst das Format unabhängig von der Konfiguration wählen:
```bash
sudo /opt/adguard-shield/adguard-shield report-generate txt

View File

@@ -4,41 +4,55 @@ Dieses Dokument hilft beim Eingrenzen typischer Probleme im Betrieb. Die Reihenf
## Erste Diagnose
Diese Befehle liefern meistens schon genug Hinweise:
Diese fünf Befehle liefern meistens schon genug Hinweise, um ein Problem einzugrenzen:
```bash
# 1. Läuft der Service?
sudo systemctl status adguard-shield
# 2. Was sagt das Journal?
sudo journalctl -u adguard-shield --no-pager -n 100
# 3. Funktioniert die API?
sudo /opt/adguard-shield/adguard-shield test
# 4. Was ist der aktuelle Zustand?
sudo /opt/adguard-shield/adguard-shield status
# 5. Gibt es Warnungen oder Fehler?
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
```
Wenn du aktuelle Queries sehen willst:
Wenn du aktuelle Queries und den Echtzeit-Zustand sehen willst:
```bash
sudo /opt/adguard-shield/adguard-shield live
```
---
## Service startet nicht
Prüfen:
### Prüfen
```bash
sudo systemctl status adguard-shield
sudo journalctl -u adguard-shield --no-pager -n 100
```
Typische Ursachen:
### Typische Ursachen
- 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
| Ursache | Lösung |
|---|---|
| Konfigurationsdatei fehlt | `/opt/adguard-shield/adguard-shield.conf` prüfen |
| Falsche Dateirechte | `sudo chmod 600 /opt/adguard-shield/adguard-shield.conf` |
| Binary fehlt oder nicht ausführbar | `ls -l /opt/adguard-shield/adguard-shield` prüfen |
| Systempakete fehlen | `which iptables ip6tables ipset systemctl` prüfen |
| API nicht erreichbar | Erst AdGuard Home starten |
| Alte Shell-Artefakte | Go-Installer meldet Konflikte, alte Version deinstallieren |
| Unit manuell geändert | `sudo systemctl daemon-reload` ausführen |
Nützliche Prüfungen:
### Nützliche Prüfbefehle
```bash
ls -l /opt/adguard-shield/adguard-shield
@@ -47,15 +61,17 @@ which iptables ip6tables ipset systemctl
sudo systemctl daemon-reload
```
---
## Verbindung zu AdGuard Home schlägt fehl
Test:
### Test
```bash
sudo /opt/adguard-shield/adguard-shield test
```
Prüfe in `/opt/adguard-shield/adguard-shield.conf`:
### Konfiguration prüfen
```bash
ADGUARD_URL="http://127.0.0.1:3000"
@@ -63,17 +79,17 @@ ADGUARD_USER="admin"
ADGUARD_PASS="..."
```
Häufige Fehler:
### Häufige Fehler und Lösungen
| 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 |
| Symptom | Mögliche Ursache | Lösung |
|---|---|---|
| HTTP 401/403 | Benutzername oder Passwort falsch | Zugangsdaten in der Konfiguration prüfen |
| HTTP 404 | Falsche URL oder falscher Port | URL und Port prüfen, AdGuard-Home-Weboberfläche testen |
| Timeout | Firewall, DNS-Problem oder falsche IP | Netzwerk und Erreichbarkeit prüfen |
| Connection refused | AdGuard Home läuft nicht oder anderer Port | `systemctl status AdGuardHome` prüfen |
| Keine Querylog-Einträge | Querylog deaktiviert oder leer | In AdGuard Home prüfen: Einstellungen > Querylog |
Direkt testen:
### Direkt testen (unabhängig von AdGuard Shield)
```bash
curl -k -u "admin:passwort" "http://127.0.0.1:3000/control/querylog?limit=1&response_status=all"
@@ -81,9 +97,11 @@ curl -k -u "admin:passwort" "http://127.0.0.1:3000/control/querylog?limit=1&resp
Passe URL und Zugangsdaten entsprechend an.
---
## Keine Sperren trotz vieler Anfragen
Prüfen:
### Prüfen
```bash
sudo /opt/adguard-shield/adguard-shield live --once
@@ -91,46 +109,53 @@ sudo /opt/adguard-shield/adguard-shield history 50
sudo /opt/adguard-shield/adguard-shield logs --level debug --limit 100
```
Mögliche Ursachen:
### Mögliche Ursachen und Lösungen
- `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
| Ursache | Lösung |
|---|---|
| `RATE_LIMIT_MAX_REQUESTS` zu hoch | Grenzwert senken oder `live` beobachten |
| `RATE_LIMIT_WINDOW` zu kurz | Zeitfenster verlängern |
| `API_QUERY_LIMIT` zu niedrig | Erhöhen, damit Spitzen nicht verpasst werden |
| Client steht in `WHITELIST` | Whitelist prüfen |
| Externe Whitelist enthält die IP | `whitelist-status` prüfen |
| Proxy/Forwarder maskiert echte Client-IPs | AdGuard Home sieht nur die Forwarder-IP; Forwarder whitelisten |
| Querylog enthält die Anfragen nicht | In AdGuard Home prüfen, ob Querylog aktiviert ist |
| `DRY_RUN=true` ist gesetzt | In der Konfiguration auf `false` setzen |
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.
**Wichtig bei Proxies und Forwardern:** Wenn AdGuard Home nur eine einzige interne IP sieht (z.B. die IP eines Routers oder Reverse Proxy), 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:
### Übersicht verschaffen
```bash
sudo /opt/adguard-shield/adguard-shield status
sudo /opt/adguard-shield/adguard-shield history 100
```
Dann Ursachen einordnen:
### Ursachen und Gegenmaßnahmen
| 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 |
| Legitimer Client fragt häufig dieselbe Domain | Client whitelisten oder `RATE_LIMIT_MAX_REQUESTS` erhöhen |
| Router/Resolver bündelt viele Clients | Router/Resolver in `WHITELIST` aufnehmen |
| 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 |
| Externe Blocklist ist sehr groß | `blocklist-status` prüfen und ggf. Liste anpassen |
| GeoIP Allowlist zu eng | Länder prüfen oder `GEOIP_MODE` wechseln |
Falsch gesperrte IP freigeben:
### Falsch gesperrte IP freigeben
```bash
# Sperre aufheben
sudo /opt/adguard-shield/adguard-shield unban 192.168.1.100
# Offense-Zähler zurücksetzen (damit progressive Sperren nicht sofort eskalieren)
sudo /opt/adguard-shield/adguard-shield reset-offenses 192.168.1.100
```
Dauerhaft ausnehmen:
### Dauerhaft ausnehmen
```bash
WHITELIST="127.0.0.1,::1,192.168.1.1,192.168.1.100"
@@ -142,24 +167,35 @@ Danach:
sudo systemctl restart adguard-shield
```
---
## Firewall prüfen
Status:
### Status über AdGuard Shield
```bash
sudo /opt/adguard-shield/adguard-shield firewall-status
```
Direkt prüfen:
### Direkte Prüfung mit Systembefehlen
```bash
# ipsets anzeigen
sudo ipset list adguard_shield_v4
sudo ipset list adguard_shield_v6
# iptables-Regeln anzeigen
sudo iptables -n -L ADGUARD_SHIELD --line-numbers -v
sudo ip6tables -n -L ADGUARD_SHIELD --line-numbers -v
# Prüfen, ob Chain in INPUT eingehängt ist
sudo iptables -n -L INPUT --line-numbers -v | grep ADGUARD
# Bei Docker Bridge: DOCKER-USER prüfen
sudo iptables -n -L DOCKER-USER --line-numbers -v | grep ADGUARD
```
Firewall neu aufbauen:
### Firewall neu aufbauen
```bash
sudo /opt/adguard-shield/adguard-shield firewall-remove
@@ -169,40 +205,47 @@ 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:
### 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.
Temporäre Sperren werden beim Start und während jedes Pollings auf Ablauf geprüft. Wenn eine Sperre als permanent angezeigt wird, wird sie nicht automatisch freigegeben.
Permanent sind typischerweise:
### Permanente Sperren (gewollt)
- DNS-Flood-Watchlist-Treffer
- Progressive-Ban-Maximalstufe
- manuelle `ban`-Sperren
- GeoIP-Sperren
- externe Blocklist mit `EXTERNAL_BLOCKLIST_BAN_DURATION=0`
| Typ | Warum permanent |
|---|---|
| DNS-Flood-Watchlist-Treffer | Sofortiger Permanent-Ban |
| Progressive-Ban auf Maximalstufe | Eskalation durch wiederholte Verstöße |
| Manuelle `ban`-Sperren | Manuell gesetzt, manuell aufheben |
| GeoIP-Sperren | Permanent bis Konfigurationsänderung |
| Externe Blocklist mit `BAN_DURATION=0` | Permanent bis IP aus Liste entfernt |
Manuell freigeben:
### 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:
Dry-Run ist ideal, um neue Konfigurationen zu prüfen, bevor sie produktiv gehen:
```bash
# Dry-Run starten (Strg+C zum Beenden)
sudo /opt/adguard-shield/adguard-shield dry-run
```
Währenddessen:
Währenddessen die Ergebnisse prüfen:
```bash
sudo /opt/adguard-shield/adguard-shield history 50
@@ -210,215 +253,291 @@ 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:
### Status prüfen
```bash
sudo /opt/adguard-shield/adguard-shield whitelist-status
```
Manuell synchronisieren:
### Manuell synchronisieren
```bash
sudo /opt/adguard-shield/adguard-shield whitelist-sync
```
Typische Probleme:
### 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
| Problem | Lösung |
|---|---|
| URL nicht erreichbar | URL im Browser oder mit `curl` testen |
| Windows-Zeilenenden oder BOM | Datei in UTF-8 ohne BOM und mit `LF`-Zeilenenden speichern |
| Hostname nicht auflösbar | DNS-Auflösung prüfen, ggf. alternativen Hostnamen verwenden |
| Einträge enthalten Ports oder URLs | Nur IPs, CIDR-Netze und Hostnamen werden unterstützt |
| DNS liefert `0.0.0.0` | AdGuard blockiert den Host; Ausnahme in AdGuard Home einrichten |
Format prüfen:
### Erwartetes Listenformat
```text
192.168.1.100
10.0.0.0/24
trusted.example.com
192.168.1.100 # IPv4-Adresse
10.0.0.0/24 # CIDR-Netz
trusted.example.com # Hostname (wird per DNS aufgelöst)
# Kommentare sind erlaubt
```
---
## Externe Blocklist
Status:
### Status prüfen
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-status
```
Manuell synchronisieren:
### Manuell synchronisieren
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-sync
```
Alle externen Blocklist-Sperren freigeben:
### Alle Blocklist-Sperren freigeben
```bash
sudo /opt/adguard-shield/adguard-shield blocklist-flush
```
Wenn zu viele IPs gesperrt werden:
### Zu viele IPs gesperrt?
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.
1. `EXTERNAL_BLOCKLIST_URLS` prüfen: Welche Listen sind konfiguriert?
2. Liste manuell ansehen: Wie viele Einträge enthält sie?
3. Whitelist ergänzen: Eigene IPs sollten dort stehen.
4. `EXTERNAL_BLOCKLIST_NOTIFY=false` belassen, um den Benachrichtigungskanal nicht zu überfluten.
5. `EXTERNAL_BLOCKLIST_AUTO_UNBAN=true` setzen, damit entfernte Einträge automatisch freigegeben werden.
---
## GeoIP
Status:
### Status prüfen
```bash
sudo /opt/adguard-shield/adguard-shield geoip-status
```
Einzelne IP prüfen:
### Einzelne IP prüfen
```bash
sudo /opt/adguard-shield/adguard-shield geoip-lookup 8.8.8.8
```
Cache leeren:
### Cache leeren
```bash
sudo /opt/adguard-shield/adguard-shield geoip-flush-cache
```
Alle GeoIP-Sperren freigeben:
### Alle GeoIP-Sperren freigeben
```bash
sudo /opt/adguard-shield/adguard-shield geoip-flush
```
Typische Ursachen:
### Typische Probleme und Lösungen
| 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 |
| Keine Länder erkannt | MaxMind-Key, MMDB-Pfad oder `geoiplookup`-Befehl prüfen |
| Private IPs werden nicht geprüft | `GEOIP_SKIP_PRIVATE=true` ist Standard und korrekt |
| 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; alle anderen werden gesperrt |
| Datenbank nicht gefunden | `GEOIP_LICENSE_KEY` oder `GEOIP_MMDB_PATH` setzen |
| Datenbank veraltet | `geoip-flush-cache` und Service neu starten |
### Ländercodes nachschlagen
Die GeoIP-Ländercodes folgen dem Standard ISO 3166-1 Alpha-2. Eine vollständige Liste findest du in der [ISO-3166-1-Kodierliste auf Wikipedia](https://de.wikipedia.org/wiki/ISO-3166-1-Kodierliste).
---
## Reports
Status:
### Status prüfen
```bash
sudo /opt/adguard-shield/adguard-shield report-status
```
Test:
### Funktionstest
```bash
# Testmail senden
sudo /opt/adguard-shield/adguard-shield report-test
# Text-Report in der Konsole ansehen
sudo /opt/adguard-shield/adguard-shield report-generate txt
```
Wenn keine Mail ankommt:
### Keine Mail kommt an?
- `REPORT_EMAIL_TO` gesetzt?
- `REPORT_MAIL_CMD` vorhanden?
- Mailer für root konfiguriert?
- Cron installiert?
- Spam-Ordner geprüft?
| Prüfpunkt | Befehl / Aktion |
|---|---|
| `REPORT_EMAIL_TO` gesetzt? | Konfiguration prüfen |
| `REPORT_MAIL_CMD` vorhanden? | `which msmtp` |
| Mailer für root konfiguriert? | `/root/.msmtprc` oder `/etc/msmtprc` prüfen |
| Cron installiert? | `sudo cat /etc/cron.d/adguard-shield-report` |
| Spam-Ordner geprüft? | E-Mail-Provider prüfen |
| SMTP-Port offen? | Ausgehende Verbindung auf Port 587/465 testen |
Cron prüfen:
### Cron prüfen
```bash
sudo cat /etc/cron.d/adguard-shield-report
sudo /opt/adguard-shield/adguard-shield report-send
```
---
## Benachrichtigungen
Prüfen:
### Prüfen
```bash
sudo /opt/adguard-shield/adguard-shield logs --level warn --limit 100
```
Häufige Ursachen:
### Checkliste
- `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`
| Prüfpunkt | Beschreibung |
|---|---|
| `NOTIFY_ENABLED=true` | Benachrichtigungen global aktiviert? |
| `NOTIFY_TYPE` | Korrekt geschrieben? (`ntfy`, `discord`, `slack`, `gotify`, `generic`) |
| Webhook-URL | Gesetzt und erreichbar? |
| Ntfy-Topic | Nicht leer? |
| Token | Gültig und nicht abgelaufen? |
| Netzwerk | Ausgehende HTTPS-Verbindungen möglich? |
| Modul-Schalter | `EXTERNAL_BLOCKLIST_NOTIFY` und `GEOIP_NOTIFY` separat prüfen |
Bei `generic` Webhook kannst du testweise einen lokalen HTTP-Empfänger oder einen Request-Inspector (z.B. webhook.site) verwenden, um den gesendeten Payload zu sehen.
---
## SQLite direkt auswerten
Für tiefergehende Analysen:
Für tiefergehende Analysen kannst du die SQLite-Datenbank direkt abfragen:
### Sperren nach Quelle und Grund
```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;"
"SELECT source, reason, count(*) FROM active_bans GROUP BY source, reason ORDER BY count(*) DESC;"
```
Letzte History:
### Letzte History-Einträge
```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;"
"SELECT timestamp_text, action, client_ip, domain, reason FROM ban_history ORDER BY id DESC LIMIT 20;"
```
Offense-Zähler:
### 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;"
"SELECT client_ip, offense_level, last_offense FROM offense_tracking ORDER BY offense_level DESC;"
```
### Whitelist-Cache
```bash
sudo sqlite3 /var/lib/adguard-shield/adguard-shield.db \
"SELECT ip, source FROM whitelist_cache ORDER BY ip;"
```
### GeoIP-Cache
```bash
sudo sqlite3 /var/lib/adguard-shield/adguard-shield.db \
"SELECT ip, country_code FROM geoip_cache ORDER BY ip LIMIT 50;"
```
---
## 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
```
| Datei | Funktion in der alten Version |
|---|---|
| `adguard-shield.sh` | Hauptskript |
| `iptables-helper.sh` | Firewall-Management |
| `external-blocklist-worker.sh` | Blocklist-Synchronisation |
| `external-whitelist-worker.sh` | Whitelist-Synchronisation |
| `geoip-worker.sh` | GeoIP-Prüfung |
| `offense-cleanup-worker.sh` | Offense-Bereinigung |
| `report-generator.sh` | Report-Erstellung |
| `unban-expired.sh` | Ablauf temporärer Sperren |
| `adguard-shield-watchdog.sh` | Watchdog-Skript |
Die Go-Version ersetzt diese Funktionen durch das eine Binary. Alte Worker sollten nicht parallel laufen.
Details zur Migration stehen in der [Update-Anleitung](update.md).
---
## Service hart zurücksetzen
Wenn der Zustand unklar ist:
Wenn der Zustand unklar ist und ein sauberer Neustart nötig ist:
```bash
# Service stoppen
sudo systemctl stop adguard-shield
# Firewall-Struktur entfernen
sudo /opt/adguard-shield/adguard-shield firewall-remove
# Service neu starten (baut Firewall aus SQLite wieder auf)
sudo systemctl start adguard-shield
# Status prüfen
sudo /opt/adguard-shield/adguard-shield status
```
Das entfernt die Firewall-Struktur und lässt den Daemon sie beim Start wieder aus SQLite aufbauen.
Das entfernt die Firewall-Struktur und lässt den Daemon sie beim Start wieder aus dem SQLite-State aufbauen. Aktive Sperren bleiben in der Datenbank erhalten.
---
## Deinstallation
Konfiguration behalten:
### Konfiguration behalten
```bash
sudo /opt/adguard-shield/adguard-shield uninstall --keep-config
```
Alles entfernen:
### Alles entfernen
```bash
sudo /opt/adguard-shield/adguard-shield uninstall
```
Ohne `--keep-config` werden Installationsverzeichnis, State-Verzeichnis und Logdatei entfernt.
---
## Zusammenfassung: Wichtigste Diagnosebefehle
| Befehl | Zweck |
|---|---|
| `systemctl status adguard-shield` | Service-Status prüfen |
| `journalctl -u adguard-shield -n 100` | Systemd-Journal ansehen |
| `test` | API-Verbindung prüfen |
| `status` | Aktuellen Zustand und aktive Sperren anzeigen |
| `live` | Echtzeit-Ansicht mit Queries, Sperren und Logs |
| `history 100` | Ban-History anzeigen |
| `logs --level warn --limit 100` | Warnungen und Fehler anzeigen |
| `firewall-status` | Firewall-Regeln und ipsets anzeigen |
| `dry-run` | Konfiguration testen ohne echte Sperren |

View File

@@ -5,7 +5,7 @@ AdGuard Shield wird in der Go-Version über das Binary selbst installiert und ak
## Kurzfassung
```bash
# neues Linux-Binary bereitstellen
# Neues Linux-Binary bereitstellen
chmod +x ./adguard-shield
# Update durchführen
@@ -14,7 +14,7 @@ sudo ./adguard-shield update
Am Ende fragt der Updater, ob AdGuard Shield direkt neu gestartet werden soll.
Danach prüfen:
### Nach dem Update prüfen
```bash
sudo /opt/adguard-shield/adguard-shield install-status
@@ -22,11 +22,13 @@ sudo /opt/adguard-shield/adguard-shield status
sudo journalctl -u adguard-shield --no-pager -n 50
```
## Woher kommt das neue Binary?
---
## Neues Binary beziehen
Du brauchst ein fertiges Linux-Binary. Das kann aus einem Release, aus CI oder aus einem lokalen Build kommen.
Release-Binary für v1.0.0 herunterladen:
### Variante A: Release-Binary herunterladen
```bash
curl -fL -o adguard-shield-linux-amd64.tar.gz \
@@ -35,13 +37,13 @@ tar -xzf adguard-shield-linux-amd64.tar.gz
chmod +x ./adguard-shield
```
Build mit lokal installiertem Go:
### Variante B: Lokal mit Go bauen
```bash
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o adguard-shield ./cmd/adguard-shieldd
```
Build ohne lokale Go-Installation mit Docker:
### Variante C: Per Docker bauen (ohne lokales Go)
```bash
docker run --rm -v "$PWD":/src -w /src \
@@ -51,41 +53,59 @@ docker run --rm -v "$PWD":/src -w /src \
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.
| Schritt | Aktion |
|---:|---|
| 1 | Linux- und Root-Rechte prüfen |
| 2 | Auf alte Shell-Artefakte prüfen |
| 3 | Systemabhängigkeiten prüfen (sofern nicht `--skip-deps`) |
| 4 | Installationsverzeichnis sicherstellen |
| 5 | Neues Binary nach `/opt/adguard-shield/adguard-shield` kopieren |
| 6 | Konfiguration migrieren (vorhandene Werte behalten, neue ergänzen) |
| 7 | systemd-Service neu schreiben |
| 8 | `systemctl daemon-reload` |
| 9 | Autostart aktivieren (sofern nicht `--no-enable`) |
| 10 | Nachfrage: Service direkt neu starten |
---
## Konfigurationsmigration
Vorhandene Werte bleiben erhalten. Neue Parameter werden ergänzt.
Vorhandene Werte bleiben erhalten. Neue Parameter werden am Ende der Datei ergänzt. Der Installer überschreibt keine bestehenden Einstellungen.
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
```
| Datei | Inhalt |
|---|---|
| `adguard-shield.conf` | Aktualisierte Konfiguration mit alten + neuen Parametern |
| `adguard-shield.conf.old` | Backup der vorherigen Datei |
Nach dem Update solltest du prüfen:
### Änderungen 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.
Falls `diff` keine `.old`-Datei findet, war keine Konfigurationsmigration nötig.
## Update mit Service-Neustart
### Neue Parameter prüfen
Nach dem Update solltest du die neu ergänzten Parameter überprüfen und bei Bedarf anpassen:
```bash
sudo nano /opt/adguard-shield/adguard-shield.conf
```
---
## Update-Optionen
### Update mit Service-Neustart
Wenn der Service nach dem Update direkt laufen soll, bestätige die Nachfrage am Ende mit `j`.
@@ -98,141 +118,167 @@ sudo /opt/adguard-shield/adguard-shield dry-run
sudo systemctl restart adguard-shield
```
## Update ohne Paketprüfung
### 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.
Sinnvoll, wenn `iptables`, `ip6tables`, `ipset` und `systemctl` bereits vorhanden sind oder die Paketinstallation nicht über `apt-get` laufen soll.
## Update in anderem Installationsverzeichnis
### Update mit expliziter Konfigurationsquelle
```bash
sudo ./adguard-shield update --config-source ./adguard-shield.conf
```
### 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.
**Hinweis:** 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:
### Typische alte Artefakte
```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
```
| Datei | Funktion in der alten Version |
|---|---|
| `adguard-shield.sh` | Hauptskript |
| `iptables-helper.sh` | Firewall-Management |
| `external-blocklist-worker.sh` | Blocklist-Synchronisation |
| `external-whitelist-worker.sh` | Whitelist-Synchronisation |
| `geoip-worker.sh` | GeoIP-Prüfung |
| `offense-cleanup-worker.sh` | Offense-Bereinigung |
| `report-generator.sh` | Report-Erstellung |
| `unban-expired.sh` | Ablauf temporärer Sperren |
| `adguard-shield-watchdog.service` | Watchdog-Service |
| `adguard-shield-watchdog.timer` | Watchdog-Timer |
Warum Abbruch?
### Warum bricht der Installer ab?
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.
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, bei denen zwei Implementierungen sich gegenseitig die Regeln überschreiben.
Empfohlener Migrationsablauf:
### Empfohlener Migrationsablauf
```bash
# Konfiguration sichern
# 1. 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
# 2. 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
# 3. Neues Go-Binary installieren und alte Konfiguration als Quelle nutzen
sudo ./adguard-shield install --config-source /root/adguard-shield.conf.backup
# prüfen
# 4. API-Verbindung prüfen
sudo /opt/adguard-shield/adguard-shield test
# 5. Dry-Run: prüfen, was gesperrt würde
sudo /opt/adguard-shield/adguard-shield dry-run
# 6. Produktiven Service starten
sudo systemctl start adguard-shield
sudo systemctl status adguard-shield
```
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.
**Wichtig:** 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:
### Installation
```bash
sudo /opt/adguard-shield/adguard-shield install-status
```
Service:
### Service
```bash
sudo systemctl status adguard-shield
sudo journalctl -u adguard-shield --no-pager -n 100
```
API:
### API-Verbindung
```bash
sudo /opt/adguard-shield/adguard-shield test
```
Runtime:
### Laufzeitstatus
```bash
sudo /opt/adguard-shield/adguard-shield status
sudo /opt/adguard-shield/adguard-shield live --once
```
Firewall:
### 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:
### Schritt-für-Schritt
```bash
# 1. Service stoppen
sudo systemctl stop adguard-shield
# 2. Altes Binary wiederherstellen
sudo cp ./adguard-shield-alte-version /opt/adguard-shield/adguard-shield
sudo chmod +x /opt/adguard-shield/adguard-shield
# 3. Service starten
sudo systemctl start adguard-shield
```
Wenn die Konfiguration zurückgesetzt werden soll:
### Konfiguration zurücksetzen (optional)
```bash
sudo cp /opt/adguard-shield/adguard-shield.conf.old /opt/adguard-shield/adguard-shield.conf
sudo systemctl restart adguard-shield
```
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.
**Hinweis:** SQLite-Schema-Migrationen sind aktuell sehr konservativ. Trotzdem solltest du vor größeren Updates ein Backup der Datenbank erstellen, wenn dir History und aktive Sperren wichtig sind.
---
## Backup vor größeren Updates
```bash
# Service kurz stoppen für konsistentes Backup
sudo systemctl stop adguard-shield
# Konfiguration und Datenbank sichern
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)
# Service wieder starten
sudo systemctl start adguard-shield
```
### WAL-Dateien beachten
Bei laufendem SQLite mit WAL können zusätzliche Dateien existieren:
```text
adguard-shield.db-wal
adguard-shield.db-shm
```
| Datei | Beschreibung |
|---|---|
| `adguard-shield.db` | Hauptdatenbank |
| `adguard-shield.db-wal` | Write-Ahead-Log (enthält noch nicht in die Hauptdatei geschriebene Daten) |
| `adguard-shield.db-shm` | Shared-Memory-Datei |
Am saubersten ist ein kurzer Service-Stop während des Backups.
Am saubersten ist ein kurzer Service-Stop während des Backups. So wird sichergestellt, dass alle WAL-Einträge in die Hauptdatei geschrieben werden.