Saltar al contenido
Caso · 09 / 15← Todos los trabajos

Puente

Una app de escritorio remoto self-hosted, al estilo AnyDesk, que corre en servidores propios para el soporte de SinBuque.

Rol
Diseño y desarrollo completo
Stack
Tauri v2, React, TypeScript, Rust, WebRTC, Go, coturn
Verificar el equipo
Verificar el equipoUn contrato escrito antes que el código
(01) El problema

El equipo necesitaba entrar a máquinas de oficina que están prendidas todo el día, sin pagar una herramienta comercial ni pasar las sesiones por servidores ajenos. El servidor que conecta las dos máquinas tenía que tratarse como no confiable. Y la persona del otro lado muchas veces no es técnica, así que los controles de seguridad tenían que entenderse en pantalla.

Mi rolPrimero diseñé el protocolo, y después construí el visor, el host y el servidor contra él.
(02) ResultadosContados en el código
73mensajes del protocolo, cada uno con su schema JSON y un ejemplo verificado
326tests de Rust que pasan entre los crates de cripto, host y visor
12capacidades opcionales que se negocian por sesión sobre un núcleo congelado
(03) Arquitectura

Tres decisiones que lo definieron.

  1. 01

    Un contrato escrito antes que el código

    Por qué. PROTOCOL.md define cada mensaje, el modelo de amenaza y el orden real de una conexión. Los schemas y los ejemplos se generan desde ahí, y el CI verifica que no se desincronicen. El visor, el host y el servidor se construyeron en paralelo contra el mismo documento. Lo nuevo entra como capacidad, así que nada viejo se rompe.

    El costo. El núcleo está congelado, así que un cambio de verdad ahí exige un pase coordinado en las tres partes. Los pedidos esperan anotados en un archivo hasta entonces.

  2. 02

    El visor dibuja la confianza, no la decide

    Por qué. El ID del equipo lo asigna el servidor, así que no prueba nada. La verificación del fingerprint es la única defensa real, y la pantalla la trata así: 16 celdas numeradas para leer en voz alta por teléfono, y un estado rojo cuando un equipo conocido aparece con otra clave. La decisión de confianza la toma el core en Rust. React sólo la dibuja, porque el código de un webview se puede editar en caliente.

    El costo. Cada pantalla depende de un comando de Tauri. Un test lee los dos lados y falla si el front invoca un comando que el core en Rust nunca registró, algo que si no aparecería recién como un botón que no hace nada.

  3. 03

    Honesto sobre qué va cifrado

    Por qué. El input, la terminal, los archivos y el portapapeles van cifrados de punta a punta. El video usa el cifrado propio de WebRTC, que un servidor hostil en teoría podría interceptar. Por eso los fingerprints DTLS entran en el handshake firmado: si el servidor manipula la conexión, la sesión se corta antes del primer cuadro. La pantalla de conexión lo dice con palabras simples cuando la sesión pasa por el relay.

    El costo. El video no va cifrado de punta a punta, y el producto nunca dice que sí. Hacerlo necesita insertable streams en los dos lados, y es un proyecto aparte.

(04) GaleríaSeguí scrolleando →
Verificar el equipo
Verificar el equipo · La primera conexión a un equipo. El fingerprint es una grilla para cotejar, con un código corto para leer en voz alta.
La identidad cambió
La identidad cambió · Un equipo conocido con otra clave. Es la alarma más fuerte de la app, así que va en rojo y el botón seguro va primero.
Conectando
Conectando · Cada paso de la conexión, con su detalle. Acá falló la ruta directa y la sesión pasa por el relay.
Primer arranque
Primer arranque · El visor explica de dónde salió su identidad antes que nada: el par de claves, el número y el código.
(05) Qué haría después
01Recorrer el flujo completo desde el visor en máquinas Windows reales. Hoy la verificación de punta a punta corre desde un probe de línea de comandos.
02Firmar los instaladores, para que SmartScreen de Windows deje de bloquearlos.
03Volver a pedir una contraseña por equipo, con un límite de intentos que el cliente no pueda reiniciar generando otra identidad.
Próximo proyecto · 10 / 15
Maderera Juan B. Justo →ERP, punto de venta y facturación, en uso todos los días
Caso · 09 / 15

Puente

Una app de escritorio remoto self-hosted, al estilo AnyDesk, que corre en servidores propios para el soporte de SinBuque.

Rol
Diseño y desarrollo completo
Stack
Tauri v2, React, TypeScript, Rust, WebRTC, Go, coturn
Puente
(01) El problema

El equipo necesitaba entrar a máquinas de oficina que están prendidas todo el día, sin pagar una herramienta comercial ni pasar las sesiones por servidores ajenos. El servidor que conecta las dos máquinas tenía que tratarse como no confiable. Y la persona del otro lado muchas veces no es técnica, así que los controles de seguridad tenían que entenderse en pantalla.

Mi rolPrimero diseñé el protocolo, y después construí el visor, el host y el servidor contra él.
(02) Resultados
73mensajes del protocolo, cada uno con su schema JSON y un ejemplo verificado
326tests de Rust que pasan entre los crates de cripto, host y visor
12capacidades opcionales que se negocian por sesión sobre un núcleo congelado
(03) Arquitectura

Tres decisiones que lo definieron.

01

Un contrato escrito antes que el código

Por qué. PROTOCOL.md define cada mensaje, el modelo de amenaza y el orden real de una conexión. Los schemas y los ejemplos se generan desde ahí, y el CI verifica que no se desincronicen. El visor, el host y el servidor se construyeron en paralelo contra el mismo documento. Lo nuevo entra como capacidad, así que nada viejo se rompe.

El costo. El núcleo está congelado, así que un cambio de verdad ahí exige un pase coordinado en las tres partes. Los pedidos esperan anotados en un archivo hasta entonces.

02

El visor dibuja la confianza, no la decide

Por qué. El ID del equipo lo asigna el servidor, así que no prueba nada. La verificación del fingerprint es la única defensa real, y la pantalla la trata así: 16 celdas numeradas para leer en voz alta por teléfono, y un estado rojo cuando un equipo conocido aparece con otra clave. La decisión de confianza la toma el core en Rust. React sólo la dibuja, porque el código de un webview se puede editar en caliente.

El costo. Cada pantalla depende de un comando de Tauri. Un test lee los dos lados y falla si el front invoca un comando que el core en Rust nunca registró, algo que si no aparecería recién como un botón que no hace nada.

03

Honesto sobre qué va cifrado

Por qué. El input, la terminal, los archivos y el portapapeles van cifrados de punta a punta. El video usa el cifrado propio de WebRTC, que un servidor hostil en teoría podría interceptar. Por eso los fingerprints DTLS entran en el handshake firmado: si el servidor manipula la conexión, la sesión se corta antes del primer cuadro. La pantalla de conexión lo dice con palabras simples cuando la sesión pasa por el relay.

El costo. El video no va cifrado de punta a punta, y el producto nunca dice que sí. Hacerlo necesita insertable streams en los dos lados, y es un proyecto aparte.

(04) Galería
Verificar el equipo
Verificar el equipo · La primera conexión a un equipo. El fingerprint es una grilla para cotejar, con un código corto para leer en voz alta.
La identidad cambió
La identidad cambió · Un equipo conocido con otra clave. Es la alarma más fuerte de la app, así que va en rojo y el botón seguro va primero.
Conectando
Conectando · Cada paso de la conexión, con su detalle. Acá falló la ruta directa y la sesión pasa por el relay.
Primer arranque
Primer arranque · El visor explica de dónde salió su identidad antes que nada: el par de claves, el número y el código.
(05) Qué haría después
01Recorrer el flujo completo desde el visor en máquinas Windows reales. Hoy la verificación de punta a punta corre desde un probe de línea de comandos.
02Firmar los instaladores, para que SmartScreen de Windows deje de bloquearlos.
03Volver a pedir una contraseña por equipo, con un límite de intentos que el cliente no pueda reiniciar generando otra identidad.
Próximo proyectoMaderera Juan B. Justo →
Nahuel SantillánES