[EPIC] Public-Readiness: Root-Command-Kanal für VPN-lose Hosts härten (wss-Zwang, Signatur, Bind, Bruteforce) #184

Closed
opened 2026-06-26 11:26:47 +00:00 by chinux · 4 comments
Owner

Ziel

Das System public-tauglich machen: ein Proxmox-Host ohne VPN soll sicher anbinden koennen. Architektur: Backend hinter NPM + acme.sh, Node-Agent verbindet ausgehend per wss:// zur oeffentlichen Domain. Damit wird der Root-Command-Kanal oeffentlich — er muss MITM-/Bruteforce-sicher werden.

Bereits erledigt (verifiziert @ a3dfe0d)

  • Node-Token at-rest gehasht (node_token_hash) ✓
  • Agent TLS-faehig (rustls-tls-webpki-roots) ✓
  • VM-Listener-Bind konfigurierbar (VM_LISTENER_BIND/AGENT_INTERNAL_NETWORK) ✓ (Default-Haertung offen, s. #117)
  • Mandantentrennung (#108-Cluster) ✓

Arbeitspakete

Transport / Kanal

  • #113wss:// erzwingen (Agent lehnt ws:// zu Nicht-localhost ab) + Server-Cert verifizieren. (bestehendes Issue, Kern fuers public)
  • #181 — Agent-WS-Auth Rate-Limit/Lockout + fail2ban-parsebares Log
    Agent-Integritaet
  • #113Self-Update ed25519-Signatur statt nur Hash (bestehendes Issue)
    Inbound-Exposure auf dem Host
  • #117 — VM-Listener-Default nie 0.0.0.0 (auf public Host loopback/internal erzwingen) (bestehendes Issue, Default-Teil offen)
  • #180RDP-Tunnel bindet 0.0.0.0:0 → internal bind
    Onboarding
  • #182Enrollment-Token kurzlebig + single-use (Rotation zu Node-Secret)
    Betrieb
  • #183Public-Deployment-Doku (NPM/wss, exponierte Ports, fail2ban-Filter, CRA-Hinweis)

Definition of Done

  • Ein Host ohne VPN bindet ueber wss:// zur public Domain an; ws:///http ist fuer Nicht-localhost unmoeglich.
  • Self-Update akzeptiert nur signierte Binaries.
  • Auf dem public Host ist kein theProx-Port ausser dem ausgehenden WS noetig; Listener/Tunnel nie auf 0.0.0.0.
  • Agent-WS gegen Bruteforce geschuetzt (Rate-Limit + fail2ban-tauglich).
  • Enrollment-Token kann nicht dauerhaft missbraucht werden.
  • Deploy-Doku vorhanden.

Bezug

#113, #117 (bestehend), #108 (Scope, erledigt). Architektur-Entscheidung: NPM-public + wss.

## Ziel Das System **public-tauglich** machen: ein Proxmox-Host **ohne VPN** soll sicher anbinden koennen. Architektur: **Backend hinter NPM + acme.sh**, Node-Agent verbindet **ausgehend per `wss://`** zur oeffentlichen Domain. Damit wird der **Root-Command-Kanal oeffentlich** — er muss MITM-/Bruteforce-sicher werden. ## Bereits erledigt (verifiziert @ a3dfe0d) - Node-Token **at-rest gehasht** (`node_token_hash`) ✓ - Agent **TLS-faehig** (`rustls-tls-webpki-roots`) ✓ - VM-Listener-Bind **konfigurierbar** (`VM_LISTENER_BIND`/`AGENT_INTERNAL_NETWORK`) ✓ (Default-Haertung offen, s. #117) - Mandantentrennung (#108-Cluster) ✓ ## Arbeitspakete **Transport / Kanal** - [ ] #113 — **`wss://` erzwingen** (Agent lehnt `ws://` zu Nicht-localhost ab) + Server-Cert verifizieren. *(bestehendes Issue, Kern fuers public)* - [ ] #181 — Agent-WS-Auth **Rate-Limit/Lockout** + fail2ban-parsebares Log **Agent-Integritaet** - [ ] #113 — **Self-Update ed25519-Signatur** statt nur Hash *(bestehendes Issue)* **Inbound-Exposure auf dem Host** - [ ] #117 — VM-Listener-**Default nie `0.0.0.0`** (auf public Host loopback/internal erzwingen) *(bestehendes Issue, Default-Teil offen)* - [ ] #180 — **RDP-Tunnel** bindet `0.0.0.0:0` → internal bind **Onboarding** - [ ] #182 — **Enrollment-Token kurzlebig + single-use** (Rotation zu Node-Secret) **Betrieb** - [ ] #183 — **Public-Deployment-Doku** (NPM/wss, exponierte Ports, fail2ban-Filter, CRA-Hinweis) ## Definition of Done - Ein Host ohne VPN bindet ueber `wss://` zur public Domain an; `ws://`/http ist fuer Nicht-localhost unmoeglich. - Self-Update akzeptiert nur signierte Binaries. - Auf dem public Host ist kein theProx-Port ausser dem ausgehenden WS noetig; Listener/Tunnel nie auf `0.0.0.0`. - Agent-WS gegen Bruteforce geschuetzt (Rate-Limit + fail2ban-tauglich). - Enrollment-Token kann nicht dauerhaft missbraucht werden. - Deploy-Doku vorhanden. ## Bezug #113, #117 (bestehend), #108 (Scope, erledigt). Architektur-Entscheidung: NPM-public + wss.
Author
Owner

Scope-Klarstellung fuer das gesamte Epic: DEV-Umgebung

Umsetzung aller Arbeitspakete clean, ohne Rueckwaertskompatibilitaet. Verbindungsverlust bestehender Nodes ist akzeptiert (Neu-Ausrollung). Keine Legacy-Fallbacks, alte Tokens/Verbindungen duerfen brechen. Gilt fuer #113, #117, #180, #181, #182, #183 — sauberster Code vor Kompatibilitaet.

## Scope-Klarstellung fuer das gesamte Epic: DEV-Umgebung Umsetzung aller Arbeitspakete **clean, ohne Rueckwaertskompatibilitaet**. **Verbindungsverlust bestehender Nodes ist akzeptiert** (Neu-Ausrollung). Keine Legacy-Fallbacks, alte Tokens/Verbindungen duerfen brechen. Gilt fuer #113, #117, #180, #181, #182, #183 — sauberster Code vor Kompatibilitaet.
Author
Owner

Erweiterung: Agent-Auth + Blast-Radius

Neu im Scope:

  • #185 — ed25519 Challenge-Response statt Bearer (loest Token-Leak/Replay; faltet #182 ein).
  • #115 — cmd_id/session-Owner-Binding ist Pflicht fuer Public (begrenzt den Blast-Radius eines kompromittierten Nodes auf den Node selbst). Auth allein reicht nicht — erst Auth + #115 + #114 isolieren sauber.
## Erweiterung: Agent-Auth + Blast-Radius Neu im Scope: - **#185** — ed25519 Challenge-Response statt Bearer (loest Token-Leak/Replay; faltet #182 ein). - **#115** — cmd_id/session-Owner-Binding ist **Pflicht fuer Public** (begrenzt den Blast-Radius eines kompromittierten Nodes auf den Node selbst). Auth allein reicht nicht — erst Auth + #115 + #114 isolieren sauber.
Author
Owner

Block A (Agent-Kanal) abgeschlossen ✓

Verifiziert @ d748c17:

  • #113 wss + ed25519-Self-Update
  • #117 Listener-Bind-Default + Command-Allowlist
  • #180 RDP-Tunnel internal bind
  • #185 ed25519 Challenge-Response-Auth (#182 eingefaltet)
  • #181 WS-Auth Rate-Limit/Lockout
  • #115 cmd-Owner-Binding (bereits zuvor)

Offen im Epic: nur noch #183 (Public-Deployment-Doku). Damit ist der Agent→Backend-Kanal public-tauglich gehärtet. Die HTTP-/User-API-Flanke läuft separat unter Epic #186.

## Block A (Agent-Kanal) abgeschlossen ✓ Verifiziert @ d748c17: - ✅ #113 wss + ed25519-Self-Update - ✅ #117 Listener-Bind-Default + Command-Allowlist - ✅ #180 RDP-Tunnel internal bind - ✅ #185 ed25519 Challenge-Response-Auth (#182 eingefaltet) - ✅ #181 WS-Auth Rate-Limit/Lockout - ✅ #115 cmd-Owner-Binding (bereits zuvor) **Offen im Epic:** nur noch #183 (Public-Deployment-Doku). Damit ist der Agent→Backend-Kanal public-tauglich gehärtet. Die HTTP-/User-API-Flanke läuft separat unter Epic #186.
Author
Owner

Epic abgeschlossen

Alle Arbeitspakete verifiziert & geschlossen:

  • #113 wss-Zwang + ed25519-Self-Update
  • #115 cmd-Owner-Binding
  • #117 Listener-Bind-Default + Command-Allowlist
  • #180 RDP-Tunnel internal bind
  • #185 (#182) ed25519 Challenge-Response-Auth + single-use Enrollment
  • #181 WS-Auth Rate-Limit/Lockout (Backend liest X-Real-IP)
  • #183 Public-Deployment-Doku

Der Agent→Backend-Kanal ist public-tauglich gehärtet. Vor produktivem Public-Betrieb noch: koordinierter Rollout (Doc Abschnitt 7), ed25519-Self-Update-Key erzeugen + einkompilieren (sonst fail-closed), und die HTTP-/User-API-Flanke (Epic #186).

## Epic abgeschlossen ✅ Alle Arbeitspakete verifiziert & geschlossen: - ✅ #113 wss-Zwang + ed25519-Self-Update - ✅ #115 cmd-Owner-Binding - ✅ #117 Listener-Bind-Default + Command-Allowlist - ✅ #180 RDP-Tunnel internal bind - ✅ #185 (#182) ed25519 Challenge-Response-Auth + single-use Enrollment - ✅ #181 WS-Auth Rate-Limit/Lockout (Backend liest X-Real-IP) - ✅ #183 Public-Deployment-Doku Der **Agent→Backend-Kanal ist public-tauglich gehärtet**. Vor produktivem Public-Betrieb noch: koordinierter Rollout (Doc Abschnitt 7), ed25519-Self-Update-Key erzeugen + einkompilieren (sonst fail-closed), und die **HTTP-/User-API-Flanke** (Epic #186).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
chinux/theProx#184
No description provided.