Terminal SSH: como se conecta el navegador al Local Agent en localhost:5050 y como se establece la sesion SSH via WebSocket ws/terminal? Protocolo crearack:// y persistencia de sesiones.
Pregunta
Terminal SSH: ¿cómo se conecta el navegador al Local Agent en localhost:5050 y cómo se establece la sesión SSH vía WebSocket ws/terminal? Protocolo crearack:// y persistencia de sesiones.
Respuesta corta
El navegador no habla SSH directamente. Abre un WebSocket contra el Local Agent en 127.0.0.1:5050, y es el Agente —que corre dentro de la LAN del cliente— quien abre la sesión SSH real contra el dispositivo. El Agente actúa de puente cifrado: transporta tus teclas al dispositivo y la salida de vuelta al navegador.
El flujo paso a paso
- Detección + auth local: el frontend confirma que el Agente está vivo (fetch a
/info) y obtiene el token local del SaaS para autorizar la API local (ver la página de credenciales del Local Agent). - Apertura del WebSocket:
ws://127.0.0.1:5050/ws/terminal/{client_id}. Con el Agente vinculado a un SaaS, el primer mensaje debe ser{"action":"auth","token":<token_local>}(la UI lo recibe del SaaS porpostMessage SET_AUTH_TOKEN). Sin token válido → el Agente cierra con código 4401 (terminal/agent/routes/terminal.py:255-263). - Conexión SSH:
{"action":"connect", "device_id"|"profile_id": ...}. El Agente resuelve las credenciales server-side con su JWT (R3) —fetch_device_credentials/fetch_profile_credentials(terminal.py:315-330) — abreasyncsshcon host-key TOFU y responde"Tunnel Established!". El navegador nunca ve la contraseña. - Interacción: cada tecla viaja como
{"action":"data", ...}al PTY del dispositivo; la salida vuelve por el mismo WebSocket como{"type":"output"}.
Persistencia de sesiones (reattach)
Al navegar entre páginas el WebSocket se cae, pero la sesión SSH sobrevive. El Agente conserva el puente en memoria (ACTIVE_BRIDGES) y solo pone bridge.websocket = None (log: “Client decoupled (SSH session persists)”, terminal.py:342). Al reconectar con el mismo client_id, si el SSH sigue vivo, el Agente reproduce el output_buffer (te devuelve lo que salió mientras no mirabas) y responde "Tunnel Established!" (terminal.py:265-278). Si el SSH murió mientras estabas desconectado, limpia el puente obsoleto y abre uno nuevo.
El protocolo crearack://
Sí existe (el draft anterior decía que no; es incorrecto). El instalador registra crearack como protocolo URL de Windows en el registro: HKCU\SOFTWARE\Classes\crearack con comando "CreaRackAgent.exe" "%1" (_register_protocol_handler, terminal/agent/core/installer.py:217). Así, un enlace crearack://… desde el navegador lanza o enfoca el Agente local (deep-link), sin depender de que el usuario lo abra a mano.
Seguridad del canal
- La API local exige
Authorization: Bearer <token_local>salvo rutas de bootstrap; el WS de la consola valida el token en el primer mensaje (close 4401). Cierra el DNS-rebinding/CSRF (Raíz 3 de la Auditoría Suprema). - Las credenciales del dispositivo nunca las teclea ni relé el navegador: el Agente las obtiene server-side por
device_id/profile_id(R3). Cifradas en reposo (Fernet en el SaaS, DPAPI en el Agente). - Host-key TOFU (
network/host_keys.py): graba la clave del dispositivo en la 1ª conexión y rechaza si cambia (detección de MITM).
Véase también
- [[concept—general—como-obtiene-el-local-agent-sus-credenciales-de-vi]]
- [[concept—general—como-detecta-el-frontend-si-el-local-agent-esta-co]]