chore(coturn): automated TURN shared-secret rotation #46
+2
-1
@@ -367,7 +367,8 @@ und [#15](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/15), Det
|
||||
|
||||
### Moderation & Anti-Abuse
|
||||
- [x] **Draupnir Moderationsbot** → [Issue #18](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/18) (2026-07-29, deployed + live getestet)
|
||||
- [ ] **Content Scanner für Media** → [Issue #19](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/19) (geplant, noch nicht umgesetzt - siehe Scoping-Einschränkung im Deployment-Guide)
|
||||
- [x] **Content Scanner für Media** → [Issue #19](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/19) (2026-07-29, eigenes Synapse-Modul + ClamAV, live getestet - schützt nur unverschlüsselte Räume/DMs, siehe Deployment-Guide)
|
||||
- [ ] **Grafana-Dashboard für ClamAV-Erkennungen** → [Issue #43](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/43)
|
||||
|
||||
### Secrets Management
|
||||
- [ ] **External-Secrets Operator vs. SOPS-Setup** → [Issue #20](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/20)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Moderation Bot & Content Scanning
|
||||
|
||||
**Status**: ✅ Draupnir deployed (2026-07-29, Closes Issue #18) | ⏳ Content Scanner geplant, noch nicht umgesetzt (Issue #19)
|
||||
**Konfiguration**: `apps/production/draupnir*.yaml`
|
||||
**Status**: ✅ Draupnir deployed (2026-07-29, Closes Issue #18) | ✅ Content Scanner deployed + live getestet (2026-07-29, Closes Issue #19)
|
||||
**Konfiguration**: `apps/production/draupnir*.yaml`, `apps/production/clamav*.yaml`, `apps/production/clamav_spam_checker.py`
|
||||
|
||||
## 1. Draupnir (Moderationsbot)
|
||||
|
||||
@@ -86,24 +86,47 @@ Alle Befehle im (verschlüsselten) Management-Room, Präfix `!draupnir`:
|
||||
`ban`+Liste erfolgreich aus dem geschützten Raum entfernt. Kernmechanismus bestätigt
|
||||
funktionsfähig.
|
||||
|
||||
## 2. Content Scanner (Issue #19, LOW - noch nicht umgesetzt)
|
||||
## 2. Content Scanner (Issue #19)
|
||||
|
||||
**Wichtige Einschränkung, vorab geklärt**: `matrix-content-scanner-python` ist ein Proxy, den
|
||||
der **Client** explizit statt der normalen Media-Endpunkte aufrufen muss - Synapse selbst
|
||||
leitet nichts automatisch dorthin um. Diese client-seitige Unterstützung existiert nur noch in
|
||||
den veralteten, nicht mehr gepflegten Android/iOS-SDKs. Weder aktuelles Element Web
|
||||
(matrix-js-sdk, was hier läuft) noch Element X unterstützen das. Zusätzlich hat Synapse bei
|
||||
verschlüsselten Anhängen ohnehin nie den Schlüssel - nur ein kooperierender Client kann ihn dem
|
||||
Scanner geben.
|
||||
**Verworfener erster Ansatz**: `matrix-content-scanner-python` ist ein Proxy, den der
|
||||
**Client** explizit statt der normalen Media-Endpunkte aufrufen muss - Synapse selbst leitet
|
||||
nichts automatisch dorthin um. Diese client-seitige Unterstützung existiert nur noch in
|
||||
veralteten, nicht mehr gepflegten Android/iOS-SDKs; weder aktuelles Element Web noch Element X
|
||||
unterstützen das (geprüft: kein `content_scanner`-Hook im offenen `element-x-android`-Repo).
|
||||
Element selbst hat echtes serverseitiges Scanning - aber nur in der kommerziellen
|
||||
**Element Pro** + **ESS Pro**-Kombination, nicht in unserer offenen ESS-Community-Installation.
|
||||
|
||||
**Konsequenz**: Falls umgesetzt, schützt der Scanner **keinen echten Nutzer-Traffic
|
||||
automatisch** - nur manuelle/skriptgesteuerte Admin-Prüfungen sind möglich (z.B.
|
||||
`kubectl port-forward` + `curl` nach manuellem Upload). Eine echte, transparente Absicherung
|
||||
bräuchte entweder einen Client-Fork oder ein eigenes Synapse-`check_media_file_for_spam`-Modul
|
||||
(deutlich größerer, separater Aufwand).
|
||||
**Tatsächlich umgesetzt**: ein eigenes, kleines Synapse-Modul (`clamav_spam_checker.py`),
|
||||
das Synapses echten, dokumentierten Hook `check_media_file_for_spam` nutzt - läuft
|
||||
**serverseitig**, transparent für jeden Client, ganz ohne Mitwirkung des Clients. Kein
|
||||
fertiges Modul dafür existiert (auch das verbreitete `synapse-http-antispam`-Brückenmodul
|
||||
schließt genau diesen Callback explizit aus), daher selbst geschrieben.
|
||||
|
||||
Geplante Komponenten bei Umsetzung: ClamAV (`clamav/clamav:1.5.3`, eigene PVC für die
|
||||
Signatur-DB) + `vectorim/matrix-content-scanner` (Config-Keys `scan.script`/
|
||||
`scan.temp_directory`/`crypto.request_secret_path` - aus dem echten `config.sample.yaml`
|
||||
bestätigt). Kein Ingress, keine NetworkPolicy-Ausnahme nötig, da nichts im Cluster oder von
|
||||
außen automatisch darauf zugreift.
|
||||
**Architektur**:
|
||||
- ClamAV (`clamav/clamav:1.5.3`) läuft als eigener Pod, PVC für die Signatur-Datenbank.
|
||||
- Das Modul (`apps/production/clamav_spam_checker.py`) wird per ConfigMap gemounted und über
|
||||
`PYTHONPATH` importierbar gemacht (`synapse.extraVolumes`/`extraVolumeMounts`/`extraEnv` -
|
||||
kein Custom-Synapse-Image nötig).
|
||||
- Spricht ClamAVs natives INSTREAM-Protokoll direkt über **Twisted**-Netzwerk-Primitives
|
||||
(`HostnameEndpoint`/`connectProtocol`), nicht über `asyncio` - Synapse läuft auf Twisteds
|
||||
Reactor, nicht auf einer laufenden asyncio-Event-Loop. Ein erster Versuch mit
|
||||
`asyncio.open_connection`/`wait_for` schlug live mit `RuntimeError: no running event loop`
|
||||
fehl und fiel dadurch (durch das eigene Fail-Open-Verhalten) unbemerkt auf "durchlassen"
|
||||
zurück - die EICAR-Testdatei wurde beim ersten Versuch nicht erkannt. Nach Umstellung auf
|
||||
Twisted-Primitives funktioniert es sauber.
|
||||
- **Fail-open** bei Scanner-Fehlern (Verbindungsfehler/Timeout → Datei wird durchgelassen,
|
||||
laut geloggt) - ein ClamAV-Ausfall soll nicht alle Uploads auf dem Homeserver blockieren.
|
||||
|
||||
**Live getestet und bestätigt** (2026-07-29):
|
||||
- Normale Datei in unverschlüsseltem Raum → läuft durch (kein Regressionsschaden).
|
||||
- EICAR-Testdatei in unverschlüsseltem Raum → zuverlässig blockiert
|
||||
(`ClamAV rejected an upload: Eicar-Test-Signature`, Client bekommt `400 Bad content` -
|
||||
Synapse gibt bewusst keine Begründung an den Client zurück, nur in den Server-Logs sichtbar).
|
||||
- EICAR-Testdatei in verschlüsseltem Raum/DM → **läuft durch** - erwartete, strukturelle
|
||||
Grenze: Synapse hat bei E2EE nie den Entschlüsselungsschlüssel, sieht nur Ciphertext. Nur
|
||||
ein kooperierender Client könnte das lösen (siehe oben, existiert nicht offen verfügbar).
|
||||
|
||||
**Bekannte Deckungslücke**: schützt nur unverschlüsselte Räume/DMs (viele öffentliche/
|
||||
föderierte Räume) - keine Warnung/Kennzeichnung für Nutzer in verschlüsselten Räumen, dass
|
||||
dort kein Scanning stattfindet. Folgeidee (Issue #43, LOW): Grafana-Dashboard über die
|
||||
bestehenden Loki-Logs, um Erkennungen/Scanner-Ausfälle sichtbar zu machen.
|
||||
|
||||
@@ -13,7 +13,7 @@ Die Implementierungen wurden in dieser Reihenfolge durchgeführt. Für neue Setu
|
||||
| 3 | Monitoring mit Alloy/Prometheus/Loki | `03-monitoring-integration.md` | ✅ Deployed | lokal (10.0.0.3) |
|
||||
| 4 | Element Web Anpassung & Desktop-Apps | `04-element-customization.md` | ✅ Deployed | `axion1337.chat` |
|
||||
| 5 | Room Policies (Retention, Publication, Auto-Join) | `05-room-policies.md` | ✅ Deployed | Matrix Synapse |
|
||||
| 6 | Moderationsbot (Draupnir) & Content Scanning | `06-moderation-content-scanning.md` | ✅ Draupnir deployed / ⏳ Scanner geplant | Matrix Synapse |
|
||||
| 6 | Moderationsbot (Draupnir) & Content Scanning | `06-moderation-content-scanning.md` | ✅ Deployed | Matrix Synapse |
|
||||
|
||||
---
|
||||
|
||||
@@ -87,7 +87,7 @@ Custom Themes, Desktop-Setup-Scripts, Element Admin.
|
||||
Message Retention, Room Publication, Auto-Join Policies.
|
||||
|
||||
### [06-moderation-content-scanning.md](06-moderation-content-scanning.md)
|
||||
Draupnir Moderationsbot (Bans, Policy-Listen), Content Scanner (geplant, Issue #19).
|
||||
Draupnir Moderationsbot (Bans, Policy-Listen), Content Scanner via eigenes Synapse-Modul (Issue #19) - beide live getestet.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user