Che cos'è Tailscale e come funziona?
Scopri come Tailscale usa tunnel WireGuard, server di coordinamento, NAT traversal e relay DERP, con chiavi, ACL e modello di minaccia.
Che cos'è Tailscale?
Tailscale è una VPN che connette direttamente le macchine tra loro, invece di instradare tutto il traffico attraverso un unico gateway gestito dall'utente. Ogni nodo esegue WireGuard, quindi i pacchetti viaggiano crittografati da un server all'altro e nessun elemento del percorso può leggerli. Un server di coordinamento in hosting gestisce l'associazione tra i nodi. Memorizza e distribuisce le chiavi pubbliche e comunica a ogni nodo dove si trovano gli altri. Distribuisce inoltre le regole di accesso definite dall'utente.
Questa separazione costituisce l'intero modello architetturale. Il data plane è peer-to-peer e crittografato tra i nodi. Il control plane è un servizio gestito da Tailscale. Ogni domanda importante su Tailscale, comprese quelle più delicate relative all'affidabilità, deriva da questi due aspetti. Se hai già configurato una VPN WireGuard manualmente su un VPS, Tailscale offre lo stesso tunnel, occupandosi della distribuzione delle chiavi e dell'attraversamento dei firewall.
Come funziona Tailscale?
La rete privata dei nodi si chiama tailnet. Quando una macchina entra a farne parte, avvengono quattro operazioni.
- Il daemon
tailscaledsi avvia, genera una coppia di chiavi WireGuard e conserva il proprio stato in/var/lib/tailscale/tailscaled.state. La chiave privata rimane su quella macchina. Tailscale lo afferma in modo esplicito: "the private key never, ever leaves its node." - Il nodo accede al server di coordinamento e carica la propria chiave pubblica, insieme agli indirizzi ai quali ritiene di poter essere raggiunto. Tailscale descrive quel server come "a shared drop box for public keys."
- Il server di coordinamento restituisce una mappa di rete contenente la chiave pubblica, l'indirizzo della tailnet, il nome della macchina e gli endpoint candidati di ogni nodo che questa macchina può raggiungere.
- Ogni coppia di nodi prova quindi a creare direttamente un tunnel WireGuard tra le due macchine. Se il tentativo fallisce, i pacchetti vengono inoltrati tramite un relay.
Ogni nodo riceve un indirizzo stabile nell'intervallo 100.64.0.0/10, l'intervallo CGNAT che va da 100.64.0.0 a 100.127.255.255. Tailscale usa questo intervallo perché è riservato all'infrastruttura dei provider e quindi entra raramente in conflitto con gli indirizzi privati già utilizzati dai server. Su Linux, il tunnel appare come un'interfaccia denominata tailscale0.
L'implementazione WireGuard risiede nello userspace all'interno di tailscaled, non nel modulo del kernel. Per questo Tailscale si avvia anche nella virtualizzazione dei container, dove sudo modprobe wireguard fallisce con Operation not supported. Questo significa inoltre che, su una determinata macchina, il limite massimo di throughput è inferiore rispetto a WireGuard nel kernel. È uno dei compromessi descritti in Tailscale rispetto a WireGuard senza componenti aggiuntivi.
Due comandi indicano lo stato della connessione.
tailscale ip -4
tailscale statustailscale status stampa una riga per ogni nodo. L'ultima colonna è quella da controllare.
100.101.102.103 web-1 you@ linux -
100.101.102.104 db-1 you@ linux active; direct 198.51.100.24:41641
100.101.102.105 ci-runner you@ linux active; relay "fra"direct seguito da un indirizzo e da una porta indica che le due macchine hanno trovato un percorso diretto e che il traffico è peer-to-peer. relay "fra" indica che il traffico passa attraverso un relay Tailscale a Francoforte. - indica che in questo momento non esiste una sessione attiva con quel nodo; è un comportamento normale.
Cosa può e non può vedere il server di coordinamento
Il server di coordinamento conserva le chiavi pubbliche e i metadati. Conosce i nomi delle macchine, l'utente o il tag proprietario di ciascun nodo, l'indirizzo tailnet di ogni nodo, gli indirizzi pubblici dai quali i nodi sono raggiungibili, l'ultima volta in cui ciascun nodo è stato online e il file delle policy che hai scritto. Dispone quindi di una mappatura completa della tua infrastruttura.
Non conserva alcuna chiave privata, quindi non può decrittografare il traffico tra due nodi. La crittografia è end-to-end tra i peer WireGuard e il server di coordinamento non è un peer.
Può però distribuire le chiavi. Qualsiasi server di coordinamento, gestito da un provider o eseguito autonomamente, deve essere considerato attendibile perché comunica ai nodi quali chiavi pubbliche appartengono alla tailnet. Questo è il punto centrale del modello delle minacce descritto più avanti e il motivo per cui esiste Headscale, un server di coordinamento open source che ospiti autonomamente.
Come comunicano direttamente due server dietro firewall diversi
Il NAT (network address translation) consente a più macchine di condividere un unico indirizzo pubblico. Il tuo VPS dispone in genere di un proprio indirizzo pubblico, ma spesso le altre macchine che vuoi aggiungere alla tailnet non lo hanno: ad esempio un server domestico, un build runner su una rete aziendale oppure un sistema dietro il firewall del provider che non puoi modificare.
Tailscale individua un percorso usando tecniche basate sugli standard STUN (session traversal utilities for NAT) e ICE. Ogni nodo invia un piccolo pacchetto UDP a un server STUN e rileva l'indirizzo pubblico e la porta assegnati dal router a quel socket. Entrambi i nodi comunicano questi candidati al coordination server, che li inoltra all'altra estremità. Poi entrambi i nodi iniziano a inviare pacchetti contemporaneamente. Ogni router vede prima un pacchetto in uscita, quindi crea una mappatura e accetta la risposta proveniente dallo stesso indirizzo. Nessuna delle due estremità ha bisogno di una regola firewall in ingresso.
Le porte sono specifiche. I tunnel WireGuard diretti usano UDP con una porta di origine predefinita pari a 41641. STUN usa UDP 3478 per comunicare con i relay server di Tailscale. La connessione di controllo e gli eventuali dati inoltrati usano HTTPS sulla porta TCP 443. Nella maggior parte dei casi non è necessario aprire porte in ingresso, ma su una rete con NAT difficile consentire UDP 41641 in ingresso aumenta la probabilità di stabilire una connessione diretta.
tailscale netcheckLeggi due righe di quel report. UDP: true indica che UDP esce effettivamente dalla macchina, mentre UDP: false indica che tutte le connessioni da questo nodo verranno inoltrate tramite un relay. MappingVariesByDestIP: true indica che il router assegna una porta pubblica diversa per ogni destinazione; di conseguenza, la previsione dell'indirizzo descritta sopra non può funzionare e questi nodi rimangono generalmente collegati tramite relay.
Quando Tailscale usa un relay DERP
DERP (designated encrypted relay for packets) è il meccanismo di fallback. Tailscale gestisce relay in molte regioni, raggiungibili tramite TCP 443, e un nodo che non riesce a stabilire un percorso diretto invia i propri pacchetti WireGuard attraverso uno di questi relay.
I pacchetti restano cifrati. Tailscale lo dichiara esplicitamente: "non esiste alcun modo per cui un server DERP possa decrittografare il traffico. Inoltra semplicemente, senza esaminarlo, il traffico già cifrato da un nodo all'altro." Un relay vede il testo cifrato e vede quale nodo comunica con quale altro nodo.
I relay trasportano anche i primi pacchetti della maggior parte delle connessioni. La ricerca di un percorso diretto richiede un breve intervallo, quindi una sessione spesso inizia tramite relay e passa a un percorso diretto quando i due nodi riescono a localizzarsi. È possibile monitorare questo passaggio.
tailscale ping db-1Le prime risposte arrivano tramite via DERP(fra), poi una riga successiva segnala qualcosa come via 198.51.100.24:41641. Questo cambiamento indica il passaggio a un tunnel diretto. Se il valore non cambia mai, eseguire tailscale netcheck su entrambe le estremità. Un percorso tramite relay continua a funzionare. Aumenta però la latenza, perché ogni pacchetto passa da una macchina intermedia.
Aggiungere un VPS alla tailnet
Lo script di installazione supporta Ubuntu e Debian.
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale upsudo tailscale up stampa un URL. Apritelo, eseguite l'autenticazione e il nodo comparirà nella console di amministrazione. Verificate quindi che il demone si riavvii dopo un reboot, perché questo è il passaggio che spesso viene saltato.
sudo systemctl is-enabled tailscaled
tailscale statusis-enabled dovrebbe stampare enabled e tailscale status dovrebbe elencare il nuovo nodo con il relativo indirizzo 100.x. Per un server creato tramite script, un URL interattivo non è utile. Generate una chiave di autenticazione nella console di amministrazione e passatela insieme a un tag che identifichi il tipo di macchina.
sudo tailscale up --auth-key=tskey-auth-REPLACE-ME --advertise-tags=tag:serverUn nodo con tag appartiene al tag e non alla persona che ha eseguito il comando. Continua quindi a funzionare anche dopo la rimozione dell'account di quella persona. Il tag deve essere dichiarato prima nel file delle policy, nella sezione tagOwners, altrimenti il comando viene rifiutato. L'assegnazione di un tag modifica anche il modo in cui la macchina viene conteggiata nel piano, perché una risorsa con tag viene tariffata separatamente dai dispositivi personali di un utente. Cosa copre effettivamente il piano gratuito descrive questi limiti.
Per una flotta sono importanti due impostazioni. Per impostazione predefinita, le chiavi dei nodi scadono dopo 180 giorni (ad agosto 2026). Quando una chiave scade, "le connessioni da e verso l'endpoint indicato smettono di funzionare" finché qualcuno non esegue nuovamente l'accesso. Per i server non presidiati, aprite quindi la riga della macchina nella console di amministrazione e scegliete Disable Key Expiry. MagicDNS, abilitato per impostazione predefinita per le tailnet create a partire dal 20 ottobre 2022, assegna a ogni nodo un nome come db-1.yak-bebop.ts.net, risolto da uno stub resolver in 100.100.100.100. Usate i nomi invece degli indirizzi, perché un nodo ricreato riceve un nuovo indirizzo ma conserva il proprio nome.
Se l'installazione non riesce tramite apt o dal repository, Gli errori comuni di installazione di Tailscale su Ubuntu descrive le correzioni necessarie.
Raggiungere un servizio associato a localhost
È qui che una tailnet diventa utile e dove spesso si verificano problemi. L'adesione alla tailnet non rende raggiungibile un servizio in ascolto sul loopback.
ss -tlnp | grep 3000Se il comando restituisce 127.0.0.1:3000, il socket accetta soltanto pacchetti la cui destinazione è 127.0.0.1. Una richiesta proveniente da un altro nodo arriva con destinazione l'indirizzo 100.x di questo nodo. Il kernel non trova quindi alcun processo in ascolto su quell'indirizzo e risponde con un reset TCP. Il client restituisce Connection refused. Il tunnel funziona. Il problema riguarda il listener.
Esistono due soluzioni corrette. Associare il servizio all'indirizzo tailnet del nodo mantiene il servizio fuori dall'interfaccia pubblica senza interporre un proxy: passare --bind 100.101.102.104 o l'opzione equivalente nella configurazione, oppure, per un container, pubblicare la porta come -p 100.101.102.104:3000:3000. In alternativa, lasciare il servizio sul loopback e mettere Tailscale davanti al servizio.
tailscale serve 3000Questo inoltra le richieste a http://127.0.0.1:3000 e le rende disponibili all'interno della tailnet con un nome ts.net tramite HTTPS, dopo aver abilitato i certificati HTTPS per la tailnet. Il servizio resta privato e accessibile soltanto dai nodi della tailnet. La versione pubblica dello stesso meccanismo è Funnel; Tailscale serve con Funnel spiega quale soluzione scegliere.
Due attività correlate hanno pagine dedicate. Per raggiungere un'intera rete privata su cui Tailscale non è installato serve un subnet router su un VPS, mentre per instradare il traffico Internet in uscita di un nodo attraverso un altro nodo serve un exit node.
Chiusura delle porte non più necessarie
Quando ogni amministratore accede al server tramite la tailnet, la porta pubblica 22 non è più necessaria. Questo è il vantaggio pratico: una porta chiusa non può essere sottoposta a tentativi di brute force e i log non si riempiono più di tentativi di accesso.
L'ordine è importante. Aggiungi l'accesso tramite la tailnet, verifica di riuscire ad accedere da una seconda sessione e solo dopo rimuovi la regola pubblica.
sudo ufw allow in on tailscale0
sudo ufw status verboseDopodiché, elimina la regola SSH pubblica e riconnettiti usando il nome MagicDNS. Tieni presente cosa fa realmente ufw allow in on tailscale0: considera attendibile tutto ciò che arriva tramite il tunnel, quindi il file delle policy di Tailscale diventa il controllo degli accessi al posto di ufw. Scrivi la policy tenendo conto di questo comportamento.
Un'avvertenza per chi esegue container. Una porta Docker pubblicata installa regole NAT proprie e aggira ufw, quindi un ufw deny non la chiude. Le porte Docker pubblicate aggirano ufw spiega il meccanismo. Pubblicare sull'indirizzo della tailnet, come indicato sopra, evita il problema.
Cosa protegge Tailscale e cosa non protegge
È importante dirlo chiaramente, perché la versione usata nel marketing tende a confondere questa distinzione.
Protetto: il traffico tra due nodi è crittografato end-to-end con WireGuard e nessun relay intermedio può leggerlo. Le chiavi private non lasciano mai la macchina che le ha generate. I nodi non richiedono alcuna porta pubblica in ingresso, quindi Internet non può eseguire scansioni sulle porte 22 o 5432. L'accesso tra i nodi è determinato da un file di policy, non da chiunque conosca un indirizzo.
Non protetto: il server di coordinamento vede il grafo dei dispositivi. Questi metadati sono sensibili anche da soli, perché i nomi delle macchine, i proprietari, gli indirizzi e gli orari di connessione descrivono la tua infrastruttura. Il server distribuisce anche le chiavi, e questo rappresenta il rischio più importante. Tailscale lo dichiara direttamente: "Se Tailscale fosse malevolo e inserisse di nascosto nuovi nodi nella tua rete, potrebbe inviare o ricevere traffico verso i nodi esistenti in formato non crittografato." Il provider di single sign-on si trova nello stesso percorso di trust, perché chiunque possa creare un'identità al suo interno può aggiungere un nodo. Inoltre, un nodo compromesso è un peer all'interno della tailnet. Di conseguenza, può raggiungere tutto ciò che la policy consente. La valutazione del rischio dipende dal soggetto da cui vuoi difenderti. Il modello completo di trust analizza ciascuno di questi casi, incluso ciò che può effettivamente fare un account di identità rubato.
Esistono due risposte al rischio associato alla distribuzione delle chiavi. La prima è tailnet lock, che richiede ai nodi attendibili esistenti di firmare crittograficamente un nuovo nodo prima che gli altri nodi lo accettino. Un control plane che aggiunge un nodo senza una firma valida viene ignorato. La console di amministrazione genera la riga tailscale lock init esatta per i nodi incaricati della firma, e ogni nodo può verificare ciò che riceve.
tailscale lock statusTutti i nodi devono riportare lo stesso insieme di chiavi di firma attendibili. La seconda risposta consiste nell'eseguire autonomamente il control plane. Un server di coordinamento Headscale self-hosted usa lo stesso protocollo con gli stessi client. Il grafo dei dispositivi e la distribuzione delle chiavi vengono così trasferiti su hardware di tua proprietà. Sei quindi responsabile anche della disponibilità di quel server. Se stai ancora confrontando control plane self-hosted invece di scegliere questa soluzione, NetBird è una VPN mesh distinta, con un server che esegui end-to-end su un singolo VPS.
C'è un'impostazione predefinita da correggere il primo giorno. Una nuova tailnet viene distribuita con autorizzazioni permissive: "il file di policy predefinito della tailnet abilita la comunicazione tra tutti i dispositivi della tailnet." Non appena aggiungi una sezione acls, il modello passa al deny by default e vengono consentite soltanto le connessioni previste dalle tue regole.
{
"tagOwners": {
"tag:server": ["autogroup:admin"]
},
"acls": [
{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}
]
}Questa policy consente ai membri della tailnet di raggiungere SSH sui server contrassegnati con i tag, e nient'altro. Aggiungi una regola per ogni servizio invece di lasciare il wildcard, perché il wildcard consente a una chiave rubata da un laptop di raggiungere il database.
Modalità di errore e stringhe visualizzate
tailscale status restituisce sempre relay. I due nodi non hanno mai stabilito un percorso diretto. Esegui tailscale netcheck su entrambe le estremità. UDP: false indica che il traffico UDP in uscita è bloccato, quindi può funzionare soltanto un relay. MappingVariesByDestIP: true indica la presenza di un NAT rigido; consentire il traffico UDP in ingresso sulla porta 41641 dal lato sotto il tuo controllo risolve spesso il problema.
Un nodo che funzionava da mesi è scomparso. La sua node key è scaduta dopo i 180 giorni previsti per impostazione predefinita. Il computer risulta scaduto nella console di amministrazione e sudo tailscale up sul computer lo riattiva. Disabilita la scadenza delle key sui server per evitare che il problema si ripeta.
I peer sono elencati, ma le connessioni vanno in timeout. La connettività funziona e la policy nega il traffico. Controlla la sezione acls per verificare la presenza di una regola che copra questa origine, questa destinazione e questa porta. Un pacchetto negato viene eliminato senza risposta; per questo ricevi un timeout invece di Connection refused.
I nomi MagicDNS non vengono risolti. ping db-1 non funziona, mentre ping 100.101.102.104 funziona. Qualcosa ha sostituito /etc/resolv.conf, quindi le query non raggiungono mai lo stub resolver su 100.100.100.100. Controlla cat /etc/resolv.conf per 100.100.100.100 e verifica quale altro componente sul computer scrive in quel file. È lo stesso tipo di problema descritto in DNS che non funziona all'interno di un tunnel WireGuard.
tailscale up rifiuta il tuo tag. Il tag non è dichiarato nella sezione tagOwners del file di policy. Aggiungilo, quindi esegui di nuovo il comando.
FAQ
Tailscale è una VPN o una rete mesh?
Entrambe le definizioni sono corrette e descrivono livelli diversi. I tunnel usano WireGuard, quindi Tailscale è una VPN. La topologia è mesh perché ogni nodo crea un tunnel diretto verso ciascun nodo con cui comunica, invece di inviare ogni pacchetto attraverso un unico server centrale. Il server di coordinamento si trova nel piano di controllo, non nel piano dati. Se diventa irraggiungibile, i tunnel esistenti continuano a trasportare il traffico. Durante un'interruzione si bloccano invece l'aggiunta di nuovi nodi e l'applicazione delle modifiche alle chiavi o ai criteri.
Tailscale può leggere il mio traffico?
Non il contenuto. Il traffico è cifrato end-to-end tra i nodi tramite WireGuard, le chiavi private non lasciano mai i nodi e un relay DERP inoltra pacchetti che non può decrittografare. Tailscale vede però i metadati: nomi delle macchine, proprietari, chiavi pubbliche, indirizzi degli endpoint e stato online dei nodi. Distribuisce inoltre le chiavi, quindi un server di coordinamento compromesso potrebbe tentare di inserire un nodo che la rete considererebbe attendibile. Tailnet lock impedisce questo comportamento richiedendo firme dai propri nodi attendibili. Headscale rimuove invece il piano di controllo gestito.
Devo aprire porte nel firewall per Tailscale?
Quasi mai in ingresso. La documentazione di Tailscale indica che "nella maggior parte dei casi non è necessario aprire porte nel firewall". In uscita, un nodo richiede TCP 443 verso il server di coordinamento e i relay, oltre a UDP 3478 per STUN. I tunnel diretti usano UDP con una porta sorgente predefinita pari a 41641. Consentire UDP 41641 in ingresso è facoltativo e aiuta soltanto a stabilire connessioni dirette su reti con configurazioni problematiche.
Perché gli altri nodi non riescono a raggiungere il mio servizio sulla porta 3000?
Controlla prima l'indirizzo di bind con ss -tlnp. Un listener su 127.0.0.1:3000 rifiuta le connessioni indirizzate all'indirizzo tailnet 100.x del nodo, perché quel socket accetta soltanto la destinazione di loopback; il client visualizza quindi Connection refused. Associa il servizio all'indirizzo tailnet oppure esegui tailscale serve 3000 per utilizzarlo come proxy. Se il listener è già associato a 0.0.0.0 e la connessione va in timeout invece di essere rifiutata, la causa è una regola di policy o il firewall dell'host, non l'indirizzo di bind.
Devo eseguire Headscale invece del server di coordinamento di Tailscale?
Esegui Headscale quando il grafo dei dispositivi o la distribuzione delle chiavi devono rimanere su un'infrastruttura sotto il tuo controllo, oppure quando la tailnet deve funzionare senza dipendere da un servizio esterno. I client e il protocollo sono gli stessi. Il costo è che devi gestire il server di coordinamento. Se il server è indisponibile, i nuovi nodi non possono unirsi e le modifiche ai criteri non vengono applicate. Per una flotta di piccole dimensioni, il piano di controllo gestito con tailnet lock abilitato offre generalmente il compromesso migliore.