[HIGH] Agent-WS-Auth ohne Rate-Limit/Lockout — Token-Bruteforce gegen Root-Kanal (public) #181

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

Teil des Public-Readiness-Epics. HIGH (sobald Agent-WS public).
Der Agent-WS (server/websocket/agent_ws.py:97-108) ist "public, token-auth only". Bei oeffentlicher Erreichbarkeit ohne Rate-Limit/Lockout ist Token-Bruteforce gegen den Root-Command-Kanal moeglich. Aktuell: bei Fehlschlag nur logger.warning(...), kein Zaehler, kein Delay, kein Block.

Fix

  • Rate-Limit pro Quell-IP auf den Auth-Schritt (z. B. Sliding-Window: N Fehlversuche/Minute → temporaerer Block mit exponential backoff). In-Memory-Struktur (dict IP→fails/until) reicht fuers Erste; optional Redis/Tabelle, falls mehrere Backend-Instanzen.
  • Strukturiertes Auth-Fail-Log (IP, Zeit, Grund) in stabilem Format, damit fail2ban extern greifen kann (empfohlener zweiter Riegel auf dem Host).
  • Konstante Antwortzeit bei Fehlschlag (kein Timing-Orakel ueber Token-Existenz).
  • Erfolgreiche Auth setzt den IP-Zaehler zurueck.

Akzeptanz

  • Wiederholte Fehlversuche von einer IP werden gedrosselt/geblockt (verifiziert per Test).
  • Auth-Fail-Logzeile ist fail2ban-parsebar (dokumentiertes Format + Beispiel-Filter im Wiki).
  • Kein Timing-Unterschied zwischen "Token unbekannt" und sonstigem Fehlschlag.

Branch

feat/agent-ws-auth-ratelimit

Teil des Public-Readiness-Epics. **HIGH (sobald Agent-WS public).** Der Agent-WS (`server/websocket/agent_ws.py:97-108`) ist "public, token-auth only". Bei oeffentlicher Erreichbarkeit ohne **Rate-Limit/Lockout** ist Token-Bruteforce gegen den Root-Command-Kanal moeglich. Aktuell: bei Fehlschlag nur `logger.warning(...)`, kein Zaehler, kein Delay, kein Block. ## Fix - **Rate-Limit pro Quell-IP** auf den Auth-Schritt (z. B. Sliding-Window: N Fehlversuche/Minute → temporaerer Block mit exponential backoff). In-Memory-Struktur (dict IP→fails/until) reicht fuers Erste; optional Redis/Tabelle, falls mehrere Backend-Instanzen. - **Strukturiertes Auth-Fail-Log** (IP, Zeit, Grund) in stabilem Format, damit **fail2ban** extern greifen kann (empfohlener zweiter Riegel auf dem Host). - Konstante Antwortzeit bei Fehlschlag (kein Timing-Orakel ueber Token-Existenz). - Erfolgreiche Auth setzt den IP-Zaehler zurueck. ## Akzeptanz - Wiederholte Fehlversuche von einer IP werden gedrosselt/geblockt (verifiziert per Test). - Auth-Fail-Logzeile ist fail2ban-parsebar (dokumentiertes Format + Beispiel-Filter im Wiki). - Kein Timing-Unterschied zwischen "Token unbekannt" und sonstigem Fehlschlag. ## Branch `feat/agent-ws-auth-ratelimit`
Author
Owner

#181 umgesetzt · Commit d748c17 (Backend-only, kein Agent-Build). Issue bleibt offen.

Setzt auf dem neuen #185-Handshake auf.

  • websocket/auth_ratelimit.py: per-Quell-IP Sliding-Window (5 Fehlschlaege/60s → Block), exponentielles Backoff (30s→60s→120s… Cap 1h), Erfolg setzt den Zaehler zurueck. In-Memory.
  • agent_ws.py: geblockte IP wird vor jeder Auth-Arbeit abgewiesen (kein Challenge/DB-Hit). Strukturiertes, fail2ban-parsebares Log: agent-auth-fail ip=<IP> reason=<grund> + agent-auth-block ip=<IP> retry_in=<n>s. Konstante Antwortzeit (kein Timing-Orakel).
  • wiki/Security.md: Log-Format + Beispiel-fail2ban-Filter (failregex = ^.*agent-auth-fail ip=<HOST> reason=.*$) + Jail.

Akzeptanz: wiederholte Fehlversuche einer IP werden gedrosselt/geblockt · Log fail2ban-parsebar . Wirksam nach Backend-Rebuild (zusammen mit #185).

**#181 umgesetzt** · Commit `d748c17` (Backend-only, kein Agent-Build). Issue bleibt offen. Setzt auf dem neuen #185-Handshake auf. - `websocket/auth_ratelimit.py`: per-Quell-IP Sliding-Window (**5 Fehlschlaege/60s → Block**), exponentielles Backoff (30s→60s→120s… Cap 1h), Erfolg setzt den Zaehler zurueck. In-Memory. - `agent_ws.py`: geblockte IP wird vor jeder Auth-Arbeit abgewiesen (kein Challenge/DB-Hit). Strukturiertes, fail2ban-parsebares Log: `agent-auth-fail ip=<IP> reason=<grund>` + `agent-auth-block ip=<IP> retry_in=<n>s`. Konstante Antwortzeit (kein Timing-Orakel). - `wiki/Security.md`: Log-Format + Beispiel-fail2ban-Filter (`failregex = ^.*agent-auth-fail ip=<HOST> reason=.*$`) + Jail. **Akzeptanz**: wiederholte Fehlversuche einer IP werden gedrosselt/geblockt ✅ · Log fail2ban-parsebar ✅. Wirksam nach Backend-Rebuild (zusammen mit #185).
Author
Owner

Verifiziert @ d748c17 → erfüllt, wird geschlossen.

Rate-Limit greift VOR Challenge/DB (agent_ws.py:~120, auth_limiter.is_blocked); Lockout + fail2ban-parsebares Log; wiki/Security.md ✓

**Verifiziert @ d748c17 → erfüllt, wird geschlossen.** Rate-Limit greift VOR Challenge/DB (agent_ws.py:~120, `auth_limiter.is_blocked`); Lockout + fail2ban-parsebares Log; wiki/Security.md ✓
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#181
No description provided.