Tailscale al posto del port forwarding: come funziona
Accedi a NAS, Raspberry Pi o server Minecraft senza aprire porte sul router. Scopri NAT, relay e i limiti di Tailscale per l'accesso da Internet.
Tailscale richiede il port forwarding?
Tailscale non richiede il port forwarding e, per raggiungere i propri dispositivi, lo sostituisce completamente. Ogni dispositivo nella tailnet (la rete privata che Tailscale crea tra i dispositivi) apre le proprie connessioni in uscita. Non è necessario modificare il router di casa: nessuna porta inoltrata, nessun host DMZ (demilitarized zone), nessun record DNS dinamico e nessun requisito di indirizzo IP pubblico. Un NAS (dispositivo di archiviazione connesso alla rete), un Raspberry Pi o un game server dietro un router ipTIME o Fritz!Box diventano raggiungibili dal laptop ovunque ci si trovi, usando il proprio indirizzo privato, mentre il lato in ingresso del router resta chiuso.
Anche ciò che Tailscale non fa è semplice da definire. Tailscale connette i dispositivi che hanno effettuato l'accesso alla propria tailnet o che sono stati condivisi al suo interno. Un estraneo su Internet, o un amico che non ha effettuato l'accesso, non può raggiungere nulla tramite Tailscale. Esporre un servizio all'intera Internet pubblica è un'attività diversa, descritta verso la fine.
Come Tailscale attraversa il NAT senza una porta inoltrata
Il port forwarding esiste a causa del NAT (network address translation). Il router gestisce l'unico indirizzo IPv4 pubblico e ogni dispositivo dietro di esso ne usa uno privato. Un pacchetto in ingresso che arriva al router non contiene informazioni sul dispositivo privato a cui è destinato, quindi il router lo scarta. Un port forwarding è una regola manuale che stabilisce che «la porta 25565 appartiene a 192.168.0.20». Tailscale ottiene lo stesso risultato senza questa regola, in quattro passaggi.
Per prima cosa, ogni nodo avvia una connessione in uscita. All'avvio, tailscaled apre una connessione HTTPS al server di coordinamento sulla porta TCP 443. Invia la propria chiave pubblica WireGuard e apprende le chiavi pubbliche e gli indirizzi di tutti gli altri nodi del tailnet. Il server di coordinamento non trasporta mai il traffico: gestisce soltanto le chiavi e la rubrica degli indirizzi.
In secondo luogo, ogni nodo determina come viene visto dall'esterno. Invia una richiesta STUN (session traversal utilities for NAT) tramite UDP alla porta 3478 sui server relay di Tailscale. La risposta contiene l'IP pubblico e la porta assegnata dal router al pacchetto in uscita. Questa è la mappatura che un port forwarding avrebbe creato manualmente, con la differenza che il router l'ha creata autonomamente per un flusso in uscita. Se il router supporta UPnP o NAT-PMP, Tailscale gli chiede anche di creare automaticamente una mappatura. Questo può essere utile, ma il funzionamento non dipende da tale funzione.
In terzo luogo, entrambi i lati eseguono il punching. Il nodo A e il nodo B apprendono l'endpoint pubblico dell'altro tramite il server di coordinamento. Entrambi inviano contemporaneamente pacchetti UDP dal proprio listener, sulla porta 41641 per impostazione predefinita, all'endpoint pubblico dell'altro lato. Ogni router dispone già di una mappatura in uscita per il proprio nodo, quindi il pacchetto che arriva dall'altro lato corrisponde a tale mappatura e viene lasciato passare. Da quel momento i due nodi comunicano direttamente tramite WireGuard e il router continua a non avere alcuna regola di inoltro.
In quarto luogo, quando il punching non riesce, il traffico passa attraverso un relay. Il CGNAT (carrier-grade NAT, in cui l'ISP colloca l'utente dietro un secondo NAT sotto il proprio controllo) e il NAT simmetrico (in cui il router sceglie una nuova porta per ogni destinazione, rendendo inutilizzabile la risposta STUN) impediscono entrambi il terzo passaggio. Lo stesso vale per un firewall aziendale che blocca UDP. Tailscale invia quindi i pacchetti WireGuard crittografati attraverso un server DERP (designated encrypted relay for packets) sulla porta TCP 443. Il relay vede soltanto testo cifrato. Questa modalità aumenta inoltre la latenza e riduce il throughput; perché una connessione Tailscale inoltrata tramite relay è lenta e come renderla diretta spiega come identificare il percorso in uso e quali modifiche applicare.
Nessuno di questi quattro passaggi è una connessione in ingresso al router. È questo il motivo per cui non serve alcun port forwarding.
Installare il client e verificare il percorso
L'installazione richiede uno script e un accesso per ogni dispositivo.
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale ip -4tailscale up stampa un URL di accesso. Aprirlo, effettuare l'accesso e il dispositivo entrerà nella tailnet. tailscale ip -4 stampa l'indirizzo tailnet del dispositivo nell'intervallo 100.64.0.0/10. Questo indirizzo rimane invariato dopo i riavvii e quando il dispositivo cambia rete. È quindi l'indirizzo da inserire nelle configurazioni SSH e nei client di gioco.
Da un secondo dispositivo nella tailnet, verificare il percorso verso il primo:
tailscale ping nasUsare il nome host o l'indirizzo tailnet. La prima risposta spesso indica via DERP, perché il percorso diretto è ancora in fase di negoziazione. Entro pochi secondi, le risposte dovrebbero mostrare un IP pubblico e una porta. Questo indica che il traversal NAT ha avuto esito positivo. Se dopo un minuto le risposte indicano ancora via DERP, uno dei due dispositivi si trova dietro un NAT che il traversal non riesce ad attraversare. La connessione usa quindi un relay.
La regola firewall che vale la pena aggiungere
Tailscale funziona senza modificare il firewall nella maggior parte delle reti, perché il traffico UDP in uscita è normalmente consentito. Una regola opzionale aumenta la probabilità di ottenere un percorso diretto: consentire il traffico UDP in ingresso sulla porta 41641.
Su un router domestico o su un firewall aziendale, questo significa consentire il traffico UDP in uscita verso la porta 41641 e, se il traffico UDP in uscita è limitato, anche verso la porta 3478 per STUN. La maggior parte dei router domestici lo consente già, quindi non è necessario intervenire.
Su un VPS, la direzione utile è quella in ingresso. Un VPS dispone di un indirizzo IP pubblico e non ha un NAT davanti, quindi una regola per il traffico UDP in ingresso sulla porta 41641 rende il VPS facilmente raggiungibile da ogni peer: il tentativo di attraversamento NAT del peer arriva sempre a destinazione, anche quando il NAT del peer è difficile da attraversare. Con ufw:
sudo ufw allow 41641/udp
sudo ufw statusufw status dovrebbe elencare 41641/udp come ALLOW da Anywhere. I provider che gestiscono un firewall di rete separato nel pannello di controllo richiedono la stessa regola anche in quella sede, perché un pacchetto bloccato al perimetro del provider non raggiunge mai ufw. Questa regola è una comodità, non un requisito. Con la porta chiusa, il VPS entra comunque nella tailnet e i peer possono ancora raggiungerlo; alcuni lo fanno tramite un relay anziché direttamente.
Raggiungere un NAS domestico o un Raspberry Pi dall'esterno
Il primo caso è il più semplice ed è quello che la maggior parte delle persone intende con «inoltro delle porte tramite Tailscale»: accedere a un dispositivo di casa da un laptop o da un telefono che si trova fuori dalla rete domestica.
Installa il client sul dispositivo di casa e sul laptop. Questa è tutta la configurazione necessaria. Il NAS o il Pi sarà ora raggiungibile all'indirizzo tailnet per ogni servizio in esecuzione, senza inoltrare alcuna porta:
ssh pi@100.101.102.103
curl -I http://100.101.102.103:8080/Sostituisci l'indirizzo con l'output di tailscale ip -4 eseguito sul dispositivo di casa. L'accesso SSH dovrebbe comportarsi esattamente come quando sei connesso al Wi-Fi di casa e curl -I dovrebbe visualizzare la riga dello stato HTTP dell'applicazione Web in esecuzione sul dispositivo. Poiché la connessione è autenticata tramite chiavi WireGuard associate a un dispositivo con sessione attiva, un servizio che sarebbe rischioso esporre tramite una porta inoltrata, come una condivisione SMB (server message block) o un pannello di amministrazione Web, è ragionevolmente sicuro in questo contesto: solo i tuoi dispositivi possono inviargli pacchetti. Il router ipTIME o Fritz!Box intermedio non riceve mai una connessione in ingresso e non richiede modifiche. Se il provider ti ha collocato dietro CGNAT, questa configurazione continua a funzionare, perché il dispositivo di casa stabilisce esclusivamente connessioni in uscita e, nel caso peggiore, il traffico passa attraverso un relay.
MagicDNS, attivo per impostazione predefinita nelle nuove tailnet, assegna inoltre un nome a ogni nodo. Di conseguenza, ssh pi@nas funziona non appena il laptop è connesso alla tailnet.
Quando il dispositivo non può eseguire Tailscale: un subnet router
Alcuni dispositivi non possono eseguire il client: una stampante, una telecamera IP, un vecchio NAS con un sistema operativo limitato oppure una smart TV. Un subnet router risolve il problema. Un dispositivo della rete domestica in grado di eseguire Tailscale, anche un Pi, pubblicizza l'intera subnet domestica. Gli altri dispositivi del tailnet instradano il traffico verso quella subnet attraverso il Pi.
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-tailscale.conf
sudo sysctl --system
sudo tailscale up --advertise-routes=192.168.0.0/24Usa la subnet domestica effettiva. La route deve quindi essere approvata nella console di amministrazione, nelle impostazioni delle route della macchina. I client Linux devono inoltre abilitarla esplicitamente con sudo tailscale set --accept-routes. Dopo questa configurazione, ping 192.168.0.50 dal laptop raggiunge la telecamera a casa. Il parametro sysctl di forwarding è necessario perché, senza di esso, il Pi scarta ogni pacchetto non indirizzato a se stesso. In questo caso la route risulta approvata, ma nessun dispositivo dietro il Pi risponde. La procedura di approvazione, l'abilitazione lato client e gli altri casi in cui una route risulta approvata ma non raggiungibile sono descritti in esecuzione di un subnet router Tailscale, che usa un VPS come router, ma si applica senza modifiche anche a un Pi nel soggiorno.
Permettere agli amici di collegarsi a un server Minecraft senza aprire il router
Caso due: un server Minecraft su un PC di casa e alcuni amici che vogliono collegarsi. La soluzione tradizionale consiste nell'inoltrare la porta TCP 25565 sul router e comunicare il proprio IP pubblico. In questo modo l'indirizzo diventa visibile anche a ogni scanner su Internet. Tailscale sostituisce questa configurazione con la condivisione.
Sono disponibili due opzioni. La prima consiste nell'invitare gli amici nel proprio tailnet come utenti. Funziona, ma il piano gratuito limita il numero di account utente e fornisce loro un accesso all'intera rete, che è più di quanto serva per un gioco. La seconda opzione, preferibile, è la condivisione del nodo. Nella console di amministrazione, aprire la pagina Machines, individuare il PC usato per il gioco, aprire il relativo menu e scegliere Share. Tailscale genera un link di invito. Ogni amico deve avere un proprio account Tailscale gratuito, che diventa il proprietario del proprio piccolo tailnet, e deve accettare il link da quell'account. La macchina condivisa viene quindi visualizzata nell'elenco delle macchine dell'amico, e solo quella macchina. La condivisione concede al destinatario l'accesso alla macchina condivisa e a nient'altro nel proprio tailnet. Per impostazione predefinita, una macchina condivisa è isolata: può rispondere alle connessioni provenienti dal tailnet dell'amico, ma non può avviarne.
Gli amici aggiungono il server in Minecraft usando il relativo indirizzo tailnet, 100.101.102.103:25565, oppure soltanto l'indirizzo quando la porta è quella predefinita. Il PC che esegue il gioco non richiede alcuna porta inoltrata e il router non viene modificato. Le macchine condivise non pubblicizzano le route della subnet. La condivisione funziona quindi per un servizio eseguito direttamente sulla macchina condivisa, che è esattamente il caso di un server di gioco.
Il limite è che ogni giocatore deve eseguire Tailscale e accettare la condivisione. Per un gruppo di amici è una soluzione adeguata. Per un server pubblico a cui chiunque può collegarsi, invece, non lo è. Le due sezioni successive descrivono la soluzione per questo caso.
Eseguire il game server su un VPS e mantenere RCON nella tailnet
L'altro modo per evitare il port forwarding consiste nel non ospitare il gioco a casa. Un VPS ha un IP pubblico e non si trova dietro NAT, quindi la porta del gioco è pubblicamente accessibile senza coinvolgere alcun router. Eseguire un server Minecraft su un VPS illustra il dimensionamento, i flag Java, i backup e l'unità systemd. Qui è importante capire quali porte sono esposte a Internet.
Un server Minecraft apre due porte. La porta TCP 25565 è quella del gioco e deve essere accessibile ai giocatori. La porta TCP 25575 è RCON (console remota): accetta una password e poi esegue qualsiasi comando del server, inclusi op e stop. Una porta RCON esposta a Internet è un obiettivo per i tentativi di indovinare la password. Inserisci il VPS nella tua tailnet e applica regole diverse alle due porte:
sudo ufw allow OpenSSH
sudo ufw allow 25565/tcp
sudo ufw allow in on tailscale0 to any port 25575 proto tcp
sudo ufw enable
sudo ufw statusLa seconda regola espone il gioco a tutti. La terza consente l'accesso a RCON soltanto ai pacchetti ricevuti sull'interfaccia tailscale0, quindi solo dai dispositivi presenti nella tua tailnet. L'IP pubblico continua a rispondere sulla porta 25565, mentre una connessione alla porta 25575 proveniente dalla rete pubblica viene eliminata dalla policy deny predefinita di ufw. Verifica entrambe le porte dal tuo laptop, che si trova nella tailnet:
nc -zv 100.101.102.103 25575
nc -zv <vps-public-ip> 25575Il primo comando dovrebbe stampare succeeded. Il secondo dovrebbe restare in attesa e poi andare in timeout, perché il pacchetto è arrivato dall'interfaccia pubblica e non corrisponde ad alcuna regola allow. Lo stesso schema si applica a SSH, a una web map, a un database o a una dashboard per le metriche: la porta pubblica sull'IP pubblico, le porte amministrative soltanto su tailscale0.
Pubblicare un servizio su Internet: Funnel o reverse tunnel tramite VPS
Il terzo caso è quello che Tailscale, da solo, non risolve. Un blog, un'API pubblica, un game server pubblico o una pagina di stato: i visitatori non fanno parte della tailnet e non ne faranno mai parte. Esistono due strumenti per gestire questo scenario, descritti ciascuno in un articolo dedicato.
Tailscale Funnel pubblica un servizio HTTPS da un nodo su Internet tramite i relay di Tailscale. Funziona solo con TLS (transport layer security) e solo sulle porte 443, 8443 e 10000. È quindi adatto a un'applicazione web, ma non a un protocollo di gioco non incapsulato sulla porta 25565. Tailscale Serve e Funnel a confronto spiega cosa espone ciascuno strumento e a quali utenti.
Un reverse tunnel tramite VPS gestisce tutti gli altri casi. Il server di casa apre un tunnel in uscita verso un VPS con un IP pubblico, quindi il VPS inoltra una porta pubblica attraverso il tunnel, usando TCP o UDP e qualsiasi numero di porta. È lo strumento adatto per un server Minecraft pubblico ospitato a casa e situato dietro CGNAT; la guida un reverse tunnel tramite VPS per un server domestico dietro CGNAT illustra la procedura. Scegli una di queste due soluzioni e non cercare un'impostazione di Tailscale che apra una porta al mondo intero. Non esiste.
Cosa non fa Tailscale
- Non inoltra una porta per client pubblici arbitrari. Un pacchetto proveniente dall'esterno della tailnet non raggiunge mai il nodo, perché non esiste una chiave WireGuard associata e un pacchetto WireGuard privo di una chiave valida viene scartato senza risposta.
- Non offre al pubblico un modo per accedere. Gli utenti devono essere membri della tailnet oppure avere accettato un nodo condiviso.
- Non garantisce un percorso diretto. In presenza di un NAT difficile, la connessione viene inoltrata tramite un relay ed è quindi più lenta.
- Non apre il router. Il router resta chiuso, ed è proprio questo il punto.
FAQ
Tailscale richiede il port forwarding?
No. Ogni nodo Tailscale stabilisce solo connessioni in uscita. Raggiunge il server di coordinamento tramite HTTPS sulla porta TCP 443 e rileva il proprio indirizzo pubblico con STUN sulla porta UDP 3478. Le connessioni dirette tra peer usano UDP hole punching sulla porta 41641. Se il tentativo fallisce, il traffico passa attraverso un relay DERP sulla porta TCP 443, sempre in uscita. Un router domestico non richiede porte inoltrate né un host DMZ. Anche un dispositivo dietro CGNAT si connette nello stesso modo.
Tailscale può sostituire il port forwarding per un server Minecraft?
Sì, per un server a cui si connettono i tuoi amici. Installa Tailscale sul PC di gioco, condividi quel computer con ogni amico dalla pagina Machines della console di amministrazione e chiedi loro di connettersi all'indirizzo tailnet del computer sulla porta 25565, senza inoltrare porte. Tailscale non sostituisce il port forwarding per un server pubblico, perché i giocatori esterni alla tua tailnet non possono raggiungere il nodo. In questo caso, ospita il gioco su un VPS con un indirizzo IP pubblico e mantieni RCON nella tailnet, oppure usa un reverse tunnel da un VPS verso il computer di casa.
Quali porte usa Tailscale?
Tre. Le connessioni in uscita sulla porta TCP 443 trasportano la connessione al server di coordinamento e il traffico del relay DERP. Le connessioni in uscita sulla porta UDP 3478 usano STUN per rilevare l'indirizzo pubblico. La porta UDP 41641 è il listener WireGuard predefinito per le connessioni dirette e può essere modificata se la porta 41641 è già occupata. Nessuna di queste porte deve essere aperta in ingresso. Consentire traffico UDP in ingresso sulla porta 41641 in un VPS è facoltativo e consente più spesso ai peer di usare un percorso diretto.
Perché la mia connessione Tailscale usa un relay invece di essere diretta?
tailscale ping continua a rispondere via DERP quando l'UDP hole punching non riesce a completarsi. Le cause più comuni sono un NAT che il tentativo non riesce ad attraversare, ad esempio CGNAT o un NAT simmetrico che assegna una nuova porta per ogni destinazione, e un firewall che blocca l'UDP in uscita. Correggi ciò che puoi controllare: consenti UDP in uscita sulle porte 41641 e 3478 oppure colloca un peer su un VPS con la porta UDP 41641 aperta in ingresso. In questo modo il tentativo dell'altro lato ha sempre una destinazione fissa.