Come configurare un subnet router Tailscale su VPS
Scopri come pubblicizzare una rete privata dal VPS: approva la route, rendi persistente l'IP forwarding dopo il riavvio e usa --accept-routes su Linux.
Cosa fa un subnet router Tailscale
Un subnet router Tailscale è una macchina che pubblicizza al tuo tailnet un intero intervallo di indirizzi IP privati, in modo che ogni dispositivo nel tailnet possa raggiungere gli indirizzi di quell'intervallo anche se su tali dispositivi non è in esecuzione Tailscale. Il tailnet è la tua rete privata Tailscale: l'insieme dei dispositivi autenticati con lo stesso account o appartenenti alla stessa organizzazione. La funzionalità che viene confusa più spesso con il subnet router è l'exit node, che svolge il compito opposto. Invia tutto il traffico di un dispositivo attraverso il VPS, quindi il VPS diventa il percorso utilizzato da quel dispositivo per raggiungere Internet pubblico.
Una frase per ciascun concetto. Un subnet router rende raggiungibile una rete privata dal tailnet. Un exit node modifica il punto da cui il traffico pubblico esce verso Internet. Se ti serve la seconda funzionalità, consulta come configurare un exit node Tailscale su un VPS. Sono flag distinti e un VPS può svolgere entrambe le funzioni contemporaneamente, ma risolvono problemi diversi e possono non funzionare per cause diverse.
Quando serve un subnet router su un VPS
Il caso più comune riguarda una rete privata già fornita dal provider. Il VPS ha un indirizzo pubblico e una seconda interfaccia su un segmento privato, mentre gli altri server di quel segmento non hanno alcun indirizzo pubblico: un database su 10.0.0.20 e una destinazione per i backup su 10.0.0.30. Installa Tailscale su un VPS, pubblicizza 10.0.0.0/24 e il laptop potrà raggiungere direttamente quegli indirizzi privati. Non è necessario modificare gli altri sistemi del segmento e il database continua a non avere un indirizzo pubblico. Se da quel segmento ti serve soltanto un'applicazione web su una porta, pubblicizzare l'intero intervallo è più di quanto occorra; Tailscale serve aggiunge invece HTTPS soltanto a quella porta. Lo stesso ragionamento vale per un daemon che esegue intenzionalmente il bind solo su localhost, ad esempio dsh eseguito senza interfaccia sotto systemd, dove un indirizzo tailnet su quel VPS sostituisce il tunnel SSH che altrimenti dovresti mantenere aperto per raggiungere la relativa interfaccia.
L’altro caso è una rete sul lato remoto del VPS. Può essere una LAN domestica o aziendale (rete locale) dietro il proprio router, oppure un rack di dispositivi che non possono eseguire Tailscale, come uno switch gestito o un vecchio NAS con firmware bloccato. Un host Linux su quella rete diventa il subnet router per tutti gli altri dispositivi. Il router domestico a monte non richiede alcuna porta inoltrata. Come Tailscale attraversa il NAT senza aprire una porta sul router spiega perché questa configurazione funziona e quando Tailscale ricorre a un relay. In ambiente domestico, questo host è spesso una piccola VM su un hypervisor già in uso. Il confronto dei costi tra un host Proxmox domestico e un VPS a noleggio aiuta a decidere prima su quale estremità del tunnel eseguire i servizi.
Entrambi i casi hanno un requisito comune. Il subnet router deve poter raggiungere autonomamente l'intervallo che pubblicizza, usando la propria tabella di routing e il proprio firewall. Tailscale non crea questa connessione. Trasporta il traffico fino al router e lo consegna al kernel, che lo inoltra.
Installa Tailscale e verifica prima la route locale
curl -fsSL https://tailscale.com/install.sh | shLo script rileva la distribuzione, aggiunge il repository dei pacchetti di Tailscale, installa il comando tailscale e il demone tailscaled, quindi abilita il servizio. Verifica il risultato con systemctl is-active tailscaled, che dovrebbe stampare active.
Prima di procedere, verifica che il VPS possa raggiungere la rete che prevedi di annunciare.
ip route show
ping -c3 10.0.0.20ip route show deve elencare l'intervallo privato su un'interfaccia reale, ad esempio 10.0.0.0/24 dev enp7s0 proto kernel scope link src 10.0.0.5. Se il ping fallisce in questo punto, direttamente sul router, nessun flag di Tailscale potrà risolvere il problema. La causa è nella configurazione di rete del VPS oppure in un firewall sull'host di destinazione. Risolvi prima questo problema, perché tutti i test successivi dipendono da questa verifica.
Attivare l'inoltro IP e renderlo persistente dopo un riavvio
Una macchina Linux scarta tutti i pacchetti non indirizzati a se stessa se l'inoltro non è attivo. Inoltrare i pacchetti delle altre macchine è il compito principale di un router di subnet, quindi questo passaggio è obbligatorio.
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.confVerificarlo con sysctl net.ipv4.ip_forward, che dovrebbe stampare net.ipv4.ip_forward = 1.
Spesso questo passaggio viene completato solo parzialmente. sudo sysctl -w net.ipv4.ip_forward=1 funziona immediatamente, ma il valore viene perso al riavvio successivo. Di conseguenza, il router di subnet può funzionare per settimane e poi smettere di funzionare la mattina dopo il riavvio causato da un aggiornamento del kernel. Il problema è difficile da individuare perché nulla sembra guasto. tailscale status continua a mostrare il nodo online, la console di amministrazione continua a mostrare la route approvata e i client continuano ad avere la route installata. I pacchetti arrivano al VPS, ma il kernel li scarta senza registrare alcun messaggio. Scrivere i valori in /etc/sysctl.d/99-tailscale.conf consente di ripristinarli dopo un riavvio.
Se si annunciano route mentre l'inoltro è ancora disattivato, tailscale up visualizza un avviso in quel momento. Su Linux, il messaggio è simile a Warning: IP forwarding is disabled, subnet routing/exit nodes will not work.. Leggere l'output di quel comando invece di ignorarlo.
Pubblicare le route
sudo tailscale up --advertise-routes=10.0.0.0/24Su un VPS già autenticato nella tailnet, modifica direttamente l'impostazione:
sudo tailscale set --advertise-routes=10.0.0.0/24Usa tailscale set per ogni modifica successiva. Eseguire di nuovo tailscale up con un solo flag reimposta i flag non specificati. La CLI interrompe l'operazione e segnala che, per modificare le impostazioni in questo modo, è necessario indicare tutti i flag non predefiniti. tailscale set modifica una sola impostazione e lascia invariate le altre.
Puoi specificare più intervalli in un unico elenco separato da virgole, senza spazi: --advertise-routes=10.0.0.0/24,192.168.50.0/24. Ogni voce deve essere un indirizzo di rete in notazione CIDR (classless inter-domain routing, nel formato 10.0.0.0/24). Se inserisci per errore l'indirizzo del tuo host, 10.0.0.5/24, l'operazione viene rifiutata perché i bit dopo il prefisso non sono impostati a zero. L'errore indica il prefisso probabilmente corretto. Per interrompere la pubblicazione, imposta un elenco vuoto con sudo tailscale set --advertise-routes=.
Approva la route nella console di amministrazione
La pubblicazione di una route è una richiesta, non una modifica immediata. Finché un amministratore non la approva, nessun client riceve la route e nessuna risorsa dell'intervallo è raggiungibile. Questo comportamento è intenzionale: una macchina che può aggiungersi alla tabella di routing di tutti potrebbe intercettare il traffico destinato a qualsiasi intervallo.
Approvala nella pagina Machines della console di amministrazione. Il VPS è elencato con un badge subnet. Apri la relativa riga, individua la sezione delle subnet, modifica le impostazioni della route, seleziona la route e salva.
L'approvazione riguarda ogni prefisso. Pubblica 10.0.0.0/24 oggi e 192.168.50.0/24 il mese prossimo: il nuovo prefisso arriva non approvato, mentre quello precedente continua a funzionare. Dal VPS, una route approvata e una route ignorata hanno lo stesso aspetto. Controlla quindi la console prima di eseguire qualsiasi altra attività di troubleshooting.
Puoi saltare il passaggio manuale con un blocco autoApprovers nel file delle policy della tailnet:
{
"autoApprovers": {
"routes": {
"10.0.0.0/24": ["tag:subnet-router"]
}
}
}Quindi avvia il nodo con quel tag, sudo tailscale up --advertise-routes=10.0.0.0/24 --advertise-tags=tag:subnet-router, e la route viene approvata nel momento stesso in cui viene pubblicata. Il tag deve esistere prima nella sezione tagOwners dello stesso file delle policy. Questa configurazione è utile se ricrei il VPS tramite uno script, perché un nodo ricreato è un nuovo nodo e le relative route tornano a essere non approvate.
Perché i client Linux ignorano la route senza --accept-routes
La route è ora annunciata e approvata. Il telefono e il Mac possono raggiungere 10.0.0.20. Il laptop Linux non può farlo e nella console di amministrazione non compare alcun problema.
Accettare una route di subnet significa aggiungere voci alla tabella di routing del client. Su Android, iOS, macOS, tvOS e Windows, il client Tailscale esegue automaticamente questa operazione. Su Linux non avviene, perché una macchina Linux è spesso un server o un router la cui tabella di routing è stata configurata intenzionalmente da un amministratore. L'inserimento automatico di una /24 appresa dalla rete potrebbe interrompere il traffico già gestito dalla macchina. Su Linux è quindi necessario abilitarlo esplicitamente su ogni client:
sudo tailscale set --accept-routesControllare quindi dove è stata installata la route:
ip route show table 52
ip route get 10.0.0.20Su Linux, Tailscale non inserisce le route accettate nella tabella di routing principale. Le inserisce nella tabella di routing 52 e installa regole di policy, visibili con ip rule show nell'intervallo di priorità da 5210 a 5270, che inoltrano i pacchetti non corrispondenti a tale tabella. Di conseguenza, ip route show da solo non mostrerà mai 10.0.0.0/24 e chi controlla soltanto questo comando conclude che --accept-routes non ha avuto effetto. ip route show table 52 è il comando che mostra la situazione effettiva e dovrebbe elencare l'intervallo annunciato su tailscale0.
È utile conoscere un'eccezione. Se questo nodo Linux è anche un secondo subnet router per la propria rete locale, --accept-routes fa sì che il traffico destinato alla subnet direttamente connessa venga inviato attraverso l'altro router invece che tramite la propria interfaccia. Su un router di standby in una coppia ad alta disponibilità, lasciare --accept-routes disabilitato e limitarsi ad annunciare la route.
Modalità di errore: due router che annunciano intervalli sovrapposti
Due subnet router possono annunciare intervalli identici. È così che funziona una coppia ad alta disponibilità: ogni router annuncia esattamente gli stessi prefissi e i client possono passare da uno all’altro in caso di errore. Sono consentiti anche intervalli sovrapposti con lunghezze di prefisso diverse e Tailscale seleziona la corrispondenza più specifica. Se il router A annuncia 10.0.0.0/24 e il router B annuncia 10.0.0.0/16, il traffico destinato a 10.0.0.20 passa da A.
Il comportamento quando A va offline può sorprendere. Tailscale non passa alla route meno specifica, perché un router offline non può ritirare il proprio annuncio e i client continuano a preferire il prefisso più specifico. Il traffico verso 10.0.0.20 si interrompe, mentre quello verso 10.0.1.20, coperto soltanto da /16 del router B, continua a funzionare attraverso B. Il sintomo fa pensare che una parte della rete privata sia inattiva, ma la causa è un nodo offline che mantiene il prefisso più specifico. Se vuoi il failover, configura anche il router con l’intervallo più ampio affinché annunci i prefissi più specifici. In questo modo entrambi coprono gli stessi indirizzi.
L’altro tipo di sovrapposizione riguarda più direttamente il client. Se ti trovi su una rete alberghiera con 192.168.1.0/24 mentre il tuo subnet router annuncia 192.168.1.0/24, le due route competono per le stesse destinazioni. Quale route prevale dipende dalla piattaforma. Su Linux, installa una regola prima di quella usata da Tailscale, in modo che gli indirizzi locali utilizzino la tabella principale:
sudo ip rule add to 192.168.1.0/24 priority 2500 lookup mainLa regola non è persistente e scompare al riavvio successivo. La soluzione corretta consiste nello scegliere un intervallo privato che non incontrerai normalmente in altre reti. 192.168.0.0/24 e 192.168.1.0/24 sono i valori predefiniti sulla maggior parte dei router domestici, quindi scegli un intervallo all’interno di 10.0.0.0/8 in modo deliberato. La stessa collisione interrompe una VPN WireGuard semplice configurata manualmente, per lo stesso motivo: la route locale più specifica prevale e il traffico non entra mai nel tunnel.
Modalità di errore: il DNS risolve un indirizzo non coperto da alcuna route
Questo caso è difficile da diagnosticare perché nessun componente segnala un errore. Il nome viene risolto, ma la connessione va in timeout.
Supponiamo che db.internal.example.com venga risolto in 10.0.5.20 tramite il tuo nameserver privato e che tu abbia pubblicizzato 10.0.0.0/24. La ricerca ha esito positivo perché la risoluzione DNS (domain name system) e il routing IP sono passaggi distinti e nessuno dei due verifica l'altro. Il pacchetto destinato a 10.0.5.20 non trova quindi alcuna route corrispondente nella tailnet, esce tramite il gateway predefinito del client e va perso.
Due comandi consentono di separare i due passaggi:
nslookup db.internal.example.com
ip route get 10.0.5.20Se la ricerca restituisce un indirizzo, ma ip route get non risponde con dev tailscale0, il nome è corretto e sul client manca la route. Su un client Linux, verifica innanzitutto che --accept-routes sia attivo, perché senza questa opzione non viene installata alcuna route verso la subnet, anche quando un prefisso approvato copre già l'indirizzo. Se l'opzione è attiva e nessun prefisso approvato copre l'indirizzo, pubblicizza un intervallo che lo includa, usando 10.0.0.0/16 oppure un secondo prefisso esplicito, quindi approva il nuovo prefisso nella console.
Esiste una situazione analoga sul nameserver stesso. Se imposti nella console di amministrazione un nameserver globale a un indirizzo privato come 10.0.0.53, tale indirizzo deve rientrare in una route approvata. In caso contrario, i dispositivi che non si trovano su quella rete privata non possono raggiungere il resolver. Se attivi l'opzione che sostituisce i server DNS locali indicando un resolver irraggiungibile, tutti i dispositivi nella tailnet perdono immediatamente la risoluzione dei nomi, compresi quelli che funzionavano fino a un secondo prima. Pubblicizza e approva prima la route verso il resolver, quindi modifica l'impostazione DNS. Se continui ad avere problemi con il DNS all'interno di un tunnel, il funzionamento del DNS in caso di problemi su un tunnel WireGuard descrive lo stesso meccanismo senza il livello di coordinamento aggiuntivo.
NAT di origine e collegamenti site-to-site
Per impostazione predefinita, il subnet router riscrive l'indirizzo di origine di ogni pacchetto inoltrato usando il proprio indirizzo privato. Si tratta di SNAT (source network address translation) e serve a fare funzionare le risposte senza modificare nulla nella rete privata: il database all'indirizzo 10.0.0.20 risponde al VPS, che sa già come raggiungerlo. Lo svantaggio è che il database vede ogni connessione della tailnet come proveniente dal VPS. Le regole firewall per origine e i log degli accessi non forniscono quindi informazioni utili.
Disattivatelo su Linux quando volete conservare l'indirizzo tailnet reale del client:
sudo tailscale set --snat-subnet-routes=falseGli host della rete privata devono quindi avere una route verso 100.64.0.0/10, l'intervallo che Tailscale assegna ai dispositivi, con il subnet router come gateway. Senza questa route di ritorno, le risposte vengono inviate al gateway predefinito e non arrivano mai a destinazione. Le connessioni restano quindi bloccate dopo il primo pacchetto. Aggiungete la route statica al gateway della rete privata oppure lasciate SNAT attivo.
Un collegamento site-to-site consiste in due subnet router che svolgono contemporaneamente questa funzione. Ognuno annuncia la propria rete e accetta quella dell'altro:
sudo tailscale up --advertise-routes=10.0.0.0/24 --snat-subnet-routes=false --accept-routesEseguite il comando corrispondente sull'altro router, usando il relativo intervallo. I due intervalli devono essere diversi. Se i trasferimenti di grandi dimensioni si bloccano mentre ssh e ping funzionano correttamente, la causa è l'MSS (maximum segment size), cioè la dimensione massima dei dati trasportati da un pacchetto TCP. L'overhead del tunnel rende i pacchetti inoltrati troppo grandi per alcuni collegamenti intermedi. Il clamping risolve il problema:
sudo iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtuSalvate la regola con iptables-persistent, altrimenti scompare al riavvio successivo.
Manutenzione per mantenere il servizio operativo
Per impostazione predefinita, le chiavi dei nodi scadono dopo 180 giorni, a partire da October 2026. Quando scade la chiave del router subnet, il nodo viene disconnesso e l'intero intervallo annunciato diventa irraggiungibile, senza che vi sia alcuna modifica di configurazione a spiegarlo. Disabilita la scadenza delle chiavi per questa macchina nella pagina Machines della console di amministrazione, quindi annota di averlo fatto. Per un nodo avviato con un tag, come nell'esempio autoApprovers precedente, la scadenza delle chiavi è disabilitata per impostazione predefinita.
Tailscale preferisce una connessione diretta tra i peer e ricorre ai propri server relay quando non riesce a stabilirla. I relay funzionano, ma aggiungono latenza. Un VPS con un indirizzo pubblico è il caso più semplice: consenti il traffico UDP in ingresso sulla porta 41641 e la maggior parte dei peer si connetterà direttamente. Quando il traffico verso l'intervallo privato è più lento di quanto dovrebbe consentire il collegamento al VPS, verificare se il client raggiunge direttamente il router subnet o passa da un relay è il primo controllo da eseguire. Se il firewall è gestito da ufw, le regole ufw effettivamente necessarie su un VPS descrivono la sintassi.
Le regole di accesso costituiscono l'altra metà della configurazione. In una tailnet predefinita, ogni tuo dispositivo può raggiungere tutti gli altri, quindi una route approvata funziona senza ulteriori interventi. Dopo aver scritto una policy ACL, il lato destinazione di una regola deve includere l'intervallo privato, indicandolo esplicitamente oppure usando il wildcard *, che include le route subnet approvate, perché 10.0.0.20 non è un indirizzo tailnet e non è coperto dalle regole scritte per gli indirizzi IP tailnet o per i tag.
Infine, valuta se vuoi affidarti a un coordination server che non gestisci tu. Il control plane di Tailscale è un servizio hosted. Le chiavi restano sulle tue macchine, ma l'account e il file della policy risiedono lì. Prima di affidargli una route verso la tua rete privata, è importante stabilire che cosa potrebbe effettivamente fare qualcuno in caso di compromissione del control plane o di furto delle credenziali di accesso all'identità; il modello di attendibilità di Tailscale indica il confine rilevante. Il costo raramente è il motivo per cui gli utenti abbandonano questo servizio, perché il piano gratuito copre fino a sei utenti con un numero illimitato di dispositivi propri, anche se un router subnet avviato con un tag viene conteggiato diversamente da uno a cui hai effettuato l'accesso personalmente. Oltre quella soglia, il costo dipende dalle persone e non dalle macchine; perciò conviene calcolare quanto paga effettivamente una famiglia o un team di cinque persone quando termina il piano gratuito prima di aggiungere l'account che fa superare il limite. Eseguire Headscale, il control server Tailscale self-hosted mantiene questo componente sul tuo VPS, ma richiede di occuparsi della manutenzione. Un'altra risposta alla stessa esigenza consiste nell'abbandonare anche i client di Tailscale: l'hosting autonomo del server VPN NetBird installa il coordination layer e i relativi client mesh su una macchina sotto il tuo controllo. Se stai ancora scegliendo tra questo modello e una configurazione scritta manualmente, il confronto tra WireGuard e Tailscale spiega che cosa offre il coordination layer e quali costi comporta.
FAQ
Qual è la differenza tra un subnet router e un exit node?
Un subnet router pubblicizza un intervallo di indirizzi privati, consentendo ai dispositivi della tailnet di raggiungere macchine su cui Tailscale non è in esecuzione. Un exit node si pubblicizza come route verso l'intera Internet, quindi un dispositivo invia tutto il proprio traffico attraverso l'indirizzo pubblico di quel nodo. Un singolo VPS può svolgere entrambi i ruoli. Sono flag distinti, --advertise-routes e --advertise-exit-node, e ciascuno richiede un'approvazione separata nella console di amministrazione.
Perché il mio client Linux ignora la subnet route pubblicizzata?
I client Linux non accettano le subnet route se non viene richiesto esplicitamente. Esegui sudo tailscale set --accept-routes sul client. Poi verifica con ip route show table 52, non con ip route show. Tailscale installa le route accettate nella routing table 52 e le raggiunge tramite policy rules, quindi la tabella principale non le elenca e una route funzionante può sembrare assente.
La subnet ha smesso di funzionare dopo un riavvio. Che cosa si è guastato?
Molto probabilmente l'IP forwarding. Un valore impostato con sysctl -w non sopravvive al riavvio, quindi scrivilo in /etc/sysctl.d/99-tailscale.conf e confermalo con sysctl net.ipv4.ip_forward. Se il forwarding è attivo e l'intervallo è ancora irraggiungibile, controlla il nodo nella console di amministrazione. Le node key scadono dopo 180 giorni per impostazione predefinita e un subnet router con una node key scaduta sembra un problema di rete, non un problema dell'account.
Due subnet router possono pubblicizzare lo stesso intervallo?
Sì. Gli intervalli identici sono il modo in cui funziona una coppia ad alta disponibilità: entrambi i router pubblicizzano esattamente gli stessi prefissi. Anche gli intervalli sovrapposti con lunghezze di prefisso diverse sono validi e prevale il prefisso più specifico. In questo caso il failover richiede attenzione: quando il router che gestisce il prefisso più specifico va offline, Tailscale non passa alla route più ampia e il relativo traffico si interrompe. Per una vera coppia standby, configura entrambi i router affinché pubblichino gli stessi prefissi specifici.
Il nome host viene risolto, ma la connessione va in timeout. Perché?
La risoluzione DNS e il routing sono passaggi distinti. Un nome può essere risolto in un indirizzo che non è coperto da alcuna route approvata; in tal caso il pacchetto esce tramite il default gateway del client. Esegui ip route get <address> sul client. Se la risposta non include dev tailscale0 su un client Linux, verifica innanzitutto che --accept-routes sia attivo. Se lo è, pubblicizza un intervallo che includa quell'indirizzo e approva il nuovo prefisso nella console di amministrazione.