diff --git a/STATUS.md b/STATUS.md index deec6e4..88ef143 100644 --- a/STATUS.md +++ b/STATUS.md @@ -75,7 +75,7 @@ Verteilung: M1 15 · M2 17 · M3 4 · M4 11 · M5 15 _none active_ -## ADRs (20) +## ADRs (21) | ADR | Status | Title | |---|---|---| @@ -99,6 +99,7 @@ _none active_ | [0018](docs/adr/0018-ki-geraeuschunterdrueckung-clientseitig-opt-in.md) | accepted | 0018 — KI-Geräuschunterdrückung in threadnet-call: client-seitig, opt-in, selbst ausgeliefert | | [0019](docs/adr/0019-komponenten-issues-adoptiert.md) | accepted | ADR-0019: Komponenten-Issues in docs/issues/ adoptiert — eine Nummernwelt für die Gruppe | | [0020](docs/adr/0020-bekannte-befunde-quittieren.md) | accepted | ADR-0020: Bekannte Befunde werden quittiert, damit Rot wieder etwas bedeutet | +| [0021](docs/adr/0021-foederation-geschlossen.md) | accepted | ADR-0021: Föderation wird geschlossen — leere Whitelist statt offener Tür | ## Open AARs (0) diff --git a/docs/adr/0021-foederation-geschlossen.md b/docs/adr/0021-foederation-geschlossen.md new file mode 100644 index 0000000..bec7779 --- /dev/null +++ b/docs/adr/0021-foederation-geschlossen.md @@ -0,0 +1,81 @@ +--- +type: adr +id: "0021" +status: accepted +date: 2026-08-19 +supersedes: null +superseded_by: null +related: + - "docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md" + - "docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md" +--- + +# ADR-0021: Föderation wird geschlossen — leere Whitelist statt offener Tür + +## Kontext + +Die Frage stand seit dem 2026-07-28 offen, weil niemand wusste, was eine Schließung +kosten würde. Am 2026-08-19 wurde sie gemessen statt geschätzt. + +**Föderation war offen und öffentlich erreichbar.** In `synapse-values.yaml` stand zu +Föderation nichts, es galten die Synapse-Vorgaben; `/_matrix/federation/v1/version` und +`/_matrix/key/v2/server` antworteten von außen mit HTTP 200. Dass Port 8448 zu ist, +änderte daran nichts: Die Delegation in `/.well-known/matrix/server` führt die +Föderation über `matrix.axion1337.chat:443`, denselben Port wie den Client-Verkehr. + +**Benutzt wurde sie nie.** Über die gesamte Betriebszeit seit dem 2026-04-21, aus der +Synapse-Datenbank: **0** Einträge in `destinations`, **0** je erfolgreich kontaktierte +Server, **0** fremde Nutzer in den 31 eigenen Räumen, **0** Räume mit fremder +Beteiligung. Nicht „wenig", sondern null. + +Damit ist der Handel nicht „Reichweite gegen Sicherheit", sondern **eine ungenutzte +Fähigkeit gegen die größte fremdzugewandte Angriffsfläche, die Synapse hat** — und +historisch die, in der seine CVEs sitzen. + +## Optionen + +**A: offen lassen.** Kein Aufwand; dauerhaft Angriffsfläche für null nachgewiesenen +Bedarf. + +**B: `federation_domain_whitelist: []`.** Föderation nur mit ausdrücklich genannten +Servern, leer also mit keinem. Eine Zeile, versioniert, in Minuten umkehrbar. +Die Endpunkte antworten weiterhin — der Server wird unbeteiligt, nicht unsichtbar. + +**C: Föderations-Endpunkte am Rand sperren.** Zunächst als „kleinste Fläche" gewählt, +dann **verworfen** — beim Umsetzen zeigte sich, dass es die Gruppen-Calls zerstört +hätte (siehe unten). + +## Entscheidung + +**Option B.** `federation_domain_whitelist: []` in +`gitops:apps/production/custom-configs/synapse-values.yaml`. + +## Warum C verworfen wurde — der Teil, der nicht offensichtlich ist + +Der MatrixRTC-Authorisation-Service (`lk-jwt-service`) prüft OpenID-Tokens über +**`/_matrix/federation/v1/openid/userinfo`** — einen Föderations-Pfad. Und er ruft ihn +über den **öffentlichen** Namen auf: Das Deployment trägt keine `hostAliases` und +`dnsPolicy: ClusterFirst`, `matrix.axion1337.chat` löst also auf die öffentliche IP auf +und der Verkehr läuft über Traefik. + +Wer `/_matrix/federation/` am Ingress sperrt, kappt damit die Token-Prüfung für +Gruppen-Calls — **derselbe Ausfall wie beim gelöschten `mrtc`-Record, nur mit anderer +Ursache.** Ein Pfad-Block sieht dabei korrekter aus als die Whitelist, weshalb dieser +Zusammenhang im Konfigurations-Kommentar festgehalten ist und nicht nur hier. + +Synapse bedient diesen Endpunkt ohne X-Matrix-Signatur (`REQUIRE_AUTH = False`); die +Whitelist greift dort also nicht und darf es auch nicht. + +## Konsequenzen + +- Fremde Server können weder beitreten noch Ereignisse einliefern. Bestehende Räume und + Nutzer sind nicht betroffen — es gab keine fremde Beteiligung, die enden könnte. +- **Die Fähigkeit ist eine Zeile entfernt**, nicht verloren: Ein Domain-Eintrag öffnet + gezielt für einen Partner. Das war der Grund, B gegenüber einem harten Rückbau + vorzuziehen. +- Die Endpunkte antworten weiterhin von außen. Wer das ändern will, muss **zuerst** den + Auth-Service clusterintern an Synapse binden — sonst siehe oben. Das ist ein eigenes + Vorhaben mit Call-Abnahme, kein Nebenschritt. +- Eine Port-Sperre bei Hetzner kann diese Trennung **nicht** leisten: Föderation und + Client-Verkehr teilen sich 443. Die Konfiguration ist die einzige Stelle, an der sie + überhaupt trennbar sind. diff --git a/docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md b/docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md index e8d09d5..a7d929a 100644 --- a/docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md +++ b/docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md @@ -79,3 +79,53 @@ nur, ob das Raumverzeichnis über Föderation sichtbar ist, und ist unabhängig Grundsatzfrage. **Entscheidung sorb steht aus.** + +## Entscheidung und Umsetzung 2026-08-19 + +**sorb: erst C, dann C verworfen — B umgesetzt.** Beim Bauen von C zeigte sich, dass +ein Pfad-Block die Gruppen-Calls zerstört hätte: `lk-jwt-service` prüft OpenID-Tokens +über `/_matrix/federation/v1/openid/userinfo` und ruft ihn über den **öffentlichen** +Namen auf (keine `hostAliases`, `dnsPolicy: ClusterFirst`), also über Traefik. Ein +Block auf `/_matrix/federation/` hätte denselben Ausfall erzeugt wie der gelöschte +`mrtc`-Record. Festgehalten als [ADR-0021](../adr/0021-foederation-geschlossen.md), +inklusive der Begründung, warum C nicht nachträglich „noch schnell" nachgeholt werden +sollte. + +`federation_domain_whitelist: []` steht in +`gitops:apps/production/custom-configs/synapse-values.yaml` (Commit `3935f35`). + +**Zwei Fallen beim Umsetzen, beide vor dem Ausrollen bemerkt:** + +1. Der erste Einschub **zerschnitt den `auto_join`-Block** — `auto_join_rooms_for_guests` + landete unter `federation`. Nach dem Zusammenführen der Fragmente funktional + identisch, zu lesen falsch; korrigiert, der Diff ist jetzt 20 Zeilen Zugewinn und + nichts Verschobenes. +2. **Flux hat angewandt, Synapse lief weiter mit der alten Konfiguration.** Die + ConfigMap trug die Zeile, der laufende Pod nicht — er stammte vom 2026-08-01. Die + Konfiguration wird beim Pod-Start gerendert; ohne Neustart ist die Änderung + wirkungslos. Dieselbe Klasse wie #0044. Neustart per + `rollout restart statefulset/matrix-stack-synapse-main` angestoßen. + +**Zur Hetzner-Port-Sperre:** Sie kann diese Trennung nicht leisten. 8448 ist bereits zu, +und die Delegation führt die Föderation über **443** — denselben Port wie alle Clients. +Die Synapse-Konfiguration ist die einzige Stelle, an der Föderation und Client-Verkehr +überhaupt trennbar sind. + +### Abnahme nach dem Neustart (2026-08-19, Synapse-Start 11:13 UTC) + +| Prüfung | Ergebnis | +|---|---| +| `federation_domain_whitelist: []` **im laufenden Prozess** (nicht nur in der ConfigMap) | ✅ vorhanden | +| `/_matrix/federation/v1/openid/userinfo` — die Element-Call-Abhängigkeit | ✅ HTTP 401 (bedient, verlangt Token) | +| `/_matrix/client/versions` — Client-Verkehr | ✅ HTTP 200 | +| `/_matrix/federation/v1/version` | HTTP 200 — **erwartet** | + +Der letzte Punkt ist kein Mangel, sondern die bewusste Grenze von Option B: Die +Endpunkte antworten weiterhin, der Server ist **unbeteiligt, nicht unsichtbar**. Was +sich geändert hat, ist nicht die Sichtbarkeit, sondern dass Synapse mit keinem fremden +Server mehr Ereignisse austauscht. + +**Noch offen: die Abnahme im echten Gruppen-Call.** `curl` belegt, dass der +OpenID-Endpunkt antwortet — nicht, dass die vollständige Token-Prüfung durchläuft. Für +Änderungen im Call-Pfad gilt hier die Regel aus #0054: Abnahme im echten Call ist +Rollout-Voraussetzung, nicht Nacharbeit.