Cómo alojar un relay de RustDesk en tu VPS
Configura hbbs y hbbr de RustDesk en tu VPS con clave Ed25519, etiquetas de imagen fijadas, puertos restringidos y cálculo del ancho de banda.
Qué es un servidor relay de RustDesk autohospedado
Un servidor relay de RustDesk autohospedado consta de dos daemons en un VPS. hbbs es el servidor de ID y rendezvous: registra el ID de cada cliente y pone en contacto a dos clientes. hbbr es el servidor relay: transporta los bytes de la sesión, pero sólo en las sesiones que no pudieron comunicarse directamente. La mayoría de las guías instalan ambos daemons, permiten emparejarlos y terminan ahí. Lo que sigue cubre el resto del trabajo: la clave que controla el acceso, los puertos, la actualización y el ancho de banda.
Ambos daemons se distribuyen en la misma imagen, rustdesk/rustdesk-server, y en la configuración siguiente ambos leen el mismo par de claves Ed25519 desde el mismo directorio. Esto se configura explícitamente; no es el comportamiento predeterminado: hbbs carga o genera el par por su cuenta, pero hbbr ignora las claves si no se inicia con una. Ed25519 es un esquema de firma con clave pública. Ese par de claves determina con qué clientes se comunicará el servidor y no existe una base de datos de usuarios detrás de él.
hbbs y hbbr: qué daemon consume el ancho de banda
El tráfico de hbbs es reducido y constante: el registro de ID y los mensajes de latido, además del breve intercambio que presenta entre sí a dos pares. Se ejecuta todo el día y apenas consume ancho de banda.
El tráfico de hbbr es la propia sesión. Los fotogramas de pantalla viajan en una dirección, el teclado y el ratón en la otra, y cada byte retransmitido llega a su VPS y vuelve a salir de él. Si su proveedor contabiliza únicamente el tráfico saliente, una sesión retransmitida le cuesta aproximadamente la velocidad de la sesión. Si contabiliza la transferencia total, el coste es aproximadamente el doble.
El relay es una vía de reserva, no la ruta normal. Primero, hbbs intenta conectar directamente los dos clientes mediante hole punching a través del NAT (network address translation) situado delante de cada uno. Si funciona, la sesión nunca pasa por hbbr y no consume su cuota de transferencia. Si un extremo está detrás de un NAT que asigna un puerto nuevo para cada destino, o de un firewall que descarta la ruta creada mediante hole punching, la sesión recurre a hbbr y cada fotograma atraviesa su VPS.
Una variable de entorno elimina esta elección. ALWAYS_USE_RELAY=Y en hbbs fuerza todas las sesiones a pasar por hbbr. La documentación de RustDesk la muestra en uno de sus ejemplos de Compose, por lo que se copia con frecuencia. Hace que las conexiones sean más predecibles y convierte el tráfico saliente en un consumo real. Establézcala porque usted lo ha decidido, no porque la haya pegado sin más.
Qué puertos necesita un servidor RustDesk autohospedado
Los números de puerto siguientes se comprobaron con la documentación del servidor RustDesk y el repositorio rustdesk-server el 10 de octubre de 2026.
- TCP 21115, en hbbs: prueba del tipo de NAT.
- UDP 21116, en hbbs: registro del ID y mensajes de latido. Esta es la ruta que usa un cliente de forma predeterminada.
- TCP 21116, en hbbs: registro del ID para clientes configurados para usar sólo TCP, además de la perforación de puertos TCP y el servicio de conexión.
- TCP 21117, en hbbr: relay. Este es el puerto que transporta los datos de sesión, por lo que es el puerto que genera costes.
- TCP 21118 en hbbs y TCP 21119 en hbbr: WebSocket, usado por el cliente del navegador. Mantenga ambos cerrados si no lo utiliza.
- TCP 21114 es el servidor de la API HTTP en RustDesk Server Pro. La compilación de código abierto no escucha en este puerto.
Instalar hbbs y hbbr con la etiqueta de imagen fijada
services:
hbbs:
container_name: hbbs
image: rustdesk/rustdesk-server:1.1.16
command: hbbs
volumes:
- ./data:/root
network_mode: "host"
depends_on:
- hbbr
restart: unless-stopped
hbbr:
container_name: hbbr
image: rustdesk/rustdesk-server:1.1.16
command: hbbr -k _
volumes:
- ./data:/root
network_mode: "host"
restart: unless-stoppedmkdir -p ~/rustdesk
cd ~/rustdesk
# save the block above as ~/rustdesk/compose.yml before this line
sudo docker compose up -d
sudo docker compose psAmbos servicios deben leer running. Confirme que los listeners existan antes de modificar el firewall.
sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'Debería ver listeners TCP en 21115, 21116 y 21117, y un listener UDP en 21116. Si falta la línea UDP, significa que hbbs no está en ejecución, porque hbbs abre ese listener al iniciarse y es el que los clientes usan para registrarse de forma predeterminada.
Hay cuatro elementos deliberados en ese archivo. La etiqueta es 1.1.16, que sigue siendo la versión actual en octubre de 2026 y se publicó el 20 de julio de 2026, en lugar de latest, porque latest significa cualquier versión publicada más recientemente y un docker compose pull dentro de seis meses podría entregarle un servidor que nunca ha probado. network_mode: "host" enlaza directamente las interfaces del host. Esto es lo que recomienda la documentación de RustDesk y determina cómo se comporta el firewall. ./data:/root asigna el directorio de trabajo de la imagen al host, por lo que el par de claves queda en una ubicación de la que puede hacer copias de seguridad. hbbr -k _ es el único cambio respecto al ejemplo ascendente, porque la configuración predeterminada deja el relay abierto a cualquiera. Si Compose es nuevo para usted, ejecutar Docker Compose en un VPS explica el formato del archivo y los comandos del ciclo de vida.
Si hbbr se traslada alguna vez a un segundo servidor, debe indicar a hbbs dónde se encuentra: pase -r relay.example.com:21117 o establezca la variable de entorno RELAY-SERVERS. En un único servidor no es necesario.
El par de claves Ed25519 controla el acceso
En el primer arranque, hbbs genera id_ed25519 y id_ed25519.pub en su directorio de trabajo. Con el montaje anterior, ambos archivos aparecen en el host.
ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pubid_ed25519.pub contiene una cadena base64. Esa cadena se introduce en el campo Key de todos los clientes. id_ed25519 es la parte privada y nunca sale del servidor. La clave pública no es un secreto, porque se copia en la configuración de todos los clientes. La clave privada sí es secreta: cualquiera que la tenga puede poner en marcha un servidor en el que confiarían sus clientes.
Haga una copia de seguridad de ambos archivos ahora, antes de configurar veinte clientes.
sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgzCopie ese archivo comprimido fuera del servidor. Este es el motivo por el que este paso importa más que cualquier otro. Si elimina ~/rustdesk/data o reconstruye el servidor en un VPS nuevo sin copiarlo, hbbs genera un par de claves nuevo en el siguiente arranque. Todos los clientes siguen teniendo la clave pública antigua, por lo que hbbs la rechaza y el cliente queda desconectado. Ejecute sudo cat ~/rustdesk/data/id_ed25519.pub y compárelo con el campo Key de cualquier cliente: las dos cadenas ya no coinciden, y esa discrepancia es la causa completa del fallo. Para corregirlo, debe editar la configuración manualmente en cada máquina, incluidas las máquinas a las que confiaba en acceder mediante RustDesk.
La clave no es la contraseña de sesión. Confundir ambas hace que algunas personas omitan una de ellas. La clave determina con qué clientes se comunicará el servidor. La contraseña permanente o el código de un solo uso de la máquina controlada determina quién puede abrir una sesión en esa máquina. Necesita ambas cosas. Tener una no compensa que la otra sea débil.
Por qué un relay sin autenticación es un problema
De forma predeterminada, hbbr no comprueba nada. La documentación de configuración de RustDesk lo indica directamente: una clave vacía permite que los clientes sin una clave coincidente usen el relay. El valor predeterminado vacío existe para que los usuarios nuevos no encuentren errores de incompatibilidad de claves durante la primera ejecución. El coste es que cualquiera que encuentre tu dirección en TCP 21117 puede enviar el tráfico de su sesión a través de tu VPS, consumiendo tu cuota de transferencia y usando tu dirección IP.
command: hbbr -k _ corrige este problema. El argumento _ indica a hbbr que cargue un par de claves desde su directorio de trabajo o que lo genere si no existe. Como ambos contenedores montan el mismo ./data, se trata del mismo par que usa hbbs. No se copia nada manualmente, por lo que las claves no pueden quedar desincronizadas.
El volumen compartido es la parte que suele configurarse mal. Si asignas a hbbr su propio directorio, generará un par de claves diferente. Entonces hbbs y hbbr no coincidirán, todas las sesiones retransmitidas fallarán y las sesiones directas seguirán funcionando. El síntoma resulta confuso: RustDesk conecta con algunos pares y no con otros, según si la perforación de NAT tuvo éxito. Un único ls -l ~/rustdesk/data/ que muestre un solo par de id_ed25519 descarta esa incompatibilidad. No demuestra que el relay compruebe las claves, porque hbbr ignora esos archivos si no se inició con una clave no vacía. Por tanto, confirma también el comando del proceso en ejecución:
ps -eo args | grep '[h]bbr'Debe mostrar hbbr -k _. Un hbbr sin argumentos indica que el relay sigue abierto, independientemente de lo que haya en el directorio.
Dirija los clientes a su servidor
En cada equipo, abra RustDesk, vaya a Settings, después a Network y, por último, a ID/Relay Server.
- ID Server: el nombre de host del servidor, por ejemplo
rustdesk.example.com. El cliente usa el puerto 21116, salvo que indique otro. - Relay Server: déjelo vacío cuando hbbr se ejecute en el mismo host que hbbs.
- API Server: déjelo vacío. El servidor de código abierto no proporciona este servicio.
- Key: la cadena base64 de
id_ed25519.pub, pegada exactamente y sin espacios finales.
La ventana principal debería indicar que el cliente está listo. Si no lo hace y el cliente usa la configuración predeterminada, la causa habitual es que UDP 21116 no llega a hbbs, porque ese es el puerto que usa un cliente predeterminado para registrarse y enviar su heartbeat. Sin embargo, un ID sin conexión no lo demuestra por sí solo. Un cliente con la opción disable-udp establecida en Y se registra mediante TCP 21116 y no usa UDP 21116. En ese caso, compruebe primero TCP 21116.
Restringir los puertos para que el relay no sea un servicio expuesto
Como los contenedores usan la red del host, no hay ninguna regla NAT de Docker delante de ellos, por lo que las reglas de ufw se aplican como espera.
sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numberedAñada 21118:21119/tcp sólo si ejecuta el cliente de navegador. Mantenga abierta una segunda sesión SSH mientras habilita ufw, para que un error en la regla de SSH no le bloquee el acceso a su propio servidor. Conceptos básicos del firewall ufw para un VPS explica las políticas predeterminadas y el orden de las reglas.
Ahora viene el problema. Si cambia a la publicación de puertos mediante un bloque ports:, como hacen muchos ejemplos de RustDesk con un solo contenedor, Docker escribe sus propias reglas DNAT y los paquetes llegan al contenedor sin pasar por la cadena donde se aplican las reglas de ufw. Por tanto, una regla de denegación de ufw para 21117 no tiene efecto, y el relay queda expuesto a Internet aunque ufw status indique lo contrario. Los puertos publicados por Docker evitan ufw explica el orden de las cadenas. La red del host evita por completo este problema. Si publica un puerto, asígnelo a una sola dirección, como en "127.0.0.1:21118:21118" detrás de un proxy inverso.
Restringir por dirección de origen sólo funciona cuando los clientes tienen direcciones estables.
sudo ufw allow from 203.0.113.0/24 to any port 21115:21117 proto tcp
sudo ufw allow from 203.0.113.0/24 to any port 21116 proto udpLos portátiles conectados a redes de hoteles no tienen direcciones estables. Por eso, en este caso, la clave de hbbr tiene un efecto más importante que el firewall.
Actualizar la pila que contiene la clave
La clave se encuentra en el bind mount, no dentro del contenedor. Por tanto, la actualización es segura siempre que no modifique ./data.
- Haga primero una copia de seguridad del directorio de datos:
sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data. - Lea las notas de la versión de la nueva etiqueta en la página de versiones de rustdesk-server.
- Edite
compose.ymly cambie las dos líneasimage:a la nueva etiqueta. - Ejecute
sudo docker compose pully, después,sudo docker compose up -d. - Ejecute
sudo cat ~/rustdesk/data/id_ed25519.puby confirme que la cadena coincide con la que ya tienen los clientes.
El paso 5 es la comprobación importante. Una clave modificada no genera avisos en el servidor y desconecta todos los clientes al mismo tiempo. Para revertir el cambio, vuelva a especificar la etiqueta anterior y ejecute up -d de nuevo. Esto sólo funciona porque fijó la etiqueta: con latest, docker compose pull movió el nombre a la nueva imagen, por lo que ya no queda ninguna etiqueta que identifique la anterior.
La forma habitual de perder la clave no es docker compose down, que deja intacto el bind mount. Lo habitual es migrar a un VPS nuevo y copiar sólo compose.yml. Copie también ./data.
Supervise el tráfico saliente en un plan con una cuota de transferencia
hbbr es la única parte de esta pila que puede consumir una cuota de transferencia. La sección de preguntas frecuentes de RustDesk sitúa una conexión retransmitida en una pantalla de 1920x1080 entre 30 KB/s y 3 MB/s, y el trabajo de oficina normal alrededor de 100 KB/s. Son cifras publicadas para una sola sesión, no una medición de su configuración. Proyectadas durante sesenta horas al mes, dos horas al día, quedan así.
Los datos de este gráfico
[
{
"label": "Low end, 30 KB/s",
"gb_per_month": 6.5
},
{
"label": "Office work, 100 KB/s",
"gb_per_month": 21.6
},
{
"label": "High end, 3 MB/s",
"gb_per_month": 648
}
]Con la tasa de trabajo de oficina, una sesión consume aproximadamente 21.6 GB al mes, una cantidad que ningún plan notará. En el extremo superior del intervalo publicado, las mismas sesenta horas consumen 648 GB, y dos sesiones simultáneas a esa tasa superan una cuota de 1 TB dentro del mes. El extremo inferior es de 6.5 GB. Aquí, los gigabytes equivalen a 1000 MB, que es la forma habitual de contabilizar las cuotas de transferencia.
docker stats no desglosa este tráfico, porque un contenedor que usa la red del host comparte el espacio de nombres de red del host, por lo que sus contadores son los contadores del host. Hay otras dos herramientas que sí sirven. vnstat mide todo el servidor:
sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -mTodo el servidor significa todo el servidor: si este VPS también ejecuta algo que mueve datos reales, por ejemplo uno de los servidores de fotos autoalojados que cada noche carga las bibliotecas de los teléfonos, esas cargas se contabilizan en la misma cuota mensual que el tráfico de retransmisión. Un servidor multimedia presenta el mismo problema en sentido contrario, porque algo como Halcyon, que convierte una biblioteca de Jellyfin en una videoteca de los años 90 que se puede explorar transmite contenido a quien lo está viendo, y ese tráfico saliente consume la misma cuota de la que depende la retransmisión.
Un contador de nftables mide específicamente la retransmisión:
sudo nft add table inet relaymeter
sudo nft add chain inet relaymeter out '{ type filter hook output priority 0 ; }'
sudo nft add rule inet relaymeter out tcp sport 21117 counter
sudo nft list table inet relaymeterEsa regla no aplica ninguna decisión, por lo que cuenta los paquetes y bytes sin modificar lo que está permitido. Además, se encuentra en una tabla independiente y no interfiere con ufw. No es persistente: coloque las mismas líneas en /etc/nftables.conf si quiere recuperarla después de un reinicio. El contador sólo aumenta mientras se está retransmitiendo una sesión. Si sigue aumentando cuando ninguno de sus equipos está conectado, significa que alguien más ha encontrado su relay. Ese es precisamente el caso que hbbr -k _ evita. Como no revisará nft list todas las mañanas, configure una tarea de cron que compare el recuento de bytes con un umbral y envíe una alerta push cuando lo supere. Para ello puede usar su propio servidor ntfy.
hbbr también tiene límites de velocidad que puede reducir. SINGLE_BANDWIDTH usa de forma predeterminada 128 Mb/s por conexión retransmitida y TOTAL_BANDWIDTH usa 1024 Mb/s para todas ellas. Al establecer SINGLE_BANDWIDTH=8, una sesión queda limitada a cerca de 1 MB/s. Esto limita la velocidad, no el total mensual. Úselo para evitar que una sesión sature el enlace, no como control del presupuesto.
Cuando no necesita ningún relay
En una configuración personal, la respuesta directa es que quizá no necesite nada de esto. Conecte ambas máquinas a una VPN en malla y conéctese directamente a la dirección del túnel. No habrá hbbs, hbbr, tráfico de salida por relay ni ningún contenedor en un VPS que actualizar.
En la máquina que quiere controlar, habilite el acceso IP directo en la configuración de seguridad de RustDesk. El campo del puerto tiene el valor predeterminado 21118. Compruebe que esté escuchando antes de intentar conectarse:
ss -tlnp | grep 21118Después, conéctese a la dirección VPN de ese peer en lugar de usar un ID. La FAQ de RustDesk indica que la conexión de este modo no está cifrada, por lo que debe ejecutarlo dentro del túnel y nunca a través de Internet abierta. El túnel es el que proporciona el cifrado.
Elija según quién sea el propietario de las máquinas. Un hbbs y un hbbr autohospedados son adecuados cuando administra máquinas que no son suyas o equipos de personas que nunca instalarán un cliente VPN, porque en su lado de la configuración sólo necesitan un ID y una contraseña. Una VPN en malla con acceso IP directo es adecuada cuando todas las máquinas le pertenecen y pueden usar una clave. WireGuard comparado con Tailscale explica las dos formas habituales de crear esa malla, y ejecutar un escritorio remoto en un VPS Linux cubre el otro caso: cuando la máquina en la que quiere ver una pantalla es el propio servidor.
FAQ
¿Todas las sesiones de RustDesk pasan por mi relay?
No. hbbs intenta conectar primero los dos clientes directamente mediante hole punching a través del NAT situado delante de cada uno. Sólo las sesiones en las que falla este intento recurren a hbbr, y sólo esas consumen ancho de banda. La excepción es ALWAYS_USE_RELAY=Y en hbbs, que fuerza el paso de todas las sesiones por hbbr aunque exista una ruta directa. Si esa variable está definida en el archivo Compose, cada byte de cada sesión se incluye en el coste de transferencia.
¿Dónde se almacena la clave del servidor RustDesk y qué ocurre si la pierdo?
hbbs genera id_ed25519 y id_ed25519.pub en su directorio de trabajo durante el primer arranque. Ese directorio es /root dentro de la imagen oficial. Por tanto, con el montaje de volumen mostrado arriba, los archivos aparecen en ./data en el host. Haga una copia de seguridad de ambos archivos fuera del servidor. Si se pierden, hbbs genera un nuevo par durante el siguiente arranque y rechaza a todos los clientes que aún tengan la clave pública anterior. No existe otra forma de recuperación que editar manualmente el campo Key en cada cliente.
¿Qué puertos debo abrir para un servidor RustDesk autohospedado?
TCP 21115, 21116 y 21117, además de UDP 21116. hbbs usa 21115 para la prueba del tipo de NAT y 21116 para el registro del ID y el heartbeat mediante UDP, así como para el registro y el hole punching mediante TCP. hbbr usa 21117 para el relay. TCP 21118 y 21119 son los puertos WebSocket del cliente de navegador. Déjelos cerrados si no lo utiliza. TCP 21114 pertenece al servidor de la API HTTP de Pro y no es necesario en la compilación de código abierto.
¿Pueden usar desconocidos mi relay RustDesk autohospedado?
Sí, si ejecuta hbbr con su configuración predeterminada. La documentación de RustDesk indica que una clave vacía permite usar el relay a clientes que no tienen una clave coincidente. Por tanto, cualquiera que conozca su nombre de host y el puerto 21117 puede enviar tráfico a través del servidor. Ejecute hbbr con -k _ para que cargue el mismo par de claves que utiliza hbbs desde el volumen compartido ./data. Después, sólo los clientes configurados con su clave pública podrán usar su relay.