feat: Migration auf sqlite3

This commit is contained in:
Patrick Asmus
2026-04-30 15:39:26 +02:00
parent 125329e4ff
commit 0d1f7db43b
18 changed files with 1118 additions and 745 deletions

View File

@@ -93,48 +93,36 @@ ADGUARD_SHIELD Chain
- Kann komplett geflusht werden ohne andere Regeln zu beeinflussen
- Einfaches Debugging per `iptables -L ADGUARD_SHIELD`
## State-Management
## State-Management (SQLite)
Jede aktive Sperre wird als Datei gespeichert:
Alle Laufzeitdaten werden in einer zentralen SQLite-Datenbank gespeichert:
```
/var/lib/adguard-shield/192.168.1.50.ban
/var/lib/adguard-shield/adguard-shield.db
```
Inhalt:
```
CLIENT_IP=192.168.1.50
DOMAIN=microsoft.com
COUNT=45
BAN_TIME=2026-03-03 14:30:00
BAN_UNTIL_EPOCH=1741012200
BAN_UNTIL=2026-03-03 15:30:00
BAN_DURATION=3600
OFFENSE_LEVEL=1
IS_PERMANENT=false
REASON=rate-limit
```
Die Datenbank enthält folgende Tabellen:
Zusätzlich wird für jede IP ein Offense-Tracker gespeichert:
| Tabelle | Beschreibung |
|---------|--------------|
| `active_bans` | Aktive Sperren (IP, Domain, Sperrdauer, Offense-Level, Grund, Quelle, GeoIP) |
| `offense_tracking` | Offense-Zähler für progressive Sperren (Level, letztes/erstes Vergehen) |
| `ban_history` | Vollständige Ban-History (alle Sperren und Entsperrungen) |
| `whitelist_cache` | Cache der aufgelösten externen Whitelist-IPs |
| `schema_version` | Datenbank-Schema-Version für zukünftige Migrationen |
```
/var/lib/adguard-shield/192.168.1.50.offenses
```
**Vorteile gegenüber Flat-Files:**
- Schnellere Abfragen, besonders bei vielen aktiven Sperren
- Atomare Transaktionen — kein Datenverlust bei Stromausfall
- WAL-Modus für parallelen Lese-/Schreibzugriff
- Indexierte Suche nach IP, Zeitstempel, Quelle und Aktion
- Kompakte Speicherung statt tausender Einzeldateien
Inhalt:
```
CLIENT_IP=192.168.1.50
OFFENSE_LEVEL=2
LAST_OFFENSE_EPOCH=1741008600
LAST_OFFENSE=2026-03-03 14:30:00
FIRST_OFFENSE=2026-03-03 12:15:00
```
Die zentrale Datenbankbibliothek (`db.sh`) wird von allen Scripts per `source db.sh` eingebunden und stellt typisierte Funktionen für alle Tabellen bereit (z.B. `db_ban_insert`, `db_offense_get_level`, `db_history_add`).
Das ermöglicht:
- Persistenz über Script-Neustarts hinweg
- Statusabfragen jederzeit möglich
- Automatisches Aufräumen per Cron-Job
- Progressive Sperrzeiten über mehrere Ban-Zyklen hinweg
### Migration von Flat-Files
Beim Update auf die SQLite-Version werden bestehende Flat-File-Daten (`.ban`, `.offenses`, Ban-History-Log, Whitelist-Cache) automatisch in die Datenbank migriert. Die alten Dateien werden als Backup nach `/var/lib/adguard-shield/.backup_pre_sqlite/` verschoben. Die Migration läuft einmalig beim Update und zeigt den Fortschritt im Terminal an.
## Dateistruktur nach Installation
@@ -149,6 +137,7 @@ Das ermöglicht:
├── external-whitelist-worker.sh # Externer Whitelist-Worker (DNS-Auflösung)
├── geoip-worker.sh # GeoIP-Länderfilter-Worker
├── offense-cleanup-worker.sh # Aufräumen abgelaufener Offense-Zähler (nice 19, idle I/O)
├── db.sh # SQLite Datenbank-Bibliothek (wird von allen Scripts eingebunden)
├── unban-expired.sh # Cron-basiertes Entsperren
└── geoip/ # Auto-Download MaxMind GeoLite2 DB (optional)
@@ -158,15 +147,16 @@ Das ermöglicht:
└── adguard-shield-watchdog.timer # systemd Timer (alle 5 Min.)
/var/lib/adguard-shield/
├── *.ban # State-Dateien aktiver Sperren
├── *.offenses # Offense-Zähler (Progressive Sperren)
├── adguard-shield.db # SQLite-Datenbank (Bans, Offenses, History, Whitelist-Cache)
├── .migration_v1_complete # Marker: Flat-File-Migration abgeschlossen
├── .backup_pre_sqlite/ # Backup der alten Flat-Files nach Migration
├── external-blocklist/ # Cache für externe Blocklisten
├── external-whitelist/ # Cache für externe Whitelisten + aufgelöste IPs
├── external-whitelist/ # Cache für externe Whitelisten
└── geoip-cache/ # Cache für GeoIP-Lookups (24h)
/var/log/
├── adguard-shield.log # Laufzeit-Log
└── adguard-shield-bans.log # Ban-History (alle Sperren/Entsperrungen)
└── adguard-shield-bans.log # Ban-History (Legacy, wird nach Migration nicht mehr geschrieben)
```
## Installer-Architektur
@@ -176,7 +166,7 @@ Der Installer (`install.sh`) bietet ein interaktives Menü und folgende Funktion
| Befehl | Beschreibung |
|--------|--------------|
| `install` | Vollständige Neuinstallation (Abhängigkeiten, Dateien, Konfiguration, Service, Watchdog) |
| `update` | Update mit automatischer Konfigurations-Migration, Watchdog-Aktivierung und Service-Neustart |
| `update` | Update mit automatischer Konfigurations-Migration, Datenbank-Migration, Watchdog-Aktivierung und Service-Neustart |
| `uninstall` | Deinstallation mit optionalem Behalten der Konfiguration |
| `status` | Installationsstatus, Version und Service-Status anzeigen |
| `--help` | Hilfe und Befehlsübersicht |
@@ -206,15 +196,20 @@ Der Installer (`install.sh`) bietet ein interaktives Menü und folgende Funktion
## Ban-History
Jede Sperre und Entsperrung wird dauerhaft in der Ban-History protokolliert (`/var/log/adguard-shield-bans.log`). Das ermöglicht eine lückenlose Nachvollziehbarkeit, auch nachdem State-Dateien bereits gelöscht wurden.
Jede Sperre und Entsperrung wird dauerhaft in der SQLite-Datenbank protokolliert (Tabelle `ban_history`). Das ermöglicht eine lückenlose Nachvollziehbarkeit mit indexierter Suche nach IP, Zeitstempel und Aktion.
**Format:**
```
ZEITSTEMPEL | AKTION | CLIENT-IP | DOMAIN | ANFRAGEN | SPERRDAUER | GRUND
2026-03-03 14:30:12 | BAN | 192.168.1.50 | microsoft.com | 45 | 3600s | rate-limit
2026-03-03 15:30:12 | UNBAN | 192.168.1.50 | microsoft.com | - | - | expired
2026-03-03 16:10:33 | UNBAN | 10.0.0.25 | telemetry.example.com | - | - | manual
```
**Gespeicherte Felder pro Eintrag:**
| Feld | Beschreibung |
|------|--------------|
| `timestamp_epoch` | Unix-Zeitstempel |
| `timestamp_text` | Lesbarer Zeitstempel |
| `action` | `BAN` oder `UNBAN` |
| `client_ip` | Betroffene IP-Adresse |
| `domain` | Angefragte Domain |
| `count` | Anzahl der Anfragen |
| `duration` | Sperrdauer |
| `protocol` | Verwendetes DNS-Protokoll |
| `reason` | Sperrgrund |
**Mögliche Gründe (GRUND-Spalte):**
| Grund | Bedeutung |

View File

@@ -42,9 +42,10 @@ Beim Update passiert automatisch:
2. Die bestehende Konfiguration wird als `adguard-shield.conf.old` gesichert
3. Neue Konfigurationsparameter werden automatisch zur bestehenden Konfig hinzugefügt
4. Bestehende Einstellungen bleiben **immer** erhalten
5. Der systemd Service und Watchdog-Timer werden per `daemon-reload` neu geladen
6. Der Watchdog-Timer wird automatisch aktiviert (falls noch nicht aktiv)
7. Der Service wird automatisch neu gestartet (falls er lief)
5. Bestehende Flat-File-Daten werden einmalig (mit einem Update kommend von einer v0.9.0 oder älter) in die SQLite-Datenbank migriert (mit Fortschrittsanzeige und Backup)
6. Der systemd Service und Watchdog-Timer werden per `daemon-reload` neu geladen
7. Der Watchdog-Timer wird automatisch aktiviert (falls noch nicht aktiv)
8. Der Service wird automatisch neu gestartet (falls er lief)
### API-Verbindungstest nach Installation
@@ -66,6 +67,7 @@ Folgende Pakete werden bei der Installation automatisch installiert (via `apt`):
- `iptables` — Firewall-Regeln für IP-Sperren
- `gawk` — Textverarbeitung
- `systemd` — Service-Management
- `sqlite3` — Datenbank für State-Management, Ban-History und Offense-Tracking
## systemd Service

View File

@@ -137,7 +137,7 @@ Wiederholungstäter werden wie bei fail2ban stufenweise länger gesperrt. Wird e
| `LOG_FILE` | `/var/log/adguard-shield.log` | Pfad zur Log-Datei |
| `LOG_LEVEL` | `INFO` | Log-Level: `DEBUG`, `INFO`, `WARN`, `ERROR` |
| `LOG_MAX_SIZE_MB` | `50` | Max. Log-Größe bevor rotiert wird |
| `BAN_HISTORY_FILE` | `/var/log/adguard-shield-bans.log` | Datei für die Ban-History (alle Sperren/Entsperrungen) |
| `BAN_HISTORY_FILE` | `/var/log/adguard-shield-bans.log` | Legacy: Pfad zur alten Ban-History-Datei (wird bei der SQLite-Migration als Quelle verwendet). Neue Einträge werden direkt in die SQLite-Datenbank geschrieben. |
| `BAN_HISTORY_RETENTION_DAYS` | `0` | Aufbewahrungsdauer der Ban-History in Tagen. `0` = unbegrenzt (niemals löschen). Alte Einträge werden beim nächsten Report automatisch entfernt. |
### Benachrichtigungen
@@ -175,7 +175,7 @@ Regelmäßige Statistik-Reports per E-Mail. Voraussetzung ist ein funktionierend
| Parameter | Standard | Beschreibung |
|-----------|----------|--------------|
| `STATE_DIR` | `/var/lib/adguard-shield` | Verzeichnis für State-Dateien |
| `STATE_DIR` | `/var/lib/adguard-shield` | Verzeichnis für die SQLite-Datenbank (`adguard-shield.db`) und Caches |
| `PID_FILE` | `/var/run/adguard-shield.pid` | PID-Datei |
| `DRY_RUN` | `false` | Testmodus — nur loggen, nicht sperren |

View File

@@ -259,7 +259,7 @@ Die Test-Mail enthält eine Übersicht der aktuellen Konfiguration und bestätig
### Report enthält keine Daten
Der Report basiert auf der Ban-History-Datei (`/var/log/adguard-shield-bans.log`). Wenn keine Sperren im Berichtszeitraum vorhanden sind, zeigt der Report „Keine Daten" an.
Der Report basiert auf der Ban-History in der SQLite-Datenbank (`/var/lib/adguard-shield/adguard-shield.db`). Wenn keine Sperren im Berichtszeitraum vorhanden sind, zeigt der Report „Keine Daten" an.
### Cron-Job wird nicht ausgeführt

View File

@@ -149,7 +149,7 @@ Wenn eine IP die maximale Stufe der progressiven Sperren erreicht hat, wird sie
### Sperren überleben Reboot nicht
Das ist normal — iptables-Regeln sind flüchtig. Der **Service** erstellt die Chain beim Start automatisch neu. Aktive Sperren aus dem State-Verzeichnis werden aber nicht automatisch wiederhergestellt.
Das ist normal — iptables-Regeln sind flüchtig. Der **Service** erstellt die Chain beim Start automatisch neu. Aktive Sperren aus der SQLite-Datenbank werden aber nicht automatisch als iptables-Regeln wiederhergestellt.
**Optionen:**
- `iptables-persistent` installieren (`apt install iptables-persistent`)
@@ -240,6 +240,7 @@ sudo bash install.sh update
- Konfiguration wird als `adguard-shield.conf.old` gesichert
- Neue Konfigurationsparameter werden automatisch zur bestehenden Konfig ergänzt
- Bestehende Einstellungen bleiben erhalten
- Bestehende Flat-File-Daten werden einmalig in die SQLite-Datenbank migriert (mit Fortschrittsanzeige)
- Service wird per `daemon-reload` neu geladen und automatisch neu gestartet
## Deinstallation
@@ -281,5 +282,6 @@ Folgende Pakete werden für den Betrieb benötigt und bei der Installation autom
| `iptables` | Firewall-Regeln (IPv4 + IPv6) |
| `gawk` | Textverarbeitung in Scripts |
| `systemd` | Service-Management und Autostart |
| `sqlite3` | Datenbank für State-Management, Ban-History und Offense-Tracking |
Diese werden bei `sudo bash install.sh install` automatisch geprüft und bei Bedarf über den Paketmanager (`apt`, `dnf`, `yum`, `pacman`) nachinstalliert.

View File

@@ -31,13 +31,14 @@ sudo bash install.sh update
Das Update-Script macht automatisch folgendes:
1. **Abhängigkeiten prüfen** — Fehlende Pakete werden nachinstalliert
1. **Abhängigkeiten prüfen** — Fehlende Pakete (inkl. `sqlite3`) werden nachinstalliert
2. **Scripts aktualisieren** — Alle `.sh`-Dateien werden nach `/opt/adguard-shield/` kopiert
3. **Konfigurations-Migration** — Neue Parameter werden automatisch zur bestehenden Konfiguration hinzugefügt, bestehende Einstellungen bleiben **unverändert**
4. **Backup erstellen** — Die alte Konfiguration wird als `adguard-shield.conf.old` gesichert
5. **Service aktualisieren** — Die systemd Service-Datei und Watchdog-Dateien werden aktualisiert und `daemon-reload` ausgeführt
6. **Watchdog aktivieren** — Der Watchdog-Timer wird automatisch aktiviert (falls noch nicht aktiv)
7. **Service neustarten** — Der Service wird automatisch neu gestartet (falls er vorher lief)
5. **Datenbank-Migration (in der v1.0.0)** — Bestehende Flat-File-Daten (`.ban`, `.offenses`, Ban-History-Log) werden einmalig in die SQLite-Datenbank migriert. Die alten Dateien werden als Backup gesichert. Der Fortschritt und das Ergebnis werden im Terminal angezeigt.
6. **Service aktualisieren** — Die systemd Service-Datei und Watchdog-Dateien werden aktualisiert und `daemon-reload` ausgeführt
7. **Watchdog aktivieren** — Der Watchdog-Timer wird automatisch aktiviert (falls noch nicht aktiv)
8. **Service neustarten** — Der Service wird automatisch neu gestartet (falls er vorher lief)
### 3. Neue Parameter prüfen (optional)