Loading theme
~/saverio

Lockdown con Tailscale e Firewall

28 feb 2026· agg. 21 mar 2026· 6 min
tailscalefirewallsecurityhetznercloudflare

Lockdown con Tailscale e Firewall

Prima cosa su una nuova VPS: installa Tailscale, connettiti via Tailscale, poi blocca il firewall in modo che solo tu (via Tailscale) e Cloudflare (per il traffico web) possiate raggiungere il server. Nessun altro.

Una VPS è come il tuo laptop, ma collegata a tutta internet. Miliardi di persone possono sondarla, provare a bucarla e sfruttarla. Tu la vuoi accessibile solo a te. E se ci ospiti un sito, vuoi che solo Cloudflare arrivi all'origin, così sta davanti e blocca gli attacchi. Non esporre mai una VPS direttamente al world wide web. In pratica, parliamo del world wild web.

Questa dovrebbe essere una cosa banale per qualsiasi VPS. In un mondo ideale, ogni provider di VPS userebbe Tailscale (o simile) di default e lo renderebbe l'unica via d'accesso. Finché non succede, fallo a mano.


Il workflow

  1. Crea il server Hetzner (o qualsiasi VPS).
  2. Connettiti via SSH una volta usando l'IP pubblico (serve un accesso iniziale).
  3. Installa Tailscale e collegati.
  4. Apri una nuova sessione SSH via il tuo IP Tailscale e verifica che funzioni.
  5. Blocca il firewall: SSH solo da Tailscale, HTTPS solo da Cloudflare.
  6. Chiudi la sessione SSH pubblica. Da ora in poi ti colleghi solo via Tailscale.

Installa Tailscale

Connettiti via SSH al server come root (o con sudo):

ssh root@YOUR_SERVER_IP

Installa Tailscale:

curl -fsSL https://tailscale.com/install.sh | sh

Collegati alla tua rete Tailscale. Per server headless usa una auth key (la generi su Tailscale Admin Console):

tailscale up --auth-key=tskey-auth-xxxxxxxxxxxx

Oppure, se hai display e browser:

tailscale up

Recupera il tuo IP Tailscale:

tailscale ip -4

Output di esempio: 100.x.x.x. Quello è il tuo indirizzo privato Tailscale.


Verifica l'accesso Tailscale

Dalla tua macchina locale (con Tailscale installato), apri un nuovo terminale:

ssh [email protected]

Sostituisci 100.x.x.x con l'IP da tailscale ip -4. Se ti colleghi, Tailscale funziona. Tieni aperta questa sessione. Non chiudere ancora la sessione su IP pubblico.


Blocca il firewall

Restringerai:

  • SSH (porta 22 o 2222): solo da IP Tailscale (100.64.0.0/10)
  • HTTPS (porta 443): solo dai range IP di Cloudflare
  • HTTP (porta 80): solo da Cloudflare (per i redirect verso HTTPS)

Tutto il resto è negato.

UFW sul server

Docker bypassa UFW per le porte pubblicate. Per SSH e 80/443 sull'host, UFW funziona. Se usi Coolify, le sue porte (8000, 6001, 6002) vanno restritte tramite il Cloud Firewall di Hetzner.

Resetta UFW e aggiungi le regole:

ufw default deny incoming
ufw default allow outgoing

# SSH solo da Tailscale (100.64.0.0/10 è il range CGNAT che Tailscale usa)
ufw allow from 100.64.0.0/10 to any port 22 proto tcp
# Oppure se usi la porta 2222 per SSH:
# ufw allow from 100.64.0.0/10 to any port 2222 proto tcp
#
# Se Coolify gira sullo stesso host, devi anche permettere alle reti Docker di raggiungere SSH
# (vedi sezione "Coolify sullo stesso server" più sotto).

# HTTP/HTTPS solo da Cloudflare
# Recupera gli IPv4 e IPv6 di Cloudflare e poi aggiungi le regole (vedi sotto)

ufw --force enable

Range IP di Cloudflare

Cloudflare pubblica i range IPv4 e IPv6. Recuperali e permettili:

# IPv4
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
  ufw allow from $ip to any port 80 proto tcp
  ufw allow from $ip to any port 443 proto tcp
done

# IPv6
for ip in $(curl -s https://www.cloudflare.com/ips-v6); do
  ufw allow from $ip to any port 80 proto tcp
  ufw allow from $ip to any port 443 proto tcp
done

Esegui questo prima di ufw enable se stai costruendo le regole da zero. Oppure eseguilo e poi fai ufw reload.

Hetzner Cloud Firewall

Se usi Hetzner Cloud, puoi anche (o invece) usare il Cloud Firewall di Hetzner. Si applica a livello di rete prima che il traffico raggiunga il server. Crea un firewall con:

PortaProtocolloSorgenteScopo
22 (o 2222)TCP100.64.0.0/10SSH (solo Tailscale)
80TCPCloudflare IPv4 + IPv6HTTP
443TCPCloudflare IPv4 + IPv6HTTPS

Per Coolify (8000, 6001, 6002), aggiungi regole che permettano solo il tuo range Tailscale o il tuo IP. Vedi Server Setup per le regole specifiche di Coolify.


Coolify sullo stesso server: perché la validazione si rompe dopo una regola SSH solo-Tailscale

Tailscale non ha rotto Coolify. UFW (e una regola Hetzner equivalente) ha fatto esattamente quello che gli hai chiesto: permettere SSH solo dal range CGNAT di Tailscale (100.64.0.0/10) e da qualche altra fonte. L'accesso umano via Tailscale continua a funzionare.

Coolify valida il server aprendo una sessione SSH dall'interno di un container Docker (l'app Coolify, il sentinel, o servizi correlati). Quel traffico non arriva da 100.x.x.x. Arriva dalla rete Docker sull'host, ad esempio 10.0.1.x sulla rete coolify.

La sequenza è quindi questa:

  1. UFW: 2222/tcp ALLOW from 100.64.0.0/10 solo.
  2. Il container prova a raggiungere l'host sulla porta 2222 (per eseguire comandi remoti e validare Docker).
  3. La sorgente del pacchetto è 10.0.1.x (o un altro range Docker). UFW non ha una regola di allow per quella sorgente.
  4. Risultato: connection timeout (pacchetto droppato), non "connection refused".

Perché 127.0.0.1 in Coolify fallisce: dentro al container, 127.0.0.1 è il container stesso, non la VPS. Lì non ascolta nessuno sulla 2222, quindi ottieni connection refused.

Perché 172.17.0.1 può fallire: quello è il gateway della rete bridge di default. Coolify spesso si attacca a una rete con nome (ad esempio coolify) con un gateway diverso (ad esempio 10.0.1.1). Il gateway che vedi da docker network inspect bridge può differire dal gateway che i container Coolify usano davvero.

Fix (sulla VPS, da una sessione SSH funzionante, ad esempio via Tailscale):

  1. Permetti alle sorgenti interne Docker di raggiungere SSH sull'host (stringi le subnet se preferisci):
sudo ufw allow from 10.0.0.0/8 to any port 2222 proto tcp comment 'Docker to host SSH'
sudo ufw allow from 172.16.0.0/12 to any port 2222 proto tcp comment 'Docker bridge ranges to host SSH'
sudo ufw reload

Usa la tua porta SSH reale al posto di 2222 se è diversa.

  1. Imposta Coolify → Servers → il tuo server → IP sul gateway della rete Docker coolify (l'host visto da quei container), non 127.0.0.1:
docker network inspect coolify --format '{{range .IPAM.Config}}Subnet: {{.Subnet}} Gateway: {{.Gateway}}{{"\n"}}{{end}}'

Pattern di esempio: gateway 10.0.1.1, subnet 10.0.1.0/24. Inserisci quel gateway in Coolify con User e Port che corrispondono a sshd sull'host.

  1. Salva in Coolify e Validate / Revalidate il server.

Riassunto: SSH solo-Tailscale su UFW è corretto per te. Coolify ha bisogno di un allow extra su UFW (e opzionalmente Hetzner) così che Docker → host:2222 sia permesso, più l'IP gateway della rete Docker in Coolify al posto di localhost.


Verifica finale

  1. Dalla sessione SSH Tailscale, esegui ufw status e conferma le regole.
  2. Chiudi la sessione SSH su IP pubblico.
  3. Dalla tua macchina locale, fai SSH via Tailscale: ssh [email protected]. Deve funzionare.
  4. Prova SSH via IP pubblico. Deve essere rifiutato.

La tua VPS adesso è raggiungibile solo via Tailscale (per te) e Cloudflare (per il traffico web). Il resto di internet non si può collegare.


Perché conta

Una VPS con SSH e porte web aperte è un bersaglio. I bot scansionano l'intero spazio IPv4. Provano password di default, exploit noti e brute force. Bloccare SSH a Tailscale rimuove quella superficie. Bloccare 80/443 a Cloudflare significa che solo Cloudflare può raggiungere il tuo origin. Cloudflare gestisce DDoS, bot e traffico malevolo prima che arrivi al server.

Il tuo server diventa una macchina privata con cui solo tu e Cloudflare potete parlare. È così che dovrebbe essere.


Integrazione con lo script di setup

Lo script di Server Setup può installare e collegare Tailscale automaticamente. Passa la tua auth key:

TAILSCALE_AUTH_KEY=tskey-auth-xxxxxxxxxxxx ./server-setup.sh

Lo script installa Tailscale e lancia tailscale up. Stampa il tuo IP Tailscale alla fine. Apri un nuovo terminale, fai SSH su quell'IP, poi esegui il lockdown del firewall:

scp -P 2222 scripts/firewall-lockdown.sh deploy@YOUR_TAILSCALE_IP:~/
ssh -p 2222 deploy@YOUR_TAILSCALE_IP
chmod +x ~/firewall-lockdown.sh
./firewall-lockdown.sh

Lo script firewall-lockdown.sh restringe UFW a Tailscale (SSH) e Cloudflare (80/443). Eseguilo solo da una sessione Tailscale. Imposta SSH_PORT=2222 se la tua porta SSH è diversa.

Per Hetzner Cloud Firewall: durante il setup iniziale potresti aver bisogno di SSH (22 o 2222) aperto da Any per poterti collegare. Dopo che Tailscale funziona, cambia la regola per permettere solo 100.64.0.0/10 (range Tailscale).