hermes-erkenntnisse/netzwerk/2026-07-20-VM302-Netzwerk-Analyse.md

170 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# VM302 Netzwerk-Analyse & Optimierung — 2026-07-20
Vollständige Untersuchung der Latenz Deutschland ↔ Kansas City (VM302, A40-Workstation)
sowie zweier kritischer Sicherheits-/Performance-Befunde.
## TL;DR
- **Routing über Relays bringt NICHTS** — der direkte Pfad ist bereits physikalisch optimal (3 Beweise)
- **Der echte Gewinn lag auf der Maschine:** RSC abschalten = 7 ms, mehr als jedes Gateway geboten hätte
- **VM302 stand ungeschützt im Internet** (ComfyUI/Ollama ohne Auth) — geschlossen
- **Tailscale lief über Relay statt direkt** — Port-Forward-Fix: 162 → 127 ms, Jitter 40 → 0,8 ms
## 1. Sicherheitslücke (kritisch)
**Befund:** VM302s Windows-Firewall-Profil „Private" war **deaktiviert**, und die öffentliche NIC lag in genau diesem Profil.
Folge: ComfyUI (:8188), Studio (:8502), Ollama (:11434), LiteLLM (:4000) waren **unauthentifiziert aus dem Internet erreichbar**.
ComfyUI erlaubt Datei-Zugriff und via Custom-Nodes faktisch Code-Ausführung → A40 und System offen für jeden.
**Fix — nur VM-Ebene filtern, Hosts offen lassen:**
```
/etc/pve/firewall/cluster.fw enable: 1, policy_in: ACCEPT # Subsystem an, Default offen
/etc/pve/nodes/<node>/host.fw enable: 1 # erbt ACCEPT = ungefiltert
/etc/pve/firewall/302.fw policy_in: DROP + Ausnahmen # NUR hier wird gefiltert
qm set 302 --net1 ...,firewall=1 # nur die öffentliche NIC
```
Ausnahmen in 302.fw: 3389 (RDP), 47984-48010 (Moonlight), 41641 (Tailscale), ICMP.
**net0 (intern/NAT) bleibt ungefiltert = Rettungsleine**, RDP über die NAT-IP bleibt immer erreichbar.
## 2. Tailscale: Relay statt Direktverbindung
**Befund:** `tailscale status` zeigte `relay "ki1-us"` — jede Verbindung lief über Virginia, also DE→USA→DE.
**Ursache:** VM302 sitzt hinter NAT auf gpu1. Forwards für RDP und Moonlight existierten, **für Tailscale UDP 41641 nicht.**
**Fix — BEIDE Regeln nötig:**
```bash
# eingehend
iptables -t nat -A PREROUTING -i vmbr0 -p udp --dport 41641 -j DNAT --to-destination 10.10.10.102:41641
iptables -I FORWARD -p udp -d 10.10.10.102 --dport 41641 -j ACCEPT
# ausgehend: Quellport ERHALTEN
iptables -t nat -I POSTROUTING 1 -o vmbr0 -p udp -s 10.10.10.102 --sport 41641 \
-j SNAT --to-source 173.208.162.26:41641
netfilter-persistent save
```
**Nur DNAT reicht nicht** — MASQUERADE würfelt sonst den Quellport, STUN meldet einen anderen Port
als den geforwardeten, und das Mapping passt nicht zusammen.
**Ergebnis:** 162 ms / 40 ms Jitter (Relay) → **127 ms / 0,8 ms Jitter (direkt)**.
## 3. RSC — der eigentliche Latenz-Fresser
**Befund:** nas2 → VM302 = 143,9 ms, nas2 → gpu1 = 134,8 ms. **9,1 ms Unterschied im selben Rechenzentrum.**
**Ursache:** Recv Segment Coalescing (RSC) auf den virtio-NICs aktiv — bündelt eingehende Pakete, spart CPU, kostet Latenz und Jitter.
```powershell
Disable-NetAdapterRsc -Name "Ethernet 2"
Disable-NetAdapterRsc -Name "Ethernet"
```
**Ergebnis:** VM302 132,3 ms · Abstand zu blankem Blech **9,1 → 2,0 ms** · netto **~7 ms Gewinn**.
RSS war bereits aktiv (16 Queues), Offloads korrekt.
## 4. Routing-Analyse — warum kein Relay hilft
| Weg | Ergebnis |
|---|---|
| Direkt DE → VM302 | **121 ms**, ±2 ms Jitter, 0 % Verlust |
| über Netcup DE (gw) | +15 ms |
| über Netcup Virginia | +9 ms |
| alle VM302-Ziele über gw | +15…20 ms |
**Traceroute:** beide Wege über Arelion/Telia (62.115.x). Direkter Pfad **ohne Umweg**, Zielnetz ab Hop 13.
**Geografie:** Virginia = Ostküste (94 ms), Kansas City = Landesinneres (121 ms) → über Virginia fährt man 27 ms extra.
**Messfallen, die zu Fehlschlüssen führen:**
- **TCP-Handshake über einen nginx-Stream-Proxy misst nichts** — nginx nimmt lokal an, bevor es das Backend kontaktiert (zeigte 3,5 ms statt der echten Strecke). Stattdessen echten Protokoll-Roundtrip messen (RDP X.224 CR→Confirm).
- **Ping-Summen unterschätzen Relays systematisch** — Annahme/Pufferung/Neuversand tauchen darin nicht auf. Gemessene Realität bei gw: +15 ms, obwohl die Summe „gleichauf" vorhersagte.
- `tailscale netcheck` nutzt einen **eigenen Socket** — der dort gemeldete Port ist NICHT tailscaleds 41641.
**Fazit:** 7.000 km über ein Tier-1-Backbone sind ~121 ms. Kein Relay, Tunnel oder Peering-Trick geht darunter.
Echte Hebel: Protokoll (Moonlight statt RDP), Maschine (RSC), Architektur (Ergebnisse nach DE pushen statt mehrfach queren).
## 5. Zwei eigene Fehler — zur Warnung
**a) Proxmox-Cluster-Falle.** gpu1 und pm1 bilden `consoro-cluster`. `/etc/pve/` ist **geteiltes Cluster-Dateisystem**
`cluster.fw` mit `enable: 1` auf gpu1 schaltete die Firewall auch auf pm1 ein → dort SSH tot, Web-UI-Timeouts bei VM-Details
(PVEFW-HOST-IN lässt SSH nur aus IPSET `management`, und das war leer).
➡️ **Vor jedem Proxmox-Firewall-Eingriff `pvecm status` prüfen.**
**b) `policy_in` ist keine gültige `host.fw`-Option** (gehört in `cluster.fw`). Falsch gesetzt → Host-Policy fiel auf DROP zurück
**Selbst-Aussperrung per SSH**. Gerettet hat Tailscale, weil `ts-input` **vor** der PVE-Kette akzeptiert.
➡️ Bei Firewall-Arbeiten immer einen zweiten, ungefilterten Zugangsweg offen halten.
**c) Unbelegte Behauptung.** Ich hatte gewarnt, der DERP auf dem Mailserver störe die Mailzustellung — **ohne zu messen**.
Nachgemessen: 0,1 % CPU, 2 Verbindungen, 1 Logzeile/Stunde. Die Behauptung war falsch.
➡️ Erst messen, dann warnen.
## 6. Latenz-Matrix (Referenz)
Gemessen von nas2 (Standort Bär, ohne WARP-Verfälschung):
| nas2 → | ms | | Server → gpu1 | ms |
|---|---|---|---|---|
| DERP-DE (Mailserver) | 24,3 | | **Mailserver** | **111,4** (bestes Peering) |
| DERP-US (Virginia) | 106,6 | | Hub | 120,5 |
| gpu1 | 130135 | | nas2 | 134,8 |
| VM302 (nach Tuning) | 132,3 | | | |
**Wichtig:** Bär nutzt Cloudflare WARP → Messungen an seinem Client sind verfälscht. **Immer von nas2 oder gpu1 aus messen.**
---
# NACHTRAG — Thema abgeschlossen (Endstand 2026-07-20)
## Weitere Messungen nach dem ersten Bericht
### Cloudflare Tunnel — mein Messfehler und die Korrektur
Erster Test zeigte scheinbar **90 ms Gewinn** durch einen Cloudflare Quick Tunnel.
**Das war falsch.** Ursache: der Testserver war ein einthreadiger Python-`BaseHTTPRequestHandler`,
der die *Direkt*messung ausbremste (274 ms bei 132 ms echter Netzlaufzeit).
Neumessung mit `ThreadingHTTPServer` + `TCP_NODELAY` + keep-alive, gleiches Backend für beide Wege:
| Weg | Median Dauerbetrieb |
|---|---|
| Direkt (http) | **130144 ms** ← entspricht exakt dem Ping |
| Cloudflare-Tunnel (https) | 166227 ms |
➡️ **Cloudflare ist 3580 ms LANGSAMER.** Kein Domain-Umzug nötig.
➡️ **Lehre: bei Latenzmessungen immer prüfen, ob der Testserver selbst der Flaschenhals ist.**
### Warum Cloudflares 1-ms-Nähe nicht hilft
`gpu1 → 1.1.1.1 = 1,06 ms`, PoP-Kennung **`mci03`** (= Kansas City), 6 Hops, echtes Cloudflare (kein Provider-Hijack).
Aber: Diese 1 ms decken nur den ersten Meter. Der Atlantik bleibt.
**Ein Anycast-Ping misst, wo die nächste Edge steht — nicht, wie schnell das Backbone nach Europa trägt.**
### Alle Varianten im Endstand
| Variante | Ergebnis |
|---|---|
| **Direkt** | ✅ 121 ms (RZ) · 130 ms (nas2) · 150 ms (Client) |
| Cloudflare-Tunnel | +35…80 ms |
| Netcup-DE-Relay | +15 ms |
| Netcup-Virginia | +9 ms |
| NordVPN Meshnet | ±0 (funktional = Tailscale) |
| Multi-Routing-Broker | nicht bauen — Tailscale leistet das bereits |
| **RSC-Tuning VM302** | ✅ **7 ms** (einziger echter Gewinn) |
**Bärs Anschluss ist Starlink** (SpaceX-IP, Berlin) → systembedingter Jitter, nicht wegoptimierbar.
Sein Client misst 150 ms, sein NAS am selben Anschluss 130 ms → Verdacht WLAN/Client-seitig.
## Weitere Sicherheitsbefunde (alle geschlossen)
### Sunshine-Admin-Oberfläche stand offen
Port 47990 öffentlich erreichbar, **ohne jede Zugangsdaten** (`credentials/` enthält nur TLS-Zertifikate,
`sunshine.conf` hat kein `username`/`password`). Wer die URL aufrief, konnte sich als Admin einrichten,
Geräte koppeln und **den Desktop streamen**.
➡️ 47990 aus der Proxmox-Regel entfernt **und** die DNAT-Weiterleitung auf gpu1 gelöscht.
### DNAT verschleierte alle RDP-Absender
```
DNAT tcp dpt:3389 → 10.10.10.102 destination 0.0.0.0/0 ← griff auch für .43
```
Folge: **jede** RDP-Verbindung erschien als `10.10.10.1` — auch die Angriffe aus Ungarn (80.94.95.152)
und Moskau (62.205.169.50). **EvlWatcher war blind** und hätte beim Sperren Bär selbst ausgesperrt.
➡️ DNAT auf `-d 173.208.162.26` eingegrenzt. `.43` läuft direkt mit echter Absender-IP,
`.26` bleibt als Rettungsleine.
**Merksatz:** DNAT-Regeln ohne Ziel-IP-Bindung hebeln VM-Firewalls aus, weil der Traffic
am gefilterten Interface vorbei auf die interne Karte umgeleitet wird.
## Moonlight/Sunshine — Ursache
**`sunshine_state.json`: 0 gekoppelte Geräte.** Ohne Kopplung kein Stream.
Sunshine läuft als SYSTEM in Sitzung 1 (Konsole), virtueller Display-Adapter (SudoMaker) vorhanden,
Aufnahme funktioniert (1600x1156 @ 66 Hz). Desktop-Duplication funktioniert in RDP-Sitzungen nicht —
deshalb muss Sunshine auf der Konsole laufen.
**Kopplung:** Client in Tailscale → Moonlight „+" → `100.104.5.57` → PIN unter `https://100.104.5.57:47990`.
## Fazit
7.000 km über ein Tier-1-Backbone sind ~121 ms. **Kein Relay, Tunnel, Mesh oder Broker geht darunter.**
Für 510 €/Monat existiert keine Lösung, die das ändert. Einziger echter Hebel: **GPU-Maschine in Europa.**
Praktisch nutzbar: Protokollwahl (Moonlight statt RDP) und **Ergebnisse nach DE pushen statt den Ozean mehrfach queren.**