Cliente RDP web hecho con Go WebAssembly y grdp
(github.com/nakagami)- Es un cliente RDP basado en web que permite conectarse al Escritorio remoto de Windows solo con el navegador y funciona sin plugins
- Separa Go WebAssembly en el navegador y un proxy WebSocket a TCP del lado del servidor, para encargarse en su lugar de la conexión TCP de RDP que el navegador no puede abrir directamente
- La conexión sigue el flujo
Browser -> WebSocket -> proxy -> TCP -> RDP Server; después de conectarse, la pantalla remota se muestra en canvas y se transmiten las entradas de teclado y mouse - Los dispositivos de entrada admiten teclado basado en RDP scan codes y mouse con movimiento, clic y rueda; el audio remoto se recibe por RDPSND y se reproduce con la Web Audio API
- Como la estructura del proxy permite todos los origin, debe ejecutarse solo en una red confiable o colocarse junto con HTTPS/WSS y una capa de autenticación antes de exponerlo externamente
Descripción general del proyecto
- Funciona como un cliente RDP basado en web para conectarse al Escritorio remoto de Windows desde el navegador sin plugins
- La implementación está hecha con la combinación de Go WebAssembly y grdp, con una arquitectura separada entre la parte que corre en el navegador y la parte de retransmisión del proxy
- Como el navegador no puede abrir sockets TCP raw directamente, también se necesita un proxy ligero en Go que conecte la conexión WebSocket con el puerto TCP del servidor RDP
Arquitectura y modo de funcionamiento
- La ruta completa sigue el orden
Browser (WASM) -> WebSocket -> proxy (Go) -> TCP -> RDP Server - En el navegador se ejecuta el binario WASM, y el proxy cumple a la vez el papel de puente WebSocket a TCP y de servidor de archivos estáticos
- El resultado de
make allse divide enstatic/main.wasm, que se ejecuta en el navegador,static/wasm_exec.js, el archivo de soporte del runtime de Go, yproxy/proxy, el servidor proxy - Gracias a esta estructura, el lado del navegador maneja la conexión con tecnologías web estándar, mientras que el proxy se encarga de la comunicación TCP real con el servidor RDP
Flujo de uso e interfaz de usuario
- En el navegador, abre
http://localhost:8080, ingresa los valores de Host, Port, Domain, User, Password, Width, Height en el formulario de conexión y luego pulsa Connect para iniciar la sesión - El valor predeterminado de Port es
3389, y Domain puede dejarse vacío si se usa una cuenta local - Cuando la conexión se completa, el escritorio remoto se muestra en canvas y, para recibir entrada del teclado, hay que hacer clic en el canvas
- Al pulsar Disconnect, la sesión termina
Dispositivos de entrada y soporte de audio
- Toda la entrada de teclado estándar se transmite al escritorio remoto mediante RDP scan codes
- El mouse admite movimiento, clic de botones y rueda de desplazamiento
- La pestaña del navegador debe tener el foco para que se transmitan los eventos de teclado, y si las teclas dejan de responder, hay que volver a hacer clic en el área de canvas
- El audio remoto se transmite por RDPSND y en el navegador se reproduce con la Web Audio API
- El formato de audio se especifica como PCM 44100 Hz, stereo, 16-bit signed little-endian
Condiciones de operación y consideraciones de seguridad
- Los requisitos son Go 1.24 o superior y un servidor RDP accesible; el servidor de destino puede ser Windows o cualquier host compatible con RDP
- El proxy permite conexiones desde todos los origin, por lo que debe ejecutarse solo en una red confiable o añadirse una capa de autenticación antes de exponerlo a Internet
- Como las credenciales se envían del navegador al proxy por WebSocket, en redes no confiables es necesario usar HTTPS/WSS
- El README también menciona la opción de usar nginx o Caddy como reverse proxy con terminación TLS
Formas de ejecución e información adicional
- Puede ejecutarse con
make serveo con./proxy/proxy -listen :8080 -static static - Las opciones del proxy usan
-listenpara especificar la dirección y puerto de escucha, y-staticpara indicar el directorio de archivos estáticos - Los targets para desarrollo se dividen en
make wasmpara recompilar solo el WASM,make proxypara recompilar solo el proxy,make wasm_execpara actualizarwasm_exec.js, ymake cleanpara borrar los artefactos generados - La licencia es GPLv3 y se incluye una referencia a grdp LICENSE
2 comentarios
Pero la verdad no le veo la ventaja.
Al final no es más que un cliente, así que del lado del servidor tampoco se puede imponer ningún requisito.
Y tampoco es que se pueda acceder solo con un navegador puro.
Comentarios en Hacker News
Se ve bastante bien. Si además le agregan soporte para grabación de sesión y autenticación SSO, podría usarse de inmediato como jump host de RDP.
He usado algo parecido con Azure Bastion: inicias sesión en el portal de Azure con el método de autenticación configurado en el tenant, luego te conectas por RDP a la VM desde el navegador y entras con una cuenta local de la VM. El manejo de archivos y portapapeles funciona bastante bien, y también soporta sesiones de consola dentro del navegador.
No sé si aplica al lado de Windows/RDP porque no lo he usado, pero el SSH en navegador de GCP ha sido de lo mejor que he visto hasta ahora.
En Linux también he sentido a veces que xrdp es mejor que otras alternativas.
Uno de los grandes valores que resuelve esto es la separación de la interfaz de administración de la VM/servidor. Solo con evitar que el servicio de administración del servidor web esté en la misma IP/dominio/interfaz que el servicio HTTP, la seguridad mejora muchísimo.
El portapapeles en RDP desde navegador es una pesadilla silenciosa. La negociación del protocolo en sí funciona bien, pero la Clipboard API del navegador está atada a permisos y requisitos de gesto del usuario.
Del lado de lectura, la mayoría de los navegadores casi siempre le piden confirmación al usuario. Por eso terminas creando un búfer de portapapeles aparte dentro de la página, o bien pegar hacia dentro del RDP funciona de forma fluida, pero para copiar hacia fuera del RDP tienes que aceptar un clic cada vez.
Ninguna de las dos opciones se acerca a cómo la gente espera que funcione un cliente web de RDP. Antes de decir que está al nivel de
mstscnativo, hay que revisar bien cómo se comporta distinto en Chrome y Firefox.Como HP está abandonando Anyware / Teradici / PCoIP, bastante gente está buscando alternativas. Hace falta especialmente algo con soporte para múltiples monitores de alta resolución, 60fps, reproducción con alta profundidad de bits, compatibilidad con tabletas Wacom y soporte para los 3 sistemas operativos.
Del lado de pago están Parsec y DCV, y da gusto ver intentos de código abierto. Hay proyectos como rustdesk, kyber y teraguchi, así que la comunidad realmente necesita una opción open source de alto rendimiento.
https://github.com/rustdesk/rustdesk
https://github.com/thedepartmentofexternalservices/teraguchi
https://kyber.tech/
Se ve interesante técnicamente, pero sorprende que no mencionen la función más importante. Me pregunto qué tan bien funciona en la práctica el portapapeles compartido.
El portapapeles compartido y la carga/descarga mediante unidades compartidas son funciones de FreeRDP, así que se pueden aprovechar con relativa facilidad.
Y la grabación de sesión es innegociable en entornos PAM.
[1] https://adaptive.live
El escalado de escritorio, el soporte multimonitor, la transferencia de archivos, la redirección de unidades y la redirección de periféricos también son importantes.
Me pregunto si esto también funciona al abrir archivos RDP recibidos desde CyberArk PAM.
También me pregunto si el cliente RDP puede capturar Alt-Tab dentro de una pestaña del navegador.
Antes, ese era el mayor problema del RDP en navegador de Guacamole.
Es interesante desde el punto de vista técnico, pero como ya existen clientes RDP nativos para casi todas las plataformas, no me queda claro por qué haría falta esto.
https://guacamole.apache.org/