docs(adr): ADR-0021 - federation closed, and why the tighter option was wrong
sorb chose C, fully disabling federation at the edge. Building it showed that would have killed group calls: lk-jwt-service verifies OpenID tokens through /_matrix/federation/v1/openid/userinfo and reaches it over the public name, so a path block on /_matrix/federation is the mrtc outage again with a different cause. C was dropped and B implemented. The ADR records the measurement the decision rests on - zero destinations, zero remote users, zero rooms with outside participation in four months - and the trap, so nobody completes C later as a quick follow-up. Doing that safely means binding the auth service to Synapse in-cluster first, which is its own undertaking with a call acceptance. Also recorded because it nearly slipped through: Flux applied the ConfigMap while Synapse kept running its old config from 2026-08-01. The config is rendered at pod start, so the change was inert until a restart - the same class as #0044. Verified afterwards inside the running process rather than in the ConfigMap, with the client API and the OpenID endpoint still answering.
This commit is contained in:
@@ -75,7 +75,7 @@ Verteilung: M1 15 · M2 17 · M3 4 · M4 11 · M5 15
|
|||||||
|
|
||||||
_none active_
|
_none active_
|
||||||
|
|
||||||
## ADRs (20)
|
## ADRs (21)
|
||||||
|
|
||||||
| ADR | Status | Title |
|
| 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 |
|
| [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 |
|
| [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 |
|
| [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)
|
## Open AARs (0)
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -79,3 +79,53 @@ nur, ob das Raumverzeichnis über Föderation sichtbar ist, und ist unabhängig
|
|||||||
Grundsatzfrage.
|
Grundsatzfrage.
|
||||||
|
|
||||||
**Entscheidung sorb steht aus.**
|
**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.
|
||||||
|
|||||||
Reference in New Issue
Block a user