Tailscale lento: relay o connessione diretta?
Scopri se Tailscale usa relay o connessione diretta con due comandi. Risolvi UDP bloccato e NAT rigido su un VPS per avvicinarti alla velocità della linea.
Perché Tailscale è lento: connessione inoltrata anziché diretta
Tailscale è lento quando la connessione viene inoltrata e raggiunge quasi la velocità massima disponibile sulla linea quando la connessione è diretta. Una connessione diretta trasporta i pacchetti WireGuard crittografati direttamente da una macchina all’altra, quindi raggiunge la velocità consentita dalle due connessioni Internet. Una connessione inoltrata invia invece ogni pacchetto prima attraverso una terza macchina, quindi eredita la latenza di quella macchina e la quota di banda che questa rende disponibile. La pagina sulle prestazioni di Tailscale lo riassume in una frase: "Le connessioni dirette garantiscono quasi sempre una latenza inferiore e un throughput maggiore."
La differenza non è visibile all’interno dell’applicazione. La copia dei file è semplicemente lenta e la sessione SSH presenta semplicemente ritardi. Il primo obiettivo è quindi verificare quale tipo di connessione è già attivo. Due comandi forniscono la risposta in meno di un minuto; tutto ciò che segue serve a correggere la causa. È utile conoscere la procedura di configurazione prima di iniziare, perché il server di coordinamento e il piano dati WireGuard sono sistemi separati e solo il piano dati trasferisce i byte.
I due comandi che distinguono una connessione diretta da una inoltrata
Invia del traffico al peer prima di eseguire qualsiasi misurazione. Tailscale costruisce il percorso su richiesta. Un peer con cui non hai comunicato oggi potrebbe non averne ancora negoziato uno, quindi leggeresti un risultato non aggiornato. È sufficiente eseguire un ping o un curl verso l'indirizzo tailnet del peer.
tailscale statusLa risposta si trova alla fine della riga di ogni peer.
100.113.160.82 device-a tagged-devices linux active; offers exit node; direct 203.0.113.9:41641
100.104.93.78 device-b you@ android active; relay "tor"direct seguito da un indirizzo e una porta indica che i pacchetti vengono inviati direttamente a quell'indirizzo. relay "tor" identifica un server DERP (designated encrypted relay for packets), cioè uno dei server di inoltro di Tailscale; tutti i pacchetti destinati a quel peer passano attraverso quel server. Un terzo valore, peer-relay, è descritto nella sezione successiva.
tailscale ping device-bUna connessione funzionante inizia come inoltrata e poi cambia. I primi pacchetti passano attraverso il server DERP più vicino mentre le due macchine negoziano, quindi il percorso cambia durante l'esecuzione:
pong from device-b (100.113.160.82) via DERP(tor) in 51ms
pong from device-b (100.113.160.82) via DERP(tor) in 48ms
pong from device-b (100.113.160.82) via 203.0.113.9:41641 in 35msL'esecuzione si interrompe perché --until-direct è impostato su true per impostazione predefinita. Una connessione che non può diventare diretta appare invece così e termina con una frase anziché con un pong:
pong from device-b (100.104.93.78) via DERP(tor) in 53ms
pong from device-b (100.104.93.78) via DERP(tor) in 60ms
direct connection not establishedL'ultima riga contiene il risultato. Indica che Tailscale ha inviato tutte le probe previste e non ha mai ottenuto un percorso diretto. Per continuare a monitorare un percorso inoltrato invece di interrompere l'esecuzione al primo percorso diretto, esegui tailscale ping --until-direct=false -c 20 device-b e leggi la distribuzione della latenza. Un percorso inoltrato mostra in genere valori più alti e una maggiore variabilità, perché combina due percorsi Internet attraverso una macchina che non controlli.
Che cosa significa peer-relay in tailscale status?
Un peer relay è una macchina della tua tailnet che inoltra il traffico per gli altri membri quando non è possibile stabilire una connessione diretta. Rimane in ascolto su una porta UDP a tua scelta e il demone lo usa preferibilmente rispetto a DERP. tailscale status contrassegna questo tipo di connessione peer-relay, mentre tailscale ping visualizza l'endpoint del relay:
pong from device-b (100.97.143.93) via peer-relay(203.0.113.42:40000:vni:1) in 4ms
direct connection not establishedLeggi attentamente l'output. Non si tratta comunque di una connessione diretta, quindi l'esecuzione termina ancora con direct connection not established. È cambiato il nodo che inoltra il traffico. Un VPS con un indirizzo IP pubblico e un'ampia disponibilità di banda è un relay molto più adatto per il tuo traffico rispetto a un nodo DERP condiviso. Per questo la funzione è importante per chi noleggia un server. Abilitala sulla macchina che dispone dell'endpoint pubblico raggiungibile:
sudo tailscale set --relay-server-port=40000Una porta 0 seleziona una porta casuale non utilizzata. Una stringa vuota disabilita il relay server. Concedi quindi ai dispositivi client l'autorizzazione a usarlo tramite la capability tailscale.com/cap/relay nel file delle policy della tua tailnet:
{
"grants": [
{
"src": ["tag:us-east-vpc"],
"dst": ["tag:us-east-relays"],
"app": {
"tailscale.com/cap/relay": []
}
}
]
}Sia il dispositivo relay sia i dispositivi client devono usare Tailscale 1.86 o una versione successiva. Prima di dedicare un'ora al file delle policy, verifica la versione con tailscale version su ciascun dispositivo. È utile memorizzare l'ordine dei tentativi del demone. Prima tenta di stabilire una connessione diretta. Se il tentativo fallisce, cerca un peer relay che sia autorizzato a usare. Se non ne trova nessuno, ripiega su DERP. DERP non viene mai escluso completamente, perché è anche il canale attraverso cui le due macchine negoziano inizialmente la connessione.
Causa 1: un firewall in uscita che blocca UDP
Tailscale documenta due motivi per cui una connessione resta inoltrata tramite relay. Il primo è UDP bloccato. Interroga direttamente la macchina:
tailscale netcheckIl report è abbreviato qui e il campo iniziale è quello decisivo:
Report:
* UDP: true
* IPv4: yes, 203.0.113.9:41641
* IPv6: no
* MappingVariesByDestIP: false
* PortMapping:
* Nearest DERP: DallasUDP: false è l'intera spiegazione quando compare questo valore. La macchina non riesce a inviare pacchetti UDP ai server probe di Tailscale. Di conseguenza non può stabilire un percorso diretto e il demone passa a DERP su TCP 443. Questo fallback spiega perché la macchina continua a sembrare perfettamente funzionante: è connessa, è raggiungibile e ogni byte viene inoltrato tramite relay.
Sono documentate due regole per il traffico in uscita. «Consenti ai dispositivi interni di avviare traffico UDP da :41641 a *:*», che corrisponde al traffico WireGuard, e «Consenti ai dispositivi interni di avviare traffico UDP verso *:3478», che corrisponde a STUN (session traversal utilities for NAT), il protocollo usato dalla macchina per determinare il proprio indirizzo e la propria porta pubblici. Usa wildcard per le destinazioni. Tailscale aggiunge periodicamente server relay e un elenco di indirizzi scritto manualmente diventerebbe errato entro un anno.
Su un server noleggiato, la causa abituale è una policy aggressiva per il traffico in uscita, ereditata da un'immagine hardened oppure applicata dal provider a monte. Controlla prima la policy predefinita per il traffico in uscita:
sudo ufw status verbose
sudo nft list rulesetDefault: deny (incoming), allow (outgoing) va bene e non è il problema. Una policy predefinita in uscita pari a deny, con un breve elenco di autorizzazioni per TCP 443 e DNS, mantiene esattamente un server su un relay in modo permanente: il percorso DERP su TCP 443 passa attraverso quella regola, mentre il percorso diretto no. La posizione effettiva di queste regole dipende da se il sistema usa iptables o nftables come livello sottostante, e modificare quella sbagliata è un modo comune per non cambiare nulla.
Anche il traffico in ingresso è importante, perché un VPS ha un indirizzo IP pubblico e può quindi rappresentare la metà più facilmente raggiungibile della coppia. Se il firewall accetta traffico UDP in ingresso sulla porta su cui tailscaled è in ascolto, i peer che si trovano dietro router domestici problematici possono raggiungerlo senza configurazioni speciali. Individua la porta effettivamente in uso:
sudo ss -lunp | grep tailscaled
sudo ufw allow 41641/udp41641 è la porta statica predefinita. In una tailnet con l'impostazione randomizeClientPort attivata, i client scelgono invece una porta casuale. In questo caso, usa il numero effettivo nell'output di ss, non quello riportato in questa pagina. Controlla quindi il pannello di controllo del provider. La maggior parte degli host utilizza un firewall di rete separato da quello interno al server, e una regola aggiunta con ufw non ha alcun effetto su quest'ultimo.
Causa 2: NAT rigido su una o entrambe le estremità
La seconda causa documentata è il NAT rigido. Il NAT (Network Address Translation) è il meccanismo con cui un router riscrive l'indirizzo privato sostituendolo con quello pubblico. Un router compatibile mantiene la stessa porta pubblica per un determinato socket interno, indipendentemente dal peer con cui si comunica. Questo comportamento è chiamato endpoint independent mapping. Un NAT rigido assegna una porta pubblica diversa per ogni destinazione. Di conseguenza, l'indirizzo appreso dalla macchina tramite un server STUN non è quello che un peer potrà utilizzare. Tailscale lo segnala in netcheck come MappingVariesByDestIP: true.
Un solo NAT rigido è gestibile. Se l'altra estremità ha un endpoint pubblico stabile, la macchina dietro il NAT rigido può comunque avviare la connessione e il percorso viene stabilito. Due NAT rigidi contemporaneamente causano il problema, perché nessuna delle due estremità può prevedere la porta sulla quale apparirà l'altra.
Su un VPS con un indirizzo IPv4 pubblico, questo campo dovrebbe riportare false, perché nessun dispositivo sta traducendo quell'indirizzo. Se su un server noleggiato il campo riporta true, l'indirizzo viene tradotto all'interno della rete del provider. Nessuna regola firewall applicata sulla macchina può modificare questo comportamento. Le opzioni sono configurare un relay peer su una macchina che disponga di un endpoint pubblico diretto oppure spostare il carico di lavoro. Questo è anche il caso in cui pubblicizzare le proprie reti private da un subnet router è utile, perché serve un solo percorso funzionante verso la rete, invece di un percorso funzionante verso ogni dispositivo che ne fa parte.
Perché un exit node fa sembrare Tailscale più lento di quanto sia
Un exit node aggiunge un secondo hop e spesso si attribuisce la lentezza al tunnel. Quando selezioni un exit node, una richiesta parte dal laptop, attraversa il tunnel fino al VPS, esce dal VPS verso Internet e la risposta torna seguendo lo stesso percorso. Anche una connessione perfettamente diretta a quel VPS non può rendere il percorso complessivo più veloce della connessione uplink del VPS. La maggiore distanza si riflette nel caricamento di ogni pagina.
Misura separatamente le due parti. Disattiva l'exit node, quindi verifica il tunnel direttamente verso il VPS usando il relativo indirizzo tailnet:
sudo tailscale set --exit-node=
sudo apt install -y iperf3
iperf3 -sEsegui iperf3 -c 100.113.160.82 dal client verso quell'indirizzo tailnet. Quel valore misura il tunnel. Riattiva l'exit node con sudo tailscale set --exit-node=100.113.160.82 ed esegui un normale test di velocità verso Internet. Quel valore misura il tunnel più la connessione uplink del VPS. Se il primo valore è buono e il secondo è scarso, Tailscale non è il problema: devi verificare la rete e il dimensionamento dell'exit node. tailscale exit-node list mostra quali risorse sono disponibili se non sai quale nodo hai selezionato.
La CPU è l'altro limite prestazionale di un exit node. Tailscale consiglia di preferire una generazione recente di CPU con una frequenza di clock più elevata rispetto a un numero maggiore di core. Un piano con più vCPU, quindi, non è automaticamente più veloce in questo scenario. Su un host condiviso sovraccarico, la CPU promessa dal provider non coincide con quella effettivamente disponibile. Il tempo steal causato da un vicino rumoroso si manifesta come un throughput che varia durante la giornata, senza modifiche sul tuo sistema.
L’unico parametro da ottimizzare: rx-udp-gro-forwarding
Tailscale documenta una sola impostazione Linux, applicabile alle macchine che inoltrano traffico, cioè exit node e subnet router. Un client normale non ne trae vantaggio. Sono necessari Tailscale 1.54 o versioni successive e il kernel Linux 6.2 o versioni successive. Verifica quindi entrambi prima di modificare l’impostazione:
tailscale version
uname -rDopo queste verifiche, abilita l’inoltro UDP GRO (generic receive offload) sull’interfaccia connessa a Internet:
NETDEV=$(ip -o route get 8.8.8.8 | cut -f 5 -d " ")
sudo ethtool -K $NETDEV rx-udp-gro-forwarding on rx-gro-list offVerifica che la modifica sia stata applicata:
ethtool -k $NETDEV | grep -E 'rx-udp-gro-forwarding|rx-gro-list'Dovresti vedere rx-udp-gro-forwarding: on e rx-gro-list: off. Questa impostazione è utile perché il traffico di Tailscale usa UDP. Se il kernel mantiene aggregati i piccoli pacchetti UDP lungo il percorso di inoltro, il demone deve gestire meno segmenti, ma di dimensioni maggiori, a parità di byte trasferiti. ethtool -K non sopravvive a un riavvio, quindi devi renderla persistente. Su un sistema che usa networkd-dispatcher:
printf '#!/bin/sh\n\nethtool -K %s rx-udp-gro-forwarding on rx-gro-list off \n' "$(ip -o route get 8.8.8.8 | cut -f 5 -d " ")" | sudo tee /etc/networkd-dispatcher/routable.d/50-tailscale
sudo chmod 755 /etc/networkd-dispatcher/routable.d/50-tailscaleEsegui manualmente lo script e verifica che il codice di uscita sia 0. Un nodo di inoltro deve inoltre avere abilitato l’inoltro IP. Si tratta di un’impostazione distinta e di un errore distinto:
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.confQuale MTU usa la tua interfaccia tailscale0?
Non basarti su una stima. Leggi il valore direttamente dal computer:
ip link show tailscale0Il valore mtu mostrato nell’output è quello effettivamente usato dal tunnel ed è inferiore a 1500, il valore riportato dall’interfaccia Ethernet. È una scelta intenzionale, non un bug. Ogni pacchetto inviato nel tunnel viene incapsulato: un header IP esterno di 20 byte per IPv4 o di 40 byte per IPv6, un header UDP di 8 byte e il framing WireGuard con il tag di autenticazione di 32 byte. Tutti questi dati devono rientrare nella dimensione massima supportata dal percorso reale. Tailscale sceglie quindi un valore abbastanza basso da funzionare anche su collegamenti che trasportano pacchetti inferiori ai 1500 byte completi, tra cui le connessioni PPPoE, alcune reti mobili e i tunnel IPv6.
Il sintomo di un problema di MTU è specifico, quindi non diagnosticarlo basandoti soltanto sulla lentezza. SSH risponde, ping funziona, poi i trasferimenti di grandi dimensioni o le pagine HTTPS pesanti si bloccano completamente invece di procedere lentamente. Questo comportamento indica che pacchetti troppo grandi vengono scartati da qualche parte e che nessun messaggio ICMP torna al mittente per segnalarlo. Aumentare la MTU tailscale0 verso 1500 peggiora il problema, perché i pacchetti che già non rientrano diventano ancora più grandi. La soluzione consiste nel individuare per bisezione l’MTU funzionante del percorso e limitare il TCP MSS sul router che inoltra il traffico. Il tipo di connessione non cambia questo comportamento: un percorso relay e un percorso diretto usano la stessa MTU dell’interfaccia.
FAQ
Come posso sapere se la connessione Tailscale è diretta o inoltrata?
Esegui tailscale status e leggi la parte finale della riga del peer. direct 203.0.113.9:41641 indica una connessione diretta, relay "tor" significa che ogni pacchetto passa attraverso quel server DERP e peer-relay significa che i pacchetti passano attraverso una macchina della tua tailnet. Per una seconda verifica, esegui tailscale ping <peer>: un percorso funzionante inizia su DERP e poi restituisce un pong con un indirizzo e una porta in chiaro, mentre un percorso inoltrato restituisce pong DERP fino al termine dell'esecuzione con direct connection not established. Invia prima del traffico al peer, perché Tailscale crea un percorso solo quando necessario.
Perché il mio VPS non stabilisce mai una connessione diretta?
Esegui tailscale netcheck sul VPS. Se restituisce UDP: false, un firewall in uscita scarta il traffico UDP in uscita e il daemon è passato a DERP tramite TCP 443. Per questo la macchina risulta comunque connessa. Consenti il traffico UDP in uscita dalla porta 41641 verso qualsiasi destinazione e il traffico UDP in uscita verso qualsiasi destinazione sulla porta 3478. Controlla il firewall di rete del provider e quello interno al server, perché sono controlli separati e una regola ufw non modifica quella del provider.
Una connessione Tailscale inoltrata è meno sicura di una diretta?
No. Un server DERP inoltra pacchetti WireGuard che non può decrittografare, perché le chiavi di cifratura vengono generate sui tuoi dispositivi e non li lasciano mai. Il costo del relay riguarda latenza e throughput, non la riservatezza. Il server di coordinamento controlla invece quali dispositivi vengono a conoscenza gli uni degli altri, e la separazione tra materiale crittografico e metadati di connessione è un aspetto da comprendere prima di decidere quanto gestire autonomamente.
L'impostazione rx-udp-gro-forwarding è utile per ogni macchina?
No. È documentata per le macchine Linux che inoltrano traffico per altri dispositivi, cioè exit node e subnet router. Un laptop o un server che comunica soltanto con i propri peer non ne trae alcun vantaggio. Inoltre, richiede Tailscale 1.54 o versioni successive e il kernel Linux 6.2 o versioni successive. Controlla quindi prima tailscale version e uname -r, e ricorda che ethtool -K viene reimpostata dopo un riavvio se non la rendi persistente.
Tailscale è più lento di WireGuard semplice?
Entrambi usano WireGuard per cifrare il traffico. Tailscale aggiunge la configurazione della connessione che WireGuard semplice lascia gestire manualmente, ed è questa configurazione che a volte porta a usare un relay. WireGuard semplice non dispone di un relay: si connette direttamente oppure non riesce a connettersi. Confronta quindi configurazioni equivalenti e misura le prestazioni di Tailscale solo quando tailscale status indica direct. Se vuoi la versione configurata manualmente per il confronto, un server WireGuard che configuri autonomamente richiede circa quaranta righe di configurazione; il compromesso associato è descritto in il confronto tra i due approcci.