docs: create betrieb/moderation-content-scanning

This commit is contained in:
Administrator
2026-08-13 18:04:42 +00:00
committed by ThreadNet Wiki
parent aeaebb936b
commit 6e23dc2205
+108
View File
@@ -0,0 +1,108 @@
---
title: Moderation & Content-Scanning
description: Draupnir-Moderationsbot + ClamAV
published: true
date: 2026-08-13T18:04:36.999Z
tags:
editor: markdown
dateCreated: 2026-08-13T18:04:36.999Z
---
**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)
Community-Nachfolger von Mjolnir. Läuft als eigener Bot-Account (`@draupnir:axion1337.chat`),
verwaltet Ban-Listen ("Policy Rooms") und setzt sie in geschützten Räumen durch.
### Bot-Account & Zugriff (Bootstrap)
Authentifizierung läuft über MAS (kein klassisches `registration_shared_secret`):
```bash
kubectl exec -it -n matrix deploy/matrix-stack-matrix-authentication-service -- \
mas-cli manage register-user draupnir --yes
kubectl exec -it -n matrix deploy/matrix-stack-matrix-authentication-service -- \
mas-cli manage issue-compatibility-token draupnir
```
Token wird manuell per `sops apps/production/draupnir-secret.yaml` eingetragen.
### Stolpersteine (live gefunden)
- `gnuxie/draupnir:v2.9.0` crasht mit `initialManager` ("Can't join remote room..."). Die
automatische Management-Room-Erstellung funktioniert erst ab **v3.1.0** - deployt.
- v3.x braucht ein explizites CLI-Argument statt `NODE_CONFIG_DIR`-Autodiscovery:
`args: ["bot", "--draupnir-config", "/data/config/default.yaml"]`.
- NetworkPolicy: `matrix-stack-synapse` routet über haproxy, dessen Ingress-Policy
standardmäßig nur Traefik erlaubt - eigene `podSelector`-Ausnahme für Draupnir nötig.
### Verschlüsselter Management-Room
Standardmäßig unverschlüsselt. Mit `experimentalRustCrypto: true` (Hersteller-Warnung: "not
considered production safe", in unserem Test aber fehlerfrei) + manuellem Aktivieren der
Raumverschlüsselung in Element (wirkt nicht rückwirkend auf bereits erstellte Räume).
### Befehle (Kurzreferenz)
| Befehl | Zweck |
|--------|-------|
| `status` | Bot-Status |
| `rooms add <room>` | Raum unter Schutz stellen (Voraussetzung für Bans!) |
| `list create <shortcode> <alias>` | Neue Policy-Liste (automatisch beobachtet + geschützt) |
| `ban <user> <liste> <grund>` | 2. Argument = Policy-Liste, NICHT der Ziel-Raum |
| `kick <user> <room> <grund>` | Direkter Kick ohne Listen-Umweg |
| `rules` | Regeln einer Policy-Liste anzeigen |
**Live getestet** (2026-07-29): Testraum geschützt, Policy-Liste angelegt, Testnutzer über
`ban`+Liste erfolgreich entfernt. Kernmechanismus bestätigt funktionsfähig.
## 2. Content Scanner (Issue #19)
**Verworfen**: `matrix-content-scanner-python` ist ein Proxy, den der **Client** explizit
statt der normalen Media-Endpunkte aufrufen muss - weder aktuelles Element Web noch Element X
unterstützen das (geprüft: kein Hook im offenen `element-x-android`-Repo). Element hat echtes
serverseitiges Scanning nur in der kommerziellen Element Pro + ESS Pro-Kombination.
**Umgesetzt**: eigenes, kleines Synapse-Modul (`clamav_spam_checker.py`) nutzt Synapses
echten `check_media_file_for_spam`-Hook - serverseitig, transparent für jeden Client, kein
fertiges Modul dafür existiert (`synapse-http-antispam` schließt genau diesen Callback aus).
ClamAV als eigener Pod, Modul per ConfigMap + `PYTHONPATH` gemounted (kein Custom-Image).
Spricht ClamAVs INSTREAM-Protokoll über **Twisted**-Primitives, nicht `asyncio` - Synapse
läuft auf Twisteds Reactor, ein erster `asyncio`-Versuch schlug live mit
`RuntimeError: no running event loop` fehl (Fail-Open verschleierte das zunächst - EICAR kam
durch). Fail-open bei Scanner-Fehlern bleibt so: ClamAV-Ausfall blockiert nicht alle Uploads.
**Live getestet** (2026-07-29): normale Datei unverschlüsselt → durchgelassen; EICAR
unverschlüsselt → zuverlässig blockiert.
## 3. Client-seitiges Scanning für verschlüsselte Räume (Erweiterung, 2026-07-29)
Synapse hat bei E2EE nie den Schlüssel - nur der **Client** kann Klartext scannen. Neuer
HTTP-Dienst `clamav-http-scanner.py` macht ClamAV für Browser-JS erreichbar
(`https://axion1337.chat/_scan`, Auth via Synapses eigenem `/whoami`, Fail-open). Zwei
Patch-Stellen im `ThreadNet-Web`-Fork:
- **Empfang**: `apps/web/src/utils/DecryptFile.ts` (`decryptFile()`) - einziger Punkt für
alle Anhangstypen.
- **Versand**: `apps/web/src/ContentMessages.ts` (`uploadFile()`) - eine Funktion für alle
Uploads (Datei, Thumbnails, Sprachnachrichten).
**Live getestet**: EICAR in verschlüsseltem Gruppenraum + 1:1-DMs vor Upload blockiert.
Zusätzlich Empfangsseite unabhängig vom Absender bestätigt: EICAR über einen echten,
ungepatchten Client (app.element.io) in denselben Raum geschickt - beim Download im
gepatchten Client greift der Scanner trotzdem.
**Wichtig, korrigiert**: gilt bestätigt für den **Web-Client**. Für **Electron/Desktop**
unklar bzw. nicht automatisch - `apps/desktop` hat zwar einen `webapp-artifact`-Mechanismus,
der den eigenen Fork-Build übernehmen würde, aber keinen laufenden CI-Runner, und der
Build-Job checkt noch das Upstream-Repo aus. Die existierende Desktop-Build (mit der
Discord-Style-Raumliste) kam aus einem manuellen, nicht wiederholten Build. Neues Issue:
[#44](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/44). Element X (Mobile)
komplett unberührt, eigene Codebasis.
Folgeidee (LOW): [Issue #43](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/43)
- Grafana-Dashboard über die bestehenden Loki-Logs für Erkennungen/Scanner-Ausfälle.
Details: [Element-Customization](/betrieb/element-customization) und `docs/deployment-guides/06-moderation-content-scanning.md`.