Doku 2026-07-20: Moonlight/Apollo-Analyse (abgebrochen) + Verbindungs-Wahrheit

- Apollo statt Sunshine: wer die Ports besitzt, bestimmt welche Konfiguration gilt
- PIN-Fehler war haengender Kopplungszustand, kein falscher PIN
- Kein NVENC weil QEMU-VGA statt A40 abgegriffen wird
- Tailscale laeuft != Tailscale wird benutzt
- Eigene Messfehler dokumentiert
This commit is contained in:
Code-Barby 2026-07-20 17:48:00 +02:00
parent 07c1c0f31d
commit 99926aaf69
2 changed files with 181 additions and 0 deletions

View file

@ -0,0 +1,58 @@
# Verbindungs-Wahrheit VM302 — welcher Weg wird wirklich benutzt
**Datum:** 2026-07-20
## Kernbefund
Ein laufendes Tailscale bedeutet **nicht**, dass der Verkehr durch den Tunnel geht.
Tailscale routet nur, was an seine Adressen adressiert ist.
Aus dem RDP-Anmeldeprotokoll von VM302:
```
16:10:57 Sitzung 4 (matthias) von 185.229.59.123 <- NordVPN
16:39:44 Sitzung 4 (matthias) von 9.246.41.123 <- Starlink, direkt
Sitzung 3 (mcp) von 100.87.20.94 <- Hub ueber Tailscale
```
Der Nutzer war ueberzeugt, ueber Tailscale zu gehen — tatsaechlich lief die Verbindung roh ueber
Starlink. Ursache: Verbindung auf den oeffentlichen Namen `rdp.go-ki.eu` -> oeffentliche IP ->
Tunnel bleibt ungenutzt. Fuer den Tunnel muesste die Tailscale-Adresse `100.104.5.57` angegeben werden.
## Nachweis, welcher Weg benutzt wurde
```powershell
Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational' -MaxEvents 60 |
Where-Object { $_.Id -in 21,25 } | ForEach-Object {
$x = [xml]$_.ToXml()
"$($_.TimeCreated) | Sitzung $($x.Event.UserData.EventXML.SessionID) | $($x.Event.UserData.EventXML.Address)"
}
```
`100.x` = Tunnel, alles andere = oeffentlicher Weg.
## Was von VM302 aus NICHT messbar ist
Die Latenz des Nutzers laesst sich vom Server aus nicht ermitteln:
- **ICMP** — Starlink filtert Ping, keine Antwort
- **TCP zurueck zum Client** — es lauscht nichts auf dem Quellport; alle Versuche liefen ins Zeitlimit
(8x ~2013 ms = exakt das gesetzte Limit, **keine Messwerte**)
- **RemoteFX-Netzwerkzaehler** — auf dieser Maschine nicht vorhanden
Messung ist nur von der Client-Seite moeglich. Vom Server aus laesst sich lediglich der **benutzte Weg**
nachweisen, nicht die Geschwindigkeit.
## Methodischer Fehler, der dabei passierte
Es waren drei Verbindungen auf Port 3389 offen. Gemessen wurde die erstbeste (144 ms, 0,18 ms Jitter)
und als "deine Verbindung" praesentiert. Sie gehoerte zu **keiner** Anmeldung.
**Regel: Erst Sitzung <-> IP ueber das Anmeldeprotokoll zuordnen, dann messen.**
Eine Messung ohne geprueften Endpunkt ist wertlos, egal wie sauber die Zahlen aussehen.
## Offener Sicherheitspunkt
`91.238.181.141` hatte eine hergestellte Verbindung auf Port 3389, **ohne dass je eine Anmeldung
protokolliert wurde**. Im Kontext der am selben Tag beobachteten Angriffe (Ungarn 80.94.95.152,
Moskau 62.205.169.50) pruefen.

View file

@ -0,0 +1,123 @@
# Moonlight / Apollo auf VM302 — Analyse und Abbruch
**Datum:** 2026-07-20
**System:** VM302 (Windows 11 26100, NVIDIA A40, Kansas City, Proxmox-VM auf gpu1)
**Ergebnis:** Kopplung geloest, Bilduebertragung unbrauchbar, auf Nutzerwunsch abgebrochen
---
## Ausgangslage
Moonlight verweigerte die Kopplung mit "PIN failed", obwohl die PIN nachweislich korrekt war.
Beim PIN-Dialog erschien die Oberflaeche von **Apollo**.
## Befund 1 — Es laeuft Apollo, nicht Sunshine
```
C:\Program Files\Apollo (16.07.2026 15:48) <- LAEUFT
C:\Program Files\Sunshine (16.07.2026 06:35) <- Dienst gestoppt
PID 46664 C:\Program Files\Apollo\Sunshine.exe Sitzung 1, SYSTEM
Ports 47984 / 47989 / 47990 / 48010 -> alle bei Apollo
```
**Apollo ist ein Fork von Sunshine** und behaelt den Binaernamen `Sunshine.exe` bei — das macht die
Verwechslung leicht.
> **Fehler in der Analyse:** Zunaechst wurde die Konfiguration unter `C:\Program Files\Sunshine\config\`
> ausgewertet. Die ist ungenutzt. Der Schluss "0 gekoppelte Geraete" war deshalb wertlos.
> **Regel:** Erst feststellen, welcher Prozess die Ports besitzt — dann dessen Konfiguration lesen.
## Befund 2 — Die PIN war nie das Problem
```
[2026-07-20 16:38:06] Warning: Pair attempt failed due to Out of order call to getservercert
```
Kein falscher PIN, sondern ein **haengender Kopplungszustand**: Der Client schickte einen
Kopplungsschritt, bevor der vorherige abgeschlossen war — typisch nach einem abgebrochenen Versuch.
**Loesung:** `Restart-Service ApolloService` raeumt den Zustand im Speicher auf.
Danach klappte die Kopplung im ersten Anlauf.
## Befund 3 — Apollo greift den falschen Bildschirm ab
| Anzeigegeraet | Aufloesung | Bemerkung |
|---|---|---|
| Microsoft Basic Display (QEMU-VGA) | 1280x800 @ **1 Hz** | <- das greift Apollo ab |
| SudoMaker Virtual Display | 640x360 @ 60 Hz | Apollos eigener Treiber |
| Microsoft Remote Display | 1600x1156 @ 66 Hz | RDP-Sitzung |
| **NVIDIA A40** | 1600x1156 @ 66 Hz | **an die RDP-Sitzung gebunden** |
Daraus folgen alle drei Symptome:
- **Kein NVENC**`Failed to create encoder D3D11 device [0x887A0004]`. Apollo versucht NVENC zuerst,
scheitert aber, weil der abgegriffene Bildschirm am Microsoft-Basisadapter haengt.
Fallback: `libx264 [software]`.
- **Ruckeln** — 1 Hz Bildwiederholrate auf dem QEMU-Notfallbildschirm.
- **Mausversatz** — Client und Host arbeiten mit verschiedenen Rastern, absolute Mauskoordinaten
werden falsch umgerechnet.
## Befund 4 — Die Anwendungen in Moonlight
`apps.json` definiert: `Desktop`, `Remote Desktop Manager`, `Claude Code`, `Hermes`, `Browser`, `PowerShell`.
**`Virtual Display` ist kein Eintrag daraus, sondern Apollos eingebauter Pseudo-Eintrag** — er legt einen
leeren Zusatzbildschirm an und zeigt sonst nichts.
| Gestartet | Ergebnis | Messwert |
|---|---|---|
| `Virtual Display` | schwarz | skip 100 %, 18 kbit/s — leerer Bildschirm |
| `Desktop` | Anmeldebildschirm sichtbar | 371 kbit/s, skip 76 % — echter Inhalt |
| `Desktop` + `always_use_virtual_display: true` | wieder schwarz | zurueckgesetzt |
Die Bitrate ist der schnellste Indikator: unter ~20 kbit/s bei 100 % uebersprungenen Bildbloecken
wird ein statisch schwarzes Bild uebertragen.
## Befund 5 — Der strukturelle Kern
Apollo laeuft als SYSTEM in **Sitzung 1 (Konsole) — dort ist niemand angemeldet.** Der Nutzer arbeitet
in Sitzung 4 ueber RDP. Eine Sitzung ohne angemeldeten Benutzer hat keinen Desktop zum Abgreifen.
Deshalb der Anmeldebildschirm.
**Falle:** Eine Anmeldung als derselbe Benutzer am Konsolen-Anmeldebildschirm wuerde wegen
`fSingleSessionPerUser=1` die bestehende RDP-Sitzung an die Konsole holen — der Nutzer fliegt aus RDP.
**Fuer einen Parallelbetrieb waere noetig:**
1. Ein **eigener Benutzer** fuer die Konsolensitzung (nicht derselbe wie fuer RDP)
2. Das virtuelle Display an den **A40** binden statt an den Basisadapter — erst dann greift NVENC
## Zurueckgenommene Behauptungen
- **"RDP und Moonlight schliessen sich gegenseitig aus."** Falsch. Der Parallelbetrieb ist ueber ein
separates virtuelles Display ausdruecklich vorgesehen; Apollo hat dafuer `always_use_virtual_display`
und `headless_mode`. Der Nutzer widersprach aus eigener Erfahrung und hatte recht.
- **"Apollo versucht NVENC gar nicht erst."** Falsch. Es versucht NVENC als erstes und scheitert.
Die Logzeilen waren durch einen zu engen Filter uebersehen worden.
- **Leerlaufwerte als Dauerzustand.** Der Encoder-Test beim Dienststart sagt nichts ueber den
Streaming-Betrieb aus, weil das virtuelle Display erst beim Verbindungsaufbau entsteht.
## Endzustand
- Apollo laeuft, **Kopplung bleibt erhalten**
- `always_use_virtual_display` zurueck auf `false`
- Debug-Protokollierung wieder aus
- Sicherung: `sunshine_state.json.bak-vor-vd`
- **RDP bleibt der Zugangsweg**
- Offen: `apps.json` verweist noch auf alte Sunshine-Pfade (`sunshine.ki1.it:47990`)
## Nuetzliche Befehle
```powershell
# Wer besitzt die Streaming-Ports?
Get-NetTCPConnection -LocalPort 47989 -State Listen |
ForEach-Object { Get-Process -Id $_.OwningProcess }
# Encoder- und Bildschirmwahl im Betrieb
Get-Content "C:\Program Files\Apollo\config\sunshine.log" |
Where-Object { $_ -match 'Found H.264|Capture size|Device Description|kb/s|skip:' }
# Debug-Protokollierung
Add-Content "C:\Program Files\Apollo\config\sunshine.conf" "`nmin_log_level = debug"
Restart-Service ApolloService
```