real-debrid-downloader/tasks/todo.md

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.ts jedes 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/config MUTIERT → "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). Bridge claude 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.