Come ospitare un relay server RustDesk
Esegui hbbs e hbbr sul tuo VPS: configura la chiave Ed25519, usa tag image fissati, limita le porte e calcola la banda relay inclusa nel piano.
Che cos’è un server relay RustDesk self-hosted
Un server relay RustDesk self-hosted è composto da due demoni eseguiti su un unico VPS. hbbs è il server ID e rendezvous: registra l’ID di ogni client e mette in contatto due client. hbbr è il server relay: trasporta i byte della sessione, ma solo per le sessioni che non sono riuscite a comunicare direttamente. La maggior parte delle guide installa entrambi i componenti, completa l’associazione e si ferma qui. Il resto del lavoro comprende la chiave che controlla l’accesso, le porte, l’aggiornamento e la larghezza di banda.
Entrambi i demoni sono inclusi nella stessa immagine, rustdesk/rustdesk-server, e nella configurazione seguente leggono la stessa coppia di chiavi Ed25519 dalla stessa directory. Questo comportamento va configurato e non è predefinito: hbbs carica o genera autonomamente la coppia, mentre hbbr ignora le chiavi se non viene avviato specificandone una. Ed25519 è uno schema di firma a chiave pubblica. La coppia di chiavi determina con quali client il server comunicherà e non esiste un database degli utenti.
hbbs e hbbr: quale daemon consuma la tua larghezza di banda
Il traffico di hbbs è ridotto e costante: registrazione degli ID e heartbeat, oltre al breve scambio che presenta tra loro due peer. Il servizio rimane attivo tutto il giorno e ha un costo quasi nullo.
Il traffico di hbbr corrisponde alla sessione vera e propria. I fotogrammi dello schermo viaggiano in una direzione, la tastiera e il mouse nell’altra, e ogni byte inoltrato arriva al tuo VPS e poi ne esce. Se il provider misura solo il traffico in uscita, una sessione inoltrata ti costa circa quanto il traffico della sessione. Se misura il trasferimento totale, il costo è circa il doppio.
Il relay è un percorso di fallback, non quello normale. hbbs prova prima a collegare direttamente i due client, usando il hole punching attraverso il NAT (network address translation) presente davanti a ciascuno di essi. Quando funziona, la sessione non passa mai da hbbr e il limite di trasferimento non viene consumato. Se un lato si trova dietro un NAT che assegna una porta diversa per ogni destinazione, oppure dietro un firewall che blocca il percorso creato dal hole punching, la sessione passa a hbbr e ogni fotogramma attraversa il tuo VPS.
Una variabile d’ambiente elimina questa scelta. ALWAYS_USE_RELAY=Y su hbbs forza il passaggio di ogni sessione attraverso hbbr. La documentazione di RustDesk la mostra in uno degli esempi Compose, quindi viene copiata spesso. In questo modo le connessioni diventano più prevedibili, ma il traffico in uscita diventa effettivo. Impostala perché hai deciso di farlo, non perché l’hai incollata.
Quali porte sono necessarie per un server RustDesk self-hosted
I numeri di porta riportati di seguito sono stati verificati nella documentazione del server RustDesk e nel repository rustdesk-server il 10 ottobre 2026.
- TCP 21115, su hbbs: test del tipo di NAT.
- UDP 21116, su hbbs: registrazione dell'ID e heartbeat. È il percorso usato per impostazione predefinita da un client.
- TCP 21116, su hbbs: registrazione dell'ID per i client configurati per usare soltanto TCP, oltre a TCP hole punching e al servizio di connessione.
- TCP 21117, su hbbr: relay. Questa è la porta che trasferisce i dati della sessione, quindi è la porta che genera costi.
- TCP 21118 su hbbs e TCP 21119 su hbbr: WebSocket, usato dal client browser. Lasciate entrambe le porte chiuse se non utilizzate questa funzione.
- TCP 21114 è il server API HTTP in RustDesk Server Pro. La build open source non è in ascolto su questa porta.
Installare hbbs e hbbr con il tag dell’immagine bloccato
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 psEntrambi i servizi devono leggere running. Verificare che i listener siano presenti prima di modificare il firewall.
sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'Dovrebbero essere presenti listener TCP sulle porte 21115, 21116 e 21117 e un listener UDP sulla porta 21116. Se manca la riga UDP, hbbs non è in esecuzione: hbbs apre quel listener all’avvio ed è quello verso cui i client si registrano per impostazione predefinita.
Nel file, quattro elementi sono impostati intenzionalmente. Il tag è 1.1.16, ancora la release corrente a ottobre 2026, pubblicata il 20 luglio 2026, invece di latest, perché latest indica qualunque versione sia stata pubblicata più di recente e un docker compose pull tra sei mesi potrebbe fornirti un server che non hai mai testato. network_mode: "host" associa direttamente le interfacce dell’host, come raccomandato dalla documentazione di RustDesk, e determina il comportamento del firewall. ./data:/root associa la directory di lavoro dell’immagine all’host, in modo che la coppia di chiavi venga salvata in un percorso di cui puoi eseguire il backup. hbbr -k _ è invece l’unica modifica rispetto all’esempio upstream, perché la configurazione predefinita lascia il relay aperto a chiunque. Se Compose è una novità, eseguire Docker Compose su un VPS illustra il formato del file e i comandi per gestire il ciclo di vita.
Se hbbr viene spostato su un secondo server, è necessario indicare a hbbs la nuova posizione: passare -r relay.example.com:21117 oppure impostare la variabile d’ambiente RELAY-SERVERS. Su un singolo server non è necessario.
La coppia di chiavi Ed25519 controlla l'accesso
Al primo avvio, hbbs genera id_ed25519 e id_ed25519.pub nella directory di lavoro. Con il mount precedente, entrambi i file sono disponibili sull'host.
ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pubid_ed25519.pub contiene una stringa base64. Inserisci questa stringa nel campo Key di ogni client. id_ed25519 è la parte privata e non deve mai lasciare il server. La chiave pubblica non è un dato segreto, perché viene copiata nella configurazione di ogni client. La chiave privata è invece un secret: chiunque ne disponga può avviare un server considerato attendibile dai client.
Esegui subito il backup di entrambi i file, prima di configurare venti client.
sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgzCopia l'archivio al di fuori del server. Ecco perché questo passaggio è più importante di qualsiasi altro. Se elimini ~/rustdesk/data o ricrei il servizio su un nuovo VPS senza copiarlo, al successivo avvio hbbs genera una nuova coppia di chiavi. Ogni client contiene ancora la vecchia chiave pubblica, quindi hbbs rifiuta la connessione e il client passa offline. Esegui sudo cat ~/rustdesk/data/id_ed25519.pub e confrontalo con il campo Key di un client qualsiasi: le due stringhe non corrispondono più, e questa mancata corrispondenza è l'unica causa del problema. Per risolverlo devi modificare manualmente le impostazioni su ogni macchina, comprese quelle che contavi di raggiungere tramite RustDesk.
La chiave non è la password della sessione. Confondere i due elementi porta spesso a ignorarne uno. La chiave determina con quali client il server può comunicare. La password permanente o il codice monouso sulla macchina controllata determina chi può aprire una sessione su quella macchina. Servono entrambi; la presenza di uno non compensa la debolezza dell'altro.
Perché un relay senza autenticazione è un problema
Per impostazione predefinita, hbbr non verifica nulla. La documentazione di configurazione di RustDesk lo afferma direttamente: una chiave vuota consente ai client senza una chiave corrispondente di usare il relay. Il valore predefinito vuoto evita che i nuovi utenti ricevano errori di mancata corrispondenza della chiave al primo avvio. Il costo è che chiunque trovi il tuo indirizzo sulla porta TCP 21117 può inoltrare il traffico della propria sessione tramite il tuo VPS, consumando la tua quota di trasferimento e usando il tuo indirizzo IP.
command: hbbr -k _ risolve il problema. L'argomento _ indica a hbbr di caricare una coppia di chiavi dalla propria directory di lavoro oppure di generarne una se non esiste. Poiché entrambi i container montano lo stesso ./data, si tratta della stessa coppia usata da hbbs. Non è necessario copiare nulla manualmente, quindi le chiavi non possono divergere.
Il volume condiviso è il punto in cui si commettono più errori. Se assegni a hbbr una directory separata, il servizio genera una coppia di chiavi diversa. hbbs e hbbr utilizzano quindi chiavi non corrispondenti, tutte le sessioni inoltrate hanno esito negativo e le sessioni dirette continuano a funzionare. Il sintomo è fuorviante: RustDesk raggiunge alcuni peer ma non altri, a seconda che il hole punching abbia avuto successo. Un singolo ls -l ~/rustdesk/data/ che mostra una sola coppia id_ed25519 esclude questa mancata corrispondenza. Non dimostra però che il relay verifichi le chiavi, perché hbbr ignora questi file se non è stato avviato con una chiave non vuota. Verifica quindi anche il comando in esecuzione:
ps -eo args | grep '[h]bbr'Dovrebbe stampare hbbr -k _. Un semplice hbbr indica che il relay è ancora aperto, indipendentemente dal contenuto della directory.
Indirizzare i client al server
Su ogni macchina, aprire RustDesk, quindi Settings, Network e infine ID/Relay Server.
- ID Server: il nome host, ad esempio
rustdesk.example.com. Il client usa la porta 21116, a meno che non ne venga indicata un'altra. - Relay Server: lasciare vuoto quando hbbr viene eseguito sullo stesso host di hbbs.
- API Server: lasciare vuoto. Il server open source non ne fornisce uno.
- Key: la stringa base64 ottenuta da
id_ed25519.pub, incollata esattamente e senza spazi finali.
La finestra principale dovrebbe quindi indicare che il client è pronto. In caso contrario, se il client usa le impostazioni predefinite, la causa più comune è che UDP 21116 non raggiunga hbbs. È su questa porta che un client configurato con i valori predefiniti effettua la registrazione e invia il proprio heartbeat. Tuttavia, un ID offline non lo dimostra da solo. Un client con l'opzione disable-udp impostata su Y effettua invece la registrazione tramite TCP 21116 e non usa mai UDP 21116. Per quel client, controllare prima TCP 21116.
Limitare le porte per evitare che il relay sia un servizio aperto
Poiché i container usano la rete dell'host, davanti a essi non è presente alcuna regola Docker NAT. Le regole di ufw si applicano quindi come previsto.
sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numberedAggiungi 21118:21119/tcp solo se esegui il client browser. Mantieni aperta una seconda sessione SSH mentre abiliti ufw, in modo che un errore nella regola SSH non ti impedisca di accedere al server. Nozioni di base sul firewall ufw per un VPS descrive i criteri predefiniti e l'ordine delle regole.
Ecco il problema. Se passi alla pubblicazione delle porte con un blocco ports:, come avviene in molti esempi RustDesk con un singolo container, Docker crea regole DNAT proprie e i pacchetti raggiungono il container senza passare dalla catena in cui si trovano le regole ufw. Un divieto ufw sulla porta 21117 non ha quindi effetto e il relay resta esposto a Internet, mentre ufw status indica il contrario. Le porte pubblicate da Docker bypassano ufw spiega l'ordine delle catene. La rete dell'host evita completamente il problema. Se pubblichi una porta, vincolala a un solo indirizzo, come "127.0.0.1:21118:21118" dietro un reverse proxy.
La limitazione in base all'indirizzo sorgente funziona solo quando i client hanno indirizzi stabili.
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 udpI laptop collegati alle reti degli hotel non hanno indirizzi stabili. Per questo, in questo caso, la chiave su hbbr svolge un ruolo più efficace del firewall.
Aggiornamento di uno stack che contiene la chiave
La chiave si trova nel bind mount, non all’interno del container. L’aggiornamento è quindi sicuro purché ./data resti invariato.
- Esegui prima il backup della directory dei dati:
sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data. - Leggi le note di rilascio del nuovo tag nella pagina delle release di rustdesk-server.
- Modifica
compose.ymle sostituisci il tag con quello nuovo in entrambe le righeimage:. - Esegui
sudo docker compose pull, quindisudo docker compose up -d. - Esegui
sudo cat ~/rustdesk/data/id_ed25519.pube verifica che la stringa corrisponda a quella già presente sui client.
Il controllo del punto 5 è quello importante, perché sul server una chiave modificata non genera alcun avviso e interrompe contemporaneamente il funzionamento di tutti i client. Per eseguire il rollback, ripristina il tag precedente ed esegui di nuovo up -d. Questa procedura funziona solo perché il tag era fissato: con latest, docker compose pull ha spostato il nome sull’immagine nuova, quindi non esiste più alcun tag che identifichi quella precedente.
Il modo più comune per perdere la chiave non è docker compose down, che lascia invariato il bind mount. Il problema si verifica durante la migrazione a un nuovo VPS, quando si copia soltanto compose.yml. Copia anche ./data.
Monitorare l'egress su un piano con un limite di trasferimento
hbbr è l'unico componente di questo stack che può consumare il limite di trasferimento. Le FAQ di RustDesk indicano, per una connessione inoltrata con schermo 1920x1080, un consumo compreso tra 30 KB/s e 3 MB/s, mentre per il normale lavoro d'ufficio indicano circa 100 KB/s. Sono valori pubblicati per una singola sessione, non misurazioni del tuo ambiente. Moltiplicati per sessanta ore al mese, cioè due ore al giorno, producono questi risultati.
I dati alla base di questo grafico
[
{
"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
}
]Al ritmo del lavoro d'ufficio, una sessione consuma circa 21.6 GB al mese, un valore che nessun piano noterà. Al limite superiore dell'intervallo pubblicato, le stesse sessanta ore consumano 648 GB; con due sessioni simultanee a questa velocità, il limite di 1 TB viene superato nel corso del mese. Il limite inferiore è 6.5 GB. In questo contesto, i gigabyte sono calcolati come 1000 MB, secondo il criterio normalmente usato per i limiti di trasferimento.
docker stats non suddivide questi dati, perché un container che usa la rete dell'host condivide il namespace di rete dell'host e quindi i suoi contatori sono quelli dell'host. Sono disponibili altri due strumenti. vnstat misura l'intero server:
sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -mL'intero server significa davvero l'intero server: se questo VPS esegue anche qualcosa che trasferisce dati reali, ad esempio uno dei server fotografici self-hosted che ogni notte importa le librerie dai telefoni, i relativi upload vengono conteggiati nella stessa voce mensile del traffico inoltrato. Lo stesso vale per un media server in senso opposto: qualcosa come Halcyon, che trasforma una libreria Jellyfin in un videonoleggio degli anni '90 consultabile, trasmette contenuti agli utenti che guardano i video e questo egress condivide il limite utilizzato dal relay.
Un contatore nftables misura nello specifico il relay:
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 relaymeterQuesta regola non contiene alcun verdict, quindi conta pacchetti e byte senza modificare ciò che è consentito. Inoltre si trova in una tabella separata, quindi non interferisce con ufw. Non è persistente: inserisci le stesse righe in /etc/nftables.conf per ripristinarla dopo un riavvio. Il contatore cresce solo mentre una sessione viene effettivamente inoltrata. Se continua a crescere quando nessuno dei tuoi computer è connesso, significa che qualcun altro ha trovato il tuo relay. È proprio il caso che hbbr -k _ serve a prevenire. Poiché non leggerai nft list ogni mattina, configura un cron job che confronti il conteggio dei byte con una soglia e invii una notifica push quando la supera. Per questo puoi usare il tuo server ntfy.
hbbr dispone anche di limiti di velocità che puoi ridurre. SINGLE_BANDWIDTH ha come valore predefinito 128 Mb/s per ogni connessione relay, mentre TOTAL_BANDWIDTH ha come valore predefinito 1024 Mb/s per tutte le connessioni. Impostando SINGLE_BANDWIDTH=8, una singola sessione viene limitata a circa 1 MB/s. Questo limita la velocità, non il totale mensile. Usalo quindi per impedire che una sessione saturi il collegamento, non come strumento per controllare il budget.
Quando non serve affatto un relay
Per una configurazione personale, la risposta corretta è che potresti non aver bisogno di nulla di tutto questo. Inserisci entrambe le macchine in una VPN mesh e connettiti direttamente all'indirizzo del tunnel. Non servono hbbs, hbbr o traffico in uscita tramite relay, né un container su un VPS da aggiornare.
Sulla macchina che vuoi controllare, abilita l'accesso IP diretto nelle impostazioni di sicurezza di RustDesk. Il campo della porta è impostato per impostazione predefinita su 21118. Verifica che la porta sia in ascolto prima di tentare la connessione:
ss -tlnp | grep 21118Connettiti quindi all'indirizzo VPN del peer invece di usare un ID. Nelle FAQ di RustDesk è specificato che questa modalità non cifra la connessione. Usala quindi all'interno del tunnel e mai tramite Internet pubblico. È il tunnel a fornire la cifratura.
Scegli in base a chi possiede le macchine. Un'istanza self-hosted di hbbs e hbbr è adatta quando gestisci macchine che non sono tue o utenti che non installeranno mai un client VPN, perché sul loro lato della configurazione servono soltanto un ID e una password. Una VPN mesh con accesso IP diretto è adatta quando tutte le macchine appartengono a te e possono gestire una chiave. WireGuard a confronto con Tailscale illustra i due metodi più comuni per creare questa mesh, mentre eseguire un desktop remoto su un VPS Linux tratta l'altro caso, in cui la macchina sulla quale vuoi visualizzare una schermata è il server stesso.
FAQ
Ogni sessione RustDesk passa dal mio relay?
No. hbbs prova prima a collegare direttamente i due client, usando il NAT hole punching attraverso il NAT presente davanti a ciascun client. Solo le sessioni per cui il tentativo fallisce ricadono su hbbr, e soltanto queste consumano la vostra banda. L’eccezione è ALWAYS_USE_RELAY=Y su hbbs, che forza ogni sessione a passare da hbbr, anche quando è disponibile un percorso diretto. Se questa variabile è impostata nel file Compose, ogni byte di ogni sessione viene conteggiato nel vostro traffico trasferito.
Dove viene archiviata la chiave del server RustDesk e cosa succede se la perdo?
All’avvio iniziale, hbbs genera id_ed25519 e id_ed25519.pub nella propria directory di lavoro. Nell’immagine ufficiale, questa directory è /root; quindi, con il mount del volume mostrato sopra, i file si trovano in ./data sull’host. Eseguite il backup di entrambi i file al di fuori del server. Se vengono persi, al successivo avvio hbbs genera una nuova coppia di chiavi e rifiuta ogni client che conserva ancora la vecchia chiave pubblica. Non esiste un metodo di ripristino oltre a modificare manualmente il campo Key su ogni client.
Quali porte devo aprire per un server RustDesk self-hosted?
TCP 21115, 21116 e 21117, oltre a UDP 21116. hbbs usa 21115 per il test del tipo di NAT e 21116 per la registrazione degli ID e l’heartbeat tramite UDP, nonché per la registrazione e il hole punching tramite TCP. hbbr usa 21117 per il relay. TCP 21118 e 21119 sono le porte WebSocket per il client browser; lasciatele quindi chiuse se non lo utilizzate. TCP 21114 appartiene al server HTTP API di Pro e non è necessaria nella build open source.
Sconosciuti possono usare il mio relay RustDesk self-hosted?
Sì, se eseguite hbbr con la configurazione predefinita. La documentazione di RustDesk specifica che una chiave vuota consente ai client privi di una chiave corrispondente di usare il relay. Di conseguenza, chiunque venga a conoscenza del vostro hostname e della porta 21117 può instradare traffico attraverso il server. Eseguite hbbr con -k _, in modo che carichi la stessa coppia di chiavi utilizzata da hbbs dal volume condiviso ./data. In questo modo, solo i client configurati con la vostra chiave pubblica potranno usare il vostro relay.