4.2 KiB
MCP-Ferndiagnose (Goal, ultracode) — v1.7.223
Ziel (Nutzer)
"Baue massive Diagnose-Funktionen ein (MCP), so dass ich MCP auf nem Windows-Server aktivieren kann und du auf den Server zugreifst und WIRKLICH ALLES siehst (State, Fehler, Logs, Probleme). 5-6 Server, ueber Verbindungscode. Du verbindest dich → liest alles → behebst Probleme direkt."
Architektur (Advisor-bestaetigt v1)
- Standalone stdio MCP-Bridge auf MEINER (Claude-Code-)Maschine, proxyt zur bestehenden HTTP
debug-server.tsjedes Servers via Verbindungscode. Eine Bridge bedient alle 5-6 Server. - KEIN eingebettetes MCP-over-HTTP (verworfen: hand-rolled Protokoll auf Internet-Oberflaeche = mehr Risiko).
- Bridge-Code identisch fuer Direkt-IP vs spaeterer Tunnel (proxyt host:port).
- Verbindungscode:
rddiag:v1:<base64url(JSON {v,h:host,p:port,t:token,n?:name,fp?:certFp})>. Nutzer liefert oeffentlichen Host (nicht auto-detecten).
Sicherheitsmodell (Advisor, first-class)
Plain HTTP + Bearer ueber Internet = sniffbares Token mit Lesezugriff auf sensible Logs. Mitigations:
- App-seitige IP-Allowlist (extractDebugClientIp existiert schon).
/trace/configMUTIERT → "read-only"-Claim auditieren: Writes von Remote-Oberflaeche gaten oder umlabeln.- Opt-in + sofort widerrufbar (Token-Rotation killt Zugang).
- debug_token.txt in userData bestaetigen (ueberlebt Auto-Update).
- Optional self-signed Cert + Fingerprint im Code gepinnt (NICHT v1-blockierend).
Phasen
- P0 Vertical Slice (Diskriminator) — ERLEDIGT, harness ALL PASS: Bridge → debug-server via stdio JSON-RPC, echte Daten zurueck.
- MCP SDK API holen (context7) → @modelcontextprotocol/sdk 1.29.0, registerTool(name,{inputSchema:zodShape},cb)
- Bridge in
tools/rd-diagnostics-mcp/(eigenes package.json, NICHT in App-Bundle): code.mjs/http.mjs/bridge.mjs/gen-code.mjs - 14 Tools: rd_servers/rd_ping/rd_diagnostics/rd_status/rd_items/rd_packages/rd_errors/rd_logs/rd_history/rd_accounts/rd_host/rd_self_check/rd_get + Multi-Server (code|server|RDDIAG_CODE|RDDIAG_SERVERS)
- Verbindungscode-Codec rddiag:v1:base64url({v,h,p,t,n?,fp?,s?})
- Test-Harness (test/harness.mjs): fake debug-server (auth+routes+query-echo) + Bridge als stdio-Child → 19 Checks gruen (handshake, tools/list, ping, diagnostics+query-passthrough, logs-mapping, errors, escape-hatch, 401, missing-code, unreachable+hint)
- P1 Security-Hardening — ERLEDIGT: IP-Allowlist (exakt+CIDR), erzwungen VOR Auth am ECHTEN Socket-Peer (req.socket.remoteAddress), NICHT X-Forwarded-For (Advisor: XFF faelschbar → Bypass; gefixt+Threat-Test). Fail-closed. /trace/config belassen (zeitbegrenzt). userData/runtime verifiziert. Log-Audit: keine Secrets in /logs/*.
- P2 One-Click-Enable + Code — ERLEDIGT: restartDebugServer ('close'+closeAllConnections, EADDRINUSE). IPC get/enable/disable/rotate + Controller + Typen. Flache Modal-UI (Hilfe→Remote-Support→"Ferndiagnose (MCP)"): Status, lokal/netzwerk, Public-Host+Chips, Allowlist, Code+Copy+Token-Rotation+Deaktivieren.
- P3 — durch bestehende Endpunkte abgedeckt: /accounts (Cooldown/Rotation), /errors, /status, /diagnostics via Bridge. Kein neuer Endpunkt noetig.
- P4 Verify — ERLEDIGT: Suite 906 gruen, tsc=6, Harness gruen, Advisor (fing XFF-Bypass). Release v1.7.223 Gitea (
6b52678, 4 Assets) + Mirror (24485be, 4 Assets, Claude-frei). Bridgeclaude mcp add(user, ✔ Connected). - P5 Reachability (NUTZER): Ferndiagnose auf 1 Server an → Code an mich → ich verbinde. Entscheid: Tunnel (sicherste, "Nur lokal") vs Direkt-Bind 0.0.0.0+Allowlist (nur vertrauenswuerdiges Netz/VPN; Token reist plain HTTP).
Review
Vertikaler Slice zuerst (Bridge gegen Fake-Debug-Server, JSON-RPC stdio), dann App-Seite load-bearing-first
(Backend+Tests vor UI). Advisor fing einen releaseblockierenden Bug: Allowlist nutzte extractDebugClientIp
(X-Forwarded-For zuerst = angreiferkontrolliert) → Bypass per X-Forwarded-For: 127.0.0.1; Tests maskierten es
(injizierten die IP per genau dem Header). Fix: Enforcement am Socket-Peer, XFF nur fuers Log; Threat-Test
(socket 8.8.8.8 + XFF 127.0.0.1 → denied). Empfohlener Transport: Loopback+Tunnel; Direkt-Bind nur mit Allowlist.