Decision sorb. Both questions are answered: there is no rule for 9090 or 3100 on CFGMON and Hetzner denies inbound by default, so Weg A never had anything to restrict; and the state now has ports-soll.md plus pruefe-ports.sh holding it. The reservation is written down rather than glossed over: from sorb's network the must-be-shut half cannot be proven, because the site coupling grants privileged access there. The script says so instead of reporting false green, and an external run - judged excessive for routine use - is named for the case that warrants it. Whether the GAME push survives the vSwitch move belongs to #0002. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
182 lines
9.7 KiB
Markdown
182 lines
9.7 KiB
Markdown
---
|
||
type: issue
|
||
id: "0008"
|
||
status: done
|
||
created: 2026-08-01
|
||
milestone: M1
|
||
priority: medium
|
||
host: cfgmon
|
||
area: security
|
||
gitlab_iid: "8"
|
||
related: []
|
||
---
|
||
# CFGMON-03: Prometheus-Remote-Write und Loki öffentlich ohne Auth — Weg A, nachgelagerte Prüfung
|
||
|
||
> Import aus [management#8](https://git.lab/axion1337.chat/management/-/issues/8) (2026-08-11). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei (ADR-0012).
|
||
|
||
Prometheus 9090 (`--web.enable-remote-write-receiver`) und Loki 3100 sind
|
||
öffentlich ohne Auth — Fremde könnten Metriken einspeisen und Daten/Logs auslesen.
|
||
Absender-Inventur: k3s/Matrix pusht längst privat (10.0.0.3); öffentlich bräuchte die
|
||
Ports nur der GAME-Host (→ GAME-01).
|
||
|
||
**Weg A beschlossen (sorb 2026-08-01):** Hetzner-Cloud-Firewall — 9090/3100 nur für
|
||
bekannte Absender. **Nachgelagerte Prüfung nötig:** Beim Baseline-Check vom Mac waren
|
||
9090/3100 bereits zu, OHNE dass der Console-Klick gemacht war — die reale
|
||
Firewall-Lage weicht vom Backlog-Bild ab. Vor dem Abhaken **gemeinsam in die
|
||
Hetzner-Console schauen**: welche Regeln existieren wirklich, und läuft der GAME-Push
|
||
(nach GAME-01) noch durch? Weg B (GAME in den vSwitch, Ports ganz zu) bleibt die
|
||
saubere Endstufe; Weg C (BasicAuth via Traefik) verworfen.
|
||
|
||
Quelle: [hosts/cfgmon.md](https://git.lab/axion1337.chat/management/-/blob/main/hosts/cfgmon.md)
|
||
|
||
---
|
||
*Übernommen aus dem Backlogs-Markdown beim Framework-Umbau 2026-08-01 (voller Wortlaut: Git-Historie der Datei).*
|
||
|
||
## Nachgeprüft 2026-08-15 — akute Exposition besteht nicht
|
||
|
||
Messung vom Mac gegen die öffentliche CFGMON-IP: **9090 (Prometheus remote-write) und 3100
|
||
(Loki) antworten nicht**, während `:443` sofort antwortet (Gegenprobe, Messmethode also
|
||
gültig). Das bestätigt die im Issue vermerkte Beobachtung: die Ports sind zu, **ohne** dass
|
||
der Console-Klick je gemacht wurde.
|
||
|
||
Damit verschiebt sich der Charakter des Issues: Es geht **nicht mehr um akutes Risiko**,
|
||
sondern darum, dass der Ist-Zustand nicht bewusst hergestellt und nicht dokumentiert ist —
|
||
was heute zufällig zu ist, kann bei der nächsten Änderung unbemerkt aufgehen. Zu klären
|
||
bleibt: welche Regeln greifen tatsächlich, und trägt das den GAME-Push (#0002) nach dessen
|
||
vSwitch-Umzug noch?
|
||
|
||
## Wächter gebaut 2026-08-19 — der Ist-Zustand hat jetzt eine Instanz, die ihn hält
|
||
|
||
Aus dem Befund vom 15.08. („zu, aber nicht bewusst hergestellt und nicht
|
||
dokumentiert") folgt genau ein wirksamer Schritt, und er ist getan:
|
||
`notfallhandbuch:pruefe-ports.sh` plus `ports-soll.md`, nach dem Muster von
|
||
`pruefe-dns.sh`.
|
||
|
||
**Gemessen, nicht abgeleitet** (2026-08-19, von sorbs Mac):
|
||
|
||
| Host | offen | zu |
|
||
|---|---|---|
|
||
| Matrix `49.13.132.245` | 80, 443, 3478, 5349, 30001, 2248 | 22 |
|
||
| CFGMON `188.245.193.243` | 80, 443 | **9090, 3100**, 22 |
|
||
|
||
Das Skript prüft **beide Richtungen** — eine reine Erreichbarkeitsprüfung würde eine
|
||
öffentlich stehende Telemetrie nie bemerken. Vor und nach jeder Firewall-Änderung
|
||
laufen lassen; damit ist auch die Frage aus dem Issue beantwortbar, ob der GAME-Push
|
||
(#0002) nach dem vSwitch-Umzug noch trägt: einmal vorher, einmal nachher.
|
||
|
||
**Die Gegenprobe ist der Kern, nicht die Zierde.** In einem Netz, das ausgehende
|
||
Verbindungen filtert, meldet jede Portprüfung „alles zu" — was wie ein perfektes
|
||
Ergebnis aussieht. Beim Bau real passiert: Die erste Fassung nutzte `/dev/tcp`, das
|
||
die zsh nicht kennt, und meldete **jeden** Port als geschlossen, 443 eingeschlossen.
|
||
Das Skript bricht deshalb mit Exit 2 ab, wenn ein bekannt offener Port nicht antwortet.
|
||
|
||
**UDP bleibt bewusst außen vor** (TURN 3478, SFU 30002): Ohne Antwort sind
|
||
„gefiltert" und „offen, aber still" nicht zu trennen. Diese Strecken belegt nur ein
|
||
echter Gruppen-Call.
|
||
|
||
**Weiterhin offen — der Teil, der sorb braucht:** der gemeinsame Blick in die
|
||
Hetzner-Console. Das Skript sagt, *was* von außen erreichbar ist; welche Regeln das
|
||
bewirken und ob sie bewusst so stehen, sagt nur die Console. Erst danach ist das
|
||
Issue erledigt.
|
||
|
||
## Console-Einblick 2026-08-19 — Matrix-Host gesehen, CFGMON weiterhin nicht
|
||
|
||
sorb hat die Hetzner-Console gezeigt: **`fw-matrix-cx42`, 15 Regeln, vollständig
|
||
angewandt.** Das ist der **Matrix-Host**, nicht CFGMON — die Frage dieses Issues
|
||
(welche Regel hält 9090/3100 auf CFGMON zu?) ist damit **noch offen**. Gemessen sind
|
||
beide Ports zu; *warum*, weiß weiterhin niemand.
|
||
|
||
Der Einblick war trotzdem wertvoll, in zwei Richtungen.
|
||
|
||
**Sauber gelöst:** SSH (2248) und die Kubernetes-API (6443) sind quellbeschränkt auf
|
||
sorbs Anschluss (`178.25.213.70`, `2a02:8108:0:2f::/64`), nicht für alle offen. Das hat
|
||
auch einen Fehler in `pruefe-ports.sh` aufgedeckt: Die Liste führte 2248 schlicht als
|
||
„offen", womit das Skript aus jedem anderen Netz zwei Falschbefunde gemeldet hätte.
|
||
Behoben — beide gelten jetzt als `quellbeschraenkt` und werden berichtet, aber nicht
|
||
gewertet.
|
||
|
||
**Die Firewall ist deutlich weiter offen als die Plattform.** Von außen gemessen
|
||
antwortet auf diesen Regeln nichts:
|
||
|
||
| Regel | Befund |
|
||
|---|---|
|
||
| `smtp` TCP **587 eingehend**, Any | **Vermutlich versehentlich.** Der Host verschickt Mail *ausgehend*; eingehende Regeln helfen dabei nicht (Hetzner filtert nur eingehend). Der Deployment-Guide dokumentiert genau dieses Debugging („465 blockiert, 587 geht") — die Regel sieht nach dessen Rest aus. |
|
||
| `mRTC SFU muxed` UDP **30000–65535** | ~35.500 Ports für einen benötigten (30002). |
|
||
| `mRTC SFU TCP` TCP **30000–60000** | ~30.000 Ports für einen benötigten (30001). |
|
||
| `RTC SFU 1` 6789, `RTC SFU 2` 7880, `mRTC Auth` 8080, je Any | nichts lauscht; die Dienste laufen über den Ingress auf 443. |
|
||
|
||
Kein akutes Risiko — aber eine unnötig breite *erklärte* Angriffsfläche: Sobald dort je
|
||
etwas horcht, ist es sofort weltweit erreichbar, ohne dass jemand eine Regel anfassen
|
||
müsste. Festgehalten in `notfallhandbuch:ports-soll.md`.
|
||
|
||
**Zum Abschluss dieses Issues fehlt weiterhin:** der Blick auf die **CFGMON**-Firewall.
|
||
|
||
## Frage beantwortet 2026-08-19 — und ein größerer Fund daneben
|
||
|
||
sorb hat `fw-matrix-cx23` gezeigt, die **CFGMON**-Firewall. Die Antwort auf die Frage
|
||
dieses Issues ist einfach: **Es gibt für 9090 und 3100 gar keine Regel.**
|
||
Hetzner-Firewalls sind eingehend Default-Deny — die Ports sind also nicht „zugemacht
|
||
worden", sie waren **nie offen**. Das deckt sich exakt mit der Beobachtung vom
|
||
2026-08-01, dass sie zu waren, ohne dass jemand den Console-Klick gemacht hatte.
|
||
|
||
„Weg A" (Firewall-Regel, die 9090/3100 auf bekannte Absender beschränkt) ist damit
|
||
**gegenstandslos für den öffentlichen Weg**. Die privaten Absender (k3s/Matrix über das
|
||
Hetzner-Netz) laufen an der Cloud-Firewall vorbei, die nur öffentlichen Verkehr filtert.
|
||
|
||
Sauber gelöst ist der Rest von CFGMON: SSH (2248), Grafana (3000), Coolify (9001,
|
||
8000–8001) und WireGuard (51841) sind quellbeschränkt auf sorbs Anschluss; cadvisor
|
||
(8080) und node-exporter (9100) nur für `157.90.155.206`.
|
||
|
||
### ~~Offener rekursiver DNS-Resolver auf CFGMON~~ — WIDERRUFEN am selben Tag
|
||
|
||
**Der Befund war falsch.** Ich hatte gemeldet, `188.245.193.243:53` löse für jeden im
|
||
Internet rekursiv auf, samt Amplifikations-Rechnung. sorbs Rückfrage („dir ist schon
|
||
klar, dass beide Netze gerade per VPN verbunden sind?") hat es aufgeklärt.
|
||
|
||
Nachgemessen **aus dem Cluster** (Hetzner-Egress, weder Lab noch Standortkopplung):
|
||
|
||
| Port | von sorbs Mac | aus dem Cluster |
|
||
|---|---|---|
|
||
| 443 (Gegenprobe) | offen | **offen** — Methode gültig |
|
||
| 53 | offen, rekursiv | **zu** |
|
||
| 9001 (nur sorbs Anschluss) | offen | **zu** |
|
||
|
||
Öffentlich ist 53 also **geschlossen**. Die Firewall-Regel (Quelle `10.58.73.17` =
|
||
Dokploy/git) ist in Ordnung; Verkehr über die Standortkopplung filtert die
|
||
Cloud-Firewall nicht, deshalb antwortet der Dienst aus dem Lab. Genau so gedacht.
|
||
|
||
**Die eigentliche Lehre betrifft mein Werkzeug, nicht die Infrastruktur.** Die
|
||
Gegenprobe in `pruefe-ports.sh` beweist, dass die *Messmethode* funktioniert — sie
|
||
beweist **nicht**, dass man von *außen* misst. Zwei verschiedene Fragen, und ich hatte
|
||
nur eine beantwortet. Das Skript führt jetzt vor allem anderen eine **Standort-Probe**
|
||
aus (ein Port, den die Firewall nur für sorbs Anschluss freigibt): Antwortet er, werden
|
||
alle „soll zu"-Prüfungen berichtet, aber **nicht gewertet**. Für diese Hälfte muss das
|
||
Skript aus einem fremden Netz laufen.
|
||
|
||
Zweiter Fehlalarm binnen zweier Tage aus derselben Wurzel — erst `/dev/tcp` in der zsh,
|
||
das jeden Port als geschlossen meldete, jetzt der Standort. Beide Male sah das Ergebnis
|
||
plausibel aus.
|
||
|
||
## Erledigt 2026-08-19 — vorbehaltlich (Entscheidung sorb)
|
||
|
||
Beide Fragen des Issues sind beantwortet:
|
||
|
||
**„Welche Regeln greifen tatsächlich?"** — Für 9090 und 3100 gibt es auf CFGMON **keine
|
||
Regel**. Hetzner filtert eingehend Default-Deny; die Ports waren nie offen. „Weg A"
|
||
(Freigabe auf bekannte Absender beschränken) ist damit gegenstandslos, es gab nie etwas
|
||
zu beschränken. Der Rest der Firewall ist quellbeschränkt und sauber.
|
||
|
||
**„Ist der Zustand dokumentiert und gehalten?"** — Ja: `notfallhandbuch:ports-soll.md`
|
||
plus `pruefe-ports.sh`, beide Richtungen prüfend, mit Gegenprobe und Standort-Probe.
|
||
|
||
**Der Vorbehalt:** Die „muss zu sein"-Hälfte ist aus sorbs Netz **nicht beweisbar** —
|
||
dort besteht über die Standortkopplung privilegierter Zugang. Das Skript weist das
|
||
ehrlich aus, statt falsches Grün zu liefern. Ein Lauf aus einem fremden Netz würde die
|
||
Lücke schließen; sorb hat das am 2026-08-19 als übertrieben verworfen, und das ist
|
||
vertretbar: Gemessen ist der Zustand gut, die Regeln sind gesehen, und für den einen
|
||
Fall, der wirklich zählt — eine Firewall-Änderung an einem „muss zu"-Port — steht der
|
||
Hinweis in `ports-soll.md`.
|
||
|
||
**Offen bleibt an anderer Stelle:** Ob der GAME-Push nach dem vSwitch-Umzug noch trägt,
|
||
entscheidet sich in **#0002**, nicht hier.
|