WireGuard e Tailscale VPN su un VPS Linux
Configura WireGuard da zero o distribuisci Tailscale per l'accesso VPN gestito su Ubuntu 24.04 e Debian 12, con prevenzione dei DNS leak, rafforzamento PreSharedKey e un confronto neutrale che include Headscale.
Questa guida copre due approcci per l'accesso VPN a un VPS Linux: WireGuard (manuale, controllo completo) e Tailscale (gestito, pronto all'uso). Entrambi usano il protocollo WireGuard sotto il cofano. La differenza sta in chi gestisce le chiavi, il routing e il coordinamento.
Scegli la sezione adatta alla tua situazione, oppure leggi tutte e tre le parti per fare una scelta informata.
Prerequisiti:
- Un VPS con Ubuntu 24.04 o Debian 12 (funziona su un VPS Virtua Cloud)
- Accesso SSH con un utente non-root con sudo
- Un firewall configurato e attivo
- Una macchina locale (Linux, macOS o Windows) come client VPN
Perché collegarsi via VPN al proprio VPS Linux?
Ogni servizio esposto su un IP pubblico è un bersaglio. I bot di brute-force SSH trovano nuovi server in pochi minuti. Le porte dei database, i pannelli di amministrazione e gli endpoint API vengono scansionati costantemente. Una VPN permette di tenere le interfacce di gestione fuori da internet.
Il principio è semplice: associa i servizi sensibili all'indirizzo dell'interfaccia VPN invece di 0.0.0.0. Solo i dispositivi con chiavi VPN valide possono raggiungerli. Internet non vede mai che queste porte esistono.
Casi d'uso comuni:
- Accesso admin senza SSH pubblico. Associa
sshdall'IP WireGuard. Niente più porta 22 esposta al mondo. Fail2ban diventa opzionale quando non c'è nulla da attaccare. - Tunnel verso API private di inferenza IA. Fai girare Ollama o un endpoint LLM privato sul VPS? Mettilo dietro la VPN. Nessun API gateway necessario, nessuna gestione di token per l'accesso interno.
- Rete mesh multi-cloud. Collega nodi VPS di diversi provider (Virtua, Hetzner, OVH) in una rete privata. I servizi comunicano tramite tunnel cifrati senza endpoint pubblici.
- Cifratura del traffico su reti non affidabili. Instrada tutto il traffico attraverso il VPS quando lavori da bar o WiFi di hotel. Il tuo ISP e l'operatore di rete locale vedono solo pacchetti WireGuard cifrati.
Il modello di minaccia conta. Se accedi al VPS solo da un IP fisso dell'ufficio, le regole del firewall possono bastare. Ma se lavori da più postazioni, usi più dispositivi o gestisci un team con diversi livelli di accesso, una VPN è la soluzione più pulita.
Come si installa WireGuard su Ubuntu 24.04 o Debian 12?
WireGuard è un protocollo VPN integrato nel kernel Linux dalla versione 5.6. Usa Curve25519 per lo scambio di chiavi, ChaCha20 per la cifratura e conta circa 4.000 righe di codice (contro le oltre 100.000 di OpenVPN). Installalo con apt, genera le coppie di chiavi, scrivi un file di configurazione e avvia il tunnel. L'intero processo richiede meno di 10 minuti.
Installa WireGuard sul server:
sudo apt update && sudo apt install wireguard wireguard-tools -y
Il pacchetto wireguard fornisce il modulo del kernel. Il pacchetto wireguard-tools fornisce le utility userspace wg e wg-quick.
Come si generano le chiavi WireGuard e si configura il server?
WireGuard usa coppie di chiavi asimmetriche (una per peer) più una chiave precondivisa opzionale per la difesa post-quantistica. Genera una coppia di chiavi server, una coppia client e una chiave precondivisa (PreSharedKey) condivisa tra i due. La chiave precondivisa aggiunge uno strato di cifratura simmetrica sopra lo scambio Curve25519 di WireGuard. Se un futuro computer quantistico dovesse rompere lo scambio asimmetrico, la chiave precondivisa simmetrica continua a proteggere il tunnel.
Sul server, genera le chiavi con un umask restrittivo affinché i file vengano creati con permessi 600:
umask 077
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
wg genpsk | sudo tee /etc/wireguard/psk.key
ls -la /etc/wireguard/
-rw------- 1 root root 45 Mar 19 10:01 psk.key
-rw------- 1 root root 45 Mar 19 10:01 server_private.key
-rw------- 1 root root 45 Mar 19 10:01 server_public.key
Tutti e tre i file hanno permessi 600 (lettura/scrittura solo per il proprietario). La chiave privata e la chiave precondivisa non devono mai lasciare il server.
Sulla macchina locale (il client), genera la propria coppia di chiavi:
umask 077
wg genkey | tee client_private.key | wg pubkey > client_public.key
Serve la chiave pubblica del client sul server e la chiave pubblica del server sul client. La chiave precondivisa va su entrambi i lati. Non trasferire mai le chiavi private.
Abilitare l'inoltro IP
Il server deve instradare il traffico per i client VPN. Abilita l'inoltro IPv4 e IPv6:
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
Usare un file in /etc/sysctl.d/ è preferibile a modificare direttamente /etc/sysctl.conf. Sopravvive agli aggiornamenti dei pacchetti e rende chiaro quali impostazioni appartengono a quale servizio.
File di configurazione del server
Identifica l'interfaccia di rete pubblica del server:
ip route show default
default via 203.0.113.1 dev eth0 proto static metric 100
In questo esempio l'interfaccia è eth0. La tua potrebbe essere ens3, ens18 o altro. Usa quello che appare dopo dev.
Crea la configurazione del server:
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.66.66.1/24, fd42:42:42::1/64
ListenPort = 51820
PrivateKey = <contenuto di /etc/wireguard/server_private.key>
PostUp = nft add table ip wireguard; nft add chain ip wireguard forward { type filter hook forward priority 0 \; policy accept \; }; nft add rule ip wireguard forward iifname "wg0" accept; nft add table ip nat; nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }; nft add rule ip nat postrouting oifname "eth0" masquerade
PostDown = nft delete table ip wireguard; nft delete table ip nat
[Peer]
PublicKey = <contenuto di client_public.key>
PresharedKey = <contenuto di /etc/wireguard/psk.key>
AllowedIPs = 10.66.66.2/32, fd42:42:42::2/128
Sostituisci eth0 nelle righe PostUp/PostDown con il nome reale della tua interfaccia.
Cosa fa ogni sezione:
Address: l'IP VPN assegnato a questo server./24e/64definiscono la dimensione della sottorete VPN.ListenPort: la porta UDP su cui WireGuard è in ascolto. 51820 è la convenzione.PostUp/PostDown: regole nftables che abilitano il NAT masquerading. Quando un client VPN invia traffico verso internet, il server riscrive l'IP sorgente con il proprio IP pubblico. Questo è ciò che fa funzionare la VPN a tunnel completo.AllowedIPsnella sezione[Peer]: quali IP VPN può usare questo client./32significa esattamente un IP. Questo impedisce ai client di falsificare altri indirizzi VPN.
Se usi ufw invece di nftables direttamente, sostituisci PostUp/PostDown con:
PostUp = ufw route allow in on wg0 out on eth0; iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PostDown = ufw route delete allow in on wg0 out on eth0; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Blocca il file di configurazione. Contiene la tua chiave privata:
sudo chmod 600 /etc/wireguard/wg0.conf
Aprire il firewall e avviare il tunnel
Consenti la porta UDP di WireGuard nel firewall:
sudo ufw allow 51820/udp
O direttamente con nftables:
sudo nft add rule inet filter input udp dport 51820 accept
Avvia il tunnel. La direttiva enable lo rende persistente dopo i riavvii. Il flag --now lo avvia immediatamente:
sudo systemctl enable --now wg-quick@wg0
sudo systemctl status wg-quick@wg0
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
Loaded: loaded (/usr/lib/systemd/system/wg-quick@.service; enabled; preset: enabled)
Active: active (exited) since ...
Lo stato mostra active (exited) perché wg-quick configura l'interfaccia e poi termina. Il modulo del kernel gestisce il tunnel da quel punto. Controlla il tunnel attivo:
sudo wg show
interface: wg0
public key: aB3dEfGhIjKlMnOpQrStUvWxYz1234567890abc=
private key: (hidden)
listening port: 51820
peer: xY9zAbCdEfGhIjKlMnOpQrStUvWxYz1234567890=
preshared key: (hidden)
allowed ips: 10.66.66.2/32, fd42:42:42::2/128
L'output (hidden) significa che WireGuard protegge il materiale crittografico sensibile. Se vedi latest handshake per un peer, quel peer si è connesso con successo.
Configurazione del client
Sulla macchina locale, crea la configurazione WireGuard:
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.66.66.2/24, fd42:42:42::2/64
PrivateKey = <contenuto di client_private.key>
DNS = 10.66.66.1
[Peer]
PublicKey = <contenuto di server_public.key>
PresharedKey = <contenuto di psk.key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = YOUR_SERVER_PUBLIC_IP:51820
PersistentKeepalive = 25
Spiegazione dei parametri chiave:
AllowedIPs = 0.0.0.0/0, ::/0instrada tutto il traffico attraverso la VPN (tunnel completo). Per lo split tunneling, dove solo il traffico della sottorete VPN passa per il tunnel, usaAllowedIPs = 10.66.66.0/24, fd42:42:42::/64.Endpointè l'IP pubblico e la porta del server. Il client ne ha bisogno per avviare la connessione. Il server non ha bisogno dell'endpoint del client perché lo apprende dai pacchetti in arrivo.PersistentKeepalive = 25invia un pacchetto keepalive ogni 25 secondi. Questo mantiene attive le mappature NAT affinché il server possa raggiungere il client. Senza, la connessione cade dopo il timeout NAT (tipicamente 30-120 secondi di inattività).DNS = 10.66.66.1indirizza le query DNS all'indirizzo VPN del server. Questo previene i DNS leak (spiegato nella sezione successiva).
Su macOS e Windows, usa l'app WireGuard. Importa il file di configurazione o incollalo.
Connettiti dal client:
sudo wg-quick up wg0
ping 10.66.66.1
PING 10.66.66.1 (10.66.66.1) 56(84) bytes of data.
64 bytes from 10.66.66.1: icmp_seq=1 ttl=64 time=4.23 ms
64 bytes from 10.66.66.1: icmp_seq=2 ttl=64 time=3.98 ms
Dalla macchina locale, conferma che il tuo IP pubblico è cambiato (se usi il tunnel completo):
curl -s https://ifconfig.me
Dovrebbe restituire l'IP pubblico del VPS, non il tuo IP di casa.
Aggiungere altri client
Per ogni client aggiuntivo, genera una nuova coppia di chiavi e una nuova chiave precondivisa (una PSK per coppia di peer). Aggiungi un blocco [Peer] al wg0.conf del server:
[Peer]
PublicKey = <nuova chiave pubblica del client>
PresharedKey = <nuova chiave precondivisa>
AllowedIPs = 10.66.66.3/32, fd42:42:42::3/128
Incrementa l'indirizzo IP per ogni client. Dopo la modifica, ricarica senza interrompere le connessioni esistenti:
sudo wg syncconf wg0 <(sudo wg-quick strip wg0)
Questo applica la nuova configurazione dei peer senza riavviare l'interfaccia. Le connessioni esistenti rimangono attive.
Regolazione del MTU
WireGuard aggiunge 60 byte di overhead per pacchetto (28 byte per gli header IPv4 e UDP esterni, 32 byte per l'header WireGuard). Se il tuo VPS ha un MTU standard di 1500 byte, imposta l'MTU di WireGuard a 1420 nella sezione [Interface]:
MTU = 1420
Impostalo sia su server che su client. MTU diversi causano frammentazione dei pacchetti e cali di throughput difficili da diagnosticare. Se esegui WireGuard su un collegamento con MTU già ridotto (PPPoE, VXLAN), sottrai di conseguenza.
Come si prevengono i DNS leak con WireGuard?
I DNS leak si verificano quando il sistema invia query DNS al di fuori del tunnel VPN, esponendo i domini visitati al tuo ISP o alla rete locale. Questo vanifica il vantaggio di privacy dell'instradamento via VPN. La soluzione: esegui un resolver DNS locale sul server VPN e punta il DNS del client verso di esso attraverso il tunnel.
Installa Unbound sul server:
sudo apt install unbound -y
Crea un file di configurazione per far ascoltare Unbound sull'interfaccia WireGuard:
sudo nano /etc/unbound/unbound.conf.d/wireguard.conf
server:
interface: 10.66.66.1
interface: fd42:42:42::1
interface: 127.0.0.1
access-control: 10.66.66.0/24 allow
access-control: fd42:42:42::/64 allow
access-control: 127.0.0.0/8 allow
do-ip6: yes
hide-identity: yes
hide-version: yes
harden-glue: yes
harden-dnssec-stripped: yes
use-caps-for-id: yes
prefetch: yes
Le direttive hide-identity e hide-version impediscono a Unbound di rivelare la propria versione nelle risposte DNS. La divulgazione della versione aiuta gli attaccanti a puntare vulnerabilità note. Le opzioni harden-* applicano la validazione DNSSEC e prevengono il cache poisoning. L'opzione use-caps-for-id aggiunge la codifica 0x20 alle query DNS, una difesa leggera contro risposte falsificate.
Su Ubuntu 24.04, systemd-resolved ascolta sulla porta 53 di default ed entra in conflitto con Unbound. Disabilitalo:
sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
Avvia Unbound:
sudo systemctl enable --now unbound
sudo systemctl status unbound
● unbound.service - Unbound DNS server
Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled; preset: enabled)
Active: active (running) since ...
Verifica che Unbound risolva dall'interfaccia WireGuard:
dig @10.66.66.1 example.com +short
Dovresti ottenere uno o più indirizzi IP. Gli IP esatti dipendono dai record DNS attuali del dominio.
La configurazione del client imposta già DNS = 10.66.66.1. Quando il tunnel WireGuard è attivo, tutte le query DNS passano attraverso il tunnel cifrato verso Unbound. Nessuna query finisce al tuo ISP.
Per conferma dal lato client, connettiti alla VPN e controlla:
resolvectl status wg0
Il server DNS dovrebbe mostrare solo 10.66.66.1. Puoi anche usare dnsleaktest.com.
| Test | Prima della VPN | Dopo la VPN (con Unbound) |
|---|---|---|
| Server DNS mostrato | Resolver ISP (es. 192.168.1.1) | 10.66.66.1 (Unbound del VPS) |
| IP visto dal sito di test | IP casa/ufficio | IP pubblico del VPS |
| Query DNS visibili all'ISP | Sì | No |
Per approfondire la sicurezza DNS tra cui DNSSEC e DNS-over-HTTPS, vedi .
Kill switch: cosa succede quando il tunnel cade?
Se il tunnel WireGuard cade, il traffico viaggia in chiaro sulla rotta predefinita. Il tuo IP reale e le query DNS sono esposti. Un kill switch previene questo bloccando tutto il traffico non-VPN a livello di firewall.
Sul client, aggiungi regole nftables che consentono solo il traffico attraverso l'interfaccia WireGuard e la connessione cifrata all'endpoint del server:
sudo nft add table inet killswitch
sudo nft add chain inet killswitch output { type filter hook output priority 0 \; policy drop \; }
sudo nft add rule inet killswitch output oifname "wg0" accept
sudo nft add rule inet killswitch output ip daddr YOUR_SERVER_PUBLIC_IP udp dport 51820 accept
sudo nft add rule inet killswitch output oifname "lo" accept
Con questo in atto, se wg0 va giù, tutto il traffico in uscita viene bloccato. Nessun DNS leak, nessun pacchetto in chiaro. L'unico traffico consentito è l'handshake WireGuard cifrato verso il server.
Rimuovi il kill switch per ripristinare il routing normale:
sudo nft delete table inet killswitch
Per un kill switch persistente che si attivi automaticamente, salva queste regole in un file e caricale con un servizio systemd che parte prima di wg-quick@wg0.
Come si installa Tailscale su un VPS Linux?
Tailscale è un servizio VPN mesh costruito su WireGuard. Gestisce la distribuzione delle chiavi, l'attraversamento NAT e la scoperta dei peer tramite un server di coordinamento. Installi il client, ti autentichi con il tuo identity provider e i tuoi dispositivi possono raggiungersi a vicenda. Nessuno scambio manuale di chiavi, nessun port forwarding, nessuna regola firewall da aprire.
Il compromesso: il server di coordinamento di Tailscale è un servizio di terze parti. Vede i metadati dei tuoi dispositivi (IP, hostname, quali dispositivi sono online) ma mai il tuo traffico, che transita peer-to-peer su WireGuard.
Come si installa Tailscale su Ubuntu 24.04 o Debian 12?
Aggiungi il repository ufficiale Tailscale e installa il pacchetto. Questo evita curl | sh e ti permette di verificare gli aggiornamenti tramite apt.
Per Ubuntu 24.04 (Noble):
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update && sudo apt-get install tailscale -y
Per Debian 12 (Bookworm):
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update && sudo apt-get install tailscale -y
Avvia Tailscale e autenticati:
sudo tailscale up
Questo stampa un URL di autenticazione. Aprilo nel browser e accedi con il tuo identity provider (Google, Microsoft, GitHub, ecc.). Una volta autenticato, il VPS entra nel tuo tailnet.
sudo systemctl status tailscaled
● tailscaled.service - Tailscale node agent
Loaded: loaded (/usr/lib/systemd/system/tailscaled.service; enabled; preset: enabled)
Active: active (running) since ...
Controlla l'IP Tailscale assegnato:
tailscale ip -4
100.64.0.1
Ogni dispositivo nel tailnet riceve un indirizzo stabile 100.x.x.x (range CGNAT). Questo IP persiste tra riavvii e riconnessioni. Usalo per raggiungere il VPS da qualsiasi altro dispositivo nello stesso tailnet.
Controlla la connettività con gli altri dispositivi:
tailscale status
100.64.0.1 vps-frankfurt youruser@ linux -
100.64.0.2 laptop youruser@ macOS active; direct 203.0.113.50:41641
L'indicazione direct significa che il traffico transita peer-to-peer su WireGuard. Se dice relay, il traffico passa per un server relay DERP, aggiungendo latenza. Il relay DERP avviene quando entrambi i peer sono dietro NAT restrittivi che impediscono le connessioni dirette.
Disabilitare la scadenza delle chiavi per i server
Le chiavi Tailscale scadono dopo 180 giorni di default. Alla scadenza, il dispositivo va offline finché qualcuno non lo riautentica. Per un VPS che deve restare connesso, hai due opzioni.
Opzione 1: disabilitare la scadenza nella console di amministrazione. Vai alla pagina Machines, trova il VPS, clicca sul menu e seleziona "Disable key expiry".
Opzione 2 (raccomandata): usare una chiave di autenticazione con tag. I dispositivi taggati hanno la scadenza automaticamente disabilitata. Genera una chiave di autenticazione riutilizzabile e taggata nella console di amministrazione sotto Settings > Keys, poi unisciti con:
sudo tailscale up --auth-key=tskey-auth-XXXXX --advertise-tags=tag:server
I tag funzionano anche con le ACL (trattate sotto), rendendoli la scelta migliore per l'infrastruttura server.
Come si configura un exit node Tailscale sul VPS?
Un exit node instrada tutto il traffico internet dei tuoi dispositivi attraverso il VPS. Il traffico in uscita sembra provenire dall'IP del VPS. Funziona come una VPN tradizionale: cifrare tutto, uscire dalla posizione del VPS.
Abilita l'inoltro IP sul VPS:
echo 'net.ipv4.ip_forward = 1' | sudo tee /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.conf
Dichiara il VPS come exit node:
sudo tailscale set --advertise-exit-node
Approva l'exit node nella console di amministrazione. Trova il VPS, clicca sul menu, vai in "Edit route settings" e abilita "Use as exit node".
Dal dispositivo client, inizia a usare l'exit node:
sudo tailscale set --exit-node=<vps-tailscale-ip>
Per mantenere l'accesso alla rete locale (stampanti, NAS, altri dispositivi) mentre il traffico internet passa per l'exit node:
sudo tailscale set --exit-node=<vps-tailscale-ip> --exit-node-allow-lan-access=true
Per smettere di instradare attraverso l'exit node:
sudo tailscale set --exit-node=
Conferma che l'exit node funziona controllando il tuo IP pubblico dal client:
curl -s https://ifconfig.me
Dovrebbe restituire l'IP pubblico del VPS.
Routing di sottorete
Il routing di sottorete espone una rete privata dietro il VPS al tailnet. È utile quando il VPS può raggiungere una sottorete di database privata o servizi interni che non eseguono Tailscale.
sudo tailscale set --advertise-routes=192.168.1.0/24
Approva la rotta nella console di amministrazione come per gli exit node. Una volta approvata, tutti i dispositivi del tailnet possono raggiungere 192.168.1.0/24 attraverso il VPS come gateway, senza installare Tailscale su ogni host di quella sottorete.
Puoi dichiarare più rotte separandole con virgole:
sudo tailscale set --advertise-routes=192.168.1.0/24,10.0.0.0/16
Per router di sottorete molto utilizzati con molti flussi contemporanei, Tailscale raccomanda la modalità kernel (solo Linux) rispetto alla modalità userspace. Su Linux, la modalità kernel è il default. Verifica con:
tailscale debug prefs | grep RouteAll
Come si configurano le ACL Tailscale per l'accesso al VPS?
Di default, tutti i dispositivi in un tailnet possono raggiungere qualsiasi altro dispositivo su tutte le porte. In produzione, limita questo con le ACL nel file di policy del tailnet.
Una policy minima che limita l'accesso al VPS a un gruppo admin:
{
"groups": {
"group:admins": ["alice@example.com", "bob@example.com"]
},
"tagOwners": {
"tag:server": ["group:admins"]
},
"acls": [
{
"action": "accept",
"src": ["group:admins"],
"dst": ["tag:server:*"]
}
]
}
Significa: solo i membri di group:admins possono accedere ai dispositivi con tag tag:server. Tutte le altre connessioni sono rifiutate di default. Modifica nella console di amministrazione sotto Access Controls.
Tagga il VPS quando entra nel tailnet:
sudo tailscale up --advertise-tags=tag:server
Una policy più granulare può limitare per porta:
{
"groups": {
"group:admins": ["alice@example.com"],
"group:developers": ["bob@example.com", "charlie@example.com"]
},
"tagOwners": {
"tag:server": ["group:admins"]
},
"acls": [
{
"action": "accept",
"src": ["group:admins"],
"dst": ["tag:server:*"]
},
{
"action": "accept",
"src": ["group:developers"],
"dst": ["tag:server:22,80,443"]
}
]
}
Gli sviluppatori ottengono accesso SSH (22) e web (80, 443). Gli admin hanno accesso completo. Nessun altro può raggiungere il server. Tailscale applica queste regole a livello client, quindi il traffico è bloccato prima ancora di raggiungere il server.
MagicDNS
Tailscale include MagicDNS, che assegna a ogni dispositivo un hostname risolvibile nel tailnet. Invece di ricordare 100.64.0.1, fai SSH a vps-frankfurt. Abilitalo nella console di amministrazione nelle impostazioni DNS. Nessun Unbound o configurazione DNS manuale necessaria.
Cos'è Headscale e quando usarlo?
Headscale è un'implementazione open source e self-hosted del server di coordinamento Tailscale. Usa i client Tailscale standard ma esegue il piano di controllo sulla tua infrastruttura. Nessun limite di dispositivi, nessuna telemetria, nessuna dipendenza dal SaaS Tailscale. Compatibile con tutti i client ufficiali Tailscale (Linux, macOS, Windows, iOS, Android).
L'architettura:
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Client A │──────▶│ Headscale │◀──────│ Client B │
│ (tailscale) │ │ (il tuo server) │ │ (tailscale) │
└──────┬───────┘ └──────────────────┘ └──────┬───────┘
│ │
└────────────── Tunnel WireGuard ──────────────────┘
(diretto, peer-to-peer)
Headscale gestisce lo scambio di chiavi, la registrazione dei dispositivi e l'applicazione delle ACL. Il traffico VPN effettivo fluisce direttamente tra i peer tramite WireGuard. Headscale non vede mai il tuo traffico dati, solo i metadati di coordinamento.
Cosa supporta Headscale oggi: registrazione dispositivi (CLI e OIDC), ACL, router di sottorete, exit node, MagicDNS, chiavi pre-autorizzate e tag. Copre il set di funzionalità core di Tailscale.
Cosa non supporta: Tailscale Funnel, Serve, log dei flussi di rete e alcune funzionalità beta. L'interfaccia di amministrazione è solo CLI. Esistono web UI create dalla comunità (headscale-ui) ma non coprono ogni funzionalità.
Quando Headscale ha senso:
- Le normative vietano server di coordinamento di terze parti. Per il SaaS di Tailscale potrebbero essere necessari accordi di trattamento dati GDPR. Headscale elimina questa dipendenza.
- Servono più dispositivi di quanti ne consenta il piano gratuito di Tailscale.
- Vuoi il pieno controllo di audit sulla registrazione dei dispositivi e la gestione delle chiavi.
- Stai costruendo un'infrastruttura dove dipendere da un SaaS esterno è un single point of failure.
Quando no:
- Hai bisogno della rete globale di relay DERP di Tailscale per un attraversamento NAT affidabile. Headscale può usare DERP, ma devi gestire i tuoi relay o accettare di usare quelli pubblici di Tailscale.
- Vuoi un'interfaccia di amministrazione curata. Headscale è CLI-first.
- Hai un team piccolo e zero voglia di mantenere un altro servizio.
Un tutorial completo di configurazione Headscale è previsto per un futuro articolo. Per ora, vedi la documentazione Headscale.
WireGuard vs Tailscale vs Headscale: quale si adatta al tuo caso?
Usa WireGuard se hai bisogno di controllo completo, latenza minima, reti air-gapped o requisiti normativi che vietano server di coordinamento di terze parti. Usa Tailscale se gestisci più dispositivi, hai bisogno di attraversamento NAT senza port forwarding o vuoi ACL senza configurazione manuale. Per team che vogliono le funzionalità Tailscale con controllo self-hosted, considera Headscale.
| Dimensione | WireGuard | Tailscale | Headscale |
|---|---|---|---|
| Tempo di setup | 10-15 min per peer | 2 min per dispositivo | 30-60 min (server + client) |
| Gestione chiavi | Manuale (generare, distribuire, ruotare) | Automatica (server di coordinamento) | Automatica (il tuo server) |
| Attraversamento NAT | Nessuno. Richiede port forwarding o IP pubblico su almeno un lato | Integrato (relay DERP + STUN) | Parziale (DERP proprio o relay pubblici) |
| Scoperta peer | Configurazione manuale per peer | Mesh automatico | Mesh automatico |
| ACL | Regole firewall (nftables/iptables) | File di policy nella console admin | File di policy sul tuo server |
| Max dispositivi | Illimitati | Il piano gratuito ha limiti (vedi pagina prezzi) | Illimitati |
| Mesh multi-cloud | Config su ogni nodo, N*(N-1)/2 voci peer | Unirsi al tailnet, il mesh si forma da solo | Come Tailscale, controllo self-hosted |
| Dipendenza terze parti | Nessuna | Tailscale Inc. (solo coordinamento) | Nessuna |
| GDPR / compliance | Pieno controllo, nessun responsabile del trattamento esterno | Tailscale tratta i metadati dei dispositivi | Pieno controllo |
| DNS | Manuale (Unbound, ecc.) | MagicDNS (automatico, hostname per dispositivo) | MagicDNS (con configurazione) |
| Latenza | Minima (WireGuard a livello kernel) | Minima in diretto; +20-50 ms con relay DERP | Come Tailscale |
| Onboarding team | Condividere config e chiavi manualmente | Link di invito, login SSO | Registrazione via CLI o OIDC |
| Difesa post-quantistica | PreSharedKey (setup manuale) | Non configurabile dall'utente | Non configurabile dall'utente |
Scorciatoie decisionali
Sviluppatore singolo, un VPS: WireGuard. Il percorso più semplice. Zero dipendenze. La latenza più bassa possibile. Generi due chiavi e scrivi due file di configurazione.
Team di 3-15, più dispositivi: Tailscale. Il server di coordinamento risparmia ore di gestione chiavi. Le ACL sono più pulite del mantenere regole nftables per peer. L'attraversamento NAT funziona senza modifiche alla rete.
Ambiente regolamentato o obbligo di self-hosting: Headscale se vuoi l'esperienza Tailscale senza la dipendenza da terze parti. WireGuard puro se vuoi zero parti mobili e il tuo team può gestire le configurazioni.
Mesh multi-cloud (5+ nodi presso diversi provider): Tailscale o Headscale. Con WireGuard, 10 nodi richiedono 45 voci peer in totale. A 20 nodi, sono 190. L'onere di gestione della configurazione cresce quadraticamente.
Accesso a endpoint di inferenza IA: Se fai un tunnel dal laptop a un VPS GPU, entrambi funzionano. Tailscale è più veloce da configurare. WireGuard non aggiunge overhead misurabile per chiamate di inferenza sensibili alla latenza. Per setup multi-GPU tra provider, il mesh Tailscale vale il compromesso.
Risoluzione dei problemi
Tunnel WireGuard attivo ma nessun traffico:
Controlla l'inoltro IP:
sysctl net.ipv4.ip_forward
Dovrebbe restituire net.ipv4.ip_forward = 1. Controlla che le regole di masquerade siano caricate:
sudo nft list ruleset | grep masquerade
Se vuoto, le regole PostUp non sono state eseguite. Riavvia con sudo systemctl restart wg-quick@wg0 e controlla journalctl -u wg-quick@wg0 per errori.
L'handshake WireGuard non si completa mai:
sudo wg show
Se latest handshake non appare mai per un peer, la porta UDP 51820 è bloccata da qualche parte. Conferma che il server è in ascolto:
sudo ss -ulnp | grep 51820
UNCONN 0 0 0.0.0.0:51820 0.0.0.0:*
WireGuard usa direttamente il modulo del kernel, quindi ss potrebbe non mostrare un nome di processo per il socket.
Poi testa dal lato client. Se il client è dietro un firewall aziendale, l'UDP 51820 potrebbe essere bloccato. Alcune reti consentono solo TCP 443.
Tailscale mostra "offline" nella console di amministrazione:
sudo systemctl status tailscaled
Se è in esecuzione ma risulta offline, riautenticati:
sudo tailscale up --force-reauth
Se tailscaled non è in esecuzione, controlla i conflitti di porta con altro software VPN.
DNS che continua a filtrare dopo la configurazione di Unbound:
Controlla che Unbound ascolti sull'IP WireGuard:
ss -ulnp | grep :53
Cerca 10.66.66.1:53 nell'output. Se Unbound è in ascolto solo su 127.0.0.1, rivedi le righe interface: in /etc/unbound/unbound.conf.d/wireguard.conf.
Su Ubuntu, controlla anche che systemd-resolved sia effettivamente fermo:
sudo systemctl is-active systemd-resolved
Se restituisce active, sta competendo con Unbound per la porta 53.
Log dei servizi:
journalctl -u wg-quick@wg0 -f
journalctl -u tailscaled -f
journalctl -u unbound -f
Copyright 2026 Virtua.Cloud. Tutti i diritti riservati. Questo contenuto è un'opera originale del team Virtua.Cloud. La riproduzione, ripubblicazione o redistribuzione senza autorizzazione scritta è vietata.
Pronto a provare?
Distribuisci il tuo server in pochi secondi. Linux, Windows o FreeBSD.
Vedi piani VPS