Cos’è una VPN
La tecnologia VPN negli ultimi anni sta diventando sempre più pervasiva e sebbene a volte venga spacciata come la soluzione a tutti i problemi, essa presenta delle caratteristiche che possono fare gola a molte persone.
L’utente novizio potrebbe sfruttare una rete VPN con server in un altro paese per collegarsi al proprio servizio di streaming preferito e accedere a contenuti bloccati o non disponibili.
L’utente esperto sfrutterebbe la VPN nella sua vera natura di Virtual Private Network al fine di avere un accesso autenticato e confidenziale alla propria rete aziendale o casalinga.
Dato che in questo blog (nonchè articolo per il buon Morro) siamo generalmente degli smanettoni abbastanza esperti, quello che vogliamo fare oggi è setuppare una VPN nel modo più semplice possibile riuscendo magari ad ottenere qualche funzionalità extra.
Wireguard
Quando si approccia a setuppare una rete VPN generalmente si predilige un protocollo tra: OpenVPN, Wireguard e Ipsec. La differenza fra questi sta nelle funzioni avanzate fornite all’utente. OpenVPN per esempio supporta ACL avanzate, autenticazione multi-fattore ma risulta allo stesso tempo più lenta e pesante di Wireguard che è nata con lo scopo di essere veloce ed efficente.
Wireguard è inoltre una soluzione molto più moderna e leggera e viene spesso utilizzata come backbone in altre soluzioni come Tailscale.
Arhitettura Hub and Spoke con Wireguard
Wireguard crea dei tunnel encriptati leggerissimi ma la maggior parte delle volte questi tunnel sono strutturati secondo una architettura Hub and Spoke dove ogni client si connette a un “coordinatore” centrale 1. Questa architettura è generalmente preferita perché richiede la configurazione e l’esposizione di un solo hub. Come vediamo nell’immagine, in una rete con 10 nodi vengono generati al massimo 10 tunnel.
Problematiche
Hub and Spoke funziona bene ma ha i suoi svantaggi:
- le grosse company non hanno solitamente un singolo punto da designare come VPN hub
- aziende multinazionali o dislocate in varie regioni di solito hanno un singolo accentratore VPN e poi impostano vari tunnel IPsec verso le varie sedi
IMPORTANTQuesto porta a svantaggi in termini di latenza e affidabilità dato che gli utenti remoti che vogliono collegarsi a un datacenter possono trovarsi lontano dall’accentratore VPN e lo stesso datacenter finale potrebbe trovarsi a sua volta molto lontano da quest’ultimo.
Mesh Network
Come abbiamo detto, Wiregaurd crea tunnel crittografati estremamente leggeri; non sarebbe bello se fosse possibile collegare i singoli nodi in modo diretto uno all’altro creando una mesh network?!
Con Wireguard è possibile ma potrebbe essere complesso:
- Una rete con 10 nodi richiede 90 configurazioni di tunnel WireGuard.
- Ogni nodo deve conoscere la propria chiave + 9 altre, aggiornandole ad ogni cambio.
- I nodi devono trovarsi e riconnettersi, ma gli IP sono spesso dinamici.
- Firewall e NAT complicano le connessioni in luoghi pubblici (caffè, hotel, aeroporti).
- Senza un hub centrale, audit e blocco del traffico tra nodi diventano complessi.
Tailscale
Tailscale risolve tutti questi problemi e lo fa in modo automatico!
Esso é di fatto un coordinatore leggero che si interpone fra i vari nodi e che si occupa di fare tutto il lavoro sporco al fine di configurare correttamente tutti i tunnel VPN.
Tailscale è molto più avanzato di così: include infatti varie strategie avanzate di Net Traversal 2 che permettono ai singoli dispositivi di superare firewall e creare connessioni.
WARNINGCome evidenziato in questo post su Reddit 3 se usi Tailscale, stai esternalizzando una parte della tua rete a un’azienda finanziata da venture capital e sarai dipendente da eventuali modifiche ai loro Termini di Servizio.
Esiste una versione di Tailscale completamente open e self hostable chiamata Headscale 4.
Headscale
Headscale mira a implementare un’alternativa self-hosted e open-source al server di controllo di Tailscale. Sul sito ufficiale di Headscale viene mostrato passo passo come installare l’intero sistema.
Prerequisiti
- server con IPv4 pubblico
- Dominio con certificato https
- utente dedicato
headscale
- Headscale è disponibile via HTTPS su porta 443 di default
Setup dominio con certificato
Per semplicità usiamo duckdns.
- Login e ci annotiamo il token e la mail
- Creiamo un mapping
hs-devstone
all’ip privato della macchina su cui hostiamo Headscale - Nel prossimo punto configureremo un reverse proxy
Caddy
che richiederà ogni volta un certificato aggiornato per il dominiohs-devstone
Setup reverse proxy Caddy
Usiamo Caddy come reverse proxy dato che è in grado di rinnovare certificati autonomamente utilizzando DNS challenge e inoltre è di facile configuraizione.
NOTECaddy non supporta nativamente duckdns quindi dobbiamo buildare un’immagine Caddy al volo.
- Creiamo una cartella
dockerfile-caddy
che contiene ilDockerfile
per la creazione dell’immagine di Caddy
FROM caddy:builder AS builder
RUN xcaddy build --with github.com/caddy-dns/duckdns
FROM caddy:2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
- Creiamo un
Caddyfile
per impostare le regole di reverse proxy.
{$DOMAIN}:443 {
log {
level INFO
output file {$LOG_FILE} {
roll_size 10MB
roll_keep 10
}
}
# Use the ACME DNS-01 challenge to get a cert for the configured domain.
tls {
dns duckdns {$DUCKDNS_TOKEN}
}
# This setting may have compatibility issues with some browsers
# (e.g., attachment downloading on Firefox). Try disabling this
# if you encounter issues.
encode gzip
# Proxy everything else to Headscale
reverse_proxy http:/headscale:8080
}
$DOMAIN
: è il dominio che abbiamo in duckdns e che imposteremo nel docker compose$LOG_FILE
: sarà il nome del file di log$DUCKDNS_TOKEN
: sarà il token Duckdns
Creazione container Docker
- Creiamo la cartella che conterrà la configurazione Headscale
mkdir -p ./headscale/config
cd ./headscale/config
- Scarichiamo il template di configurazione da qui e lo salviamo in
./headscale/config/config.yaml
. Cambiamo i valori come segue:
server_url: https://hs-devstone.duckdns.org
# Address to listen to / bind to on the server
#
# For production:
# listen_addr: 0.0.0.0:8080
listen_addr: 0.0.0.0:8080
# Address to listen to /metrics, you may want
# to keep this endpoint private to your internal
# network
#
metrics_listen_addr: 0.0.0.0:9090
# Address to listen for gRPC.
# gRPC is used for controlling a headscale server
# remotely with the CLI
# Note: Remote access _only_ works if you have
- Creiamo un
docker-compose.yaml
in./headscale
. Servizi:
- headscale: esposto su porta
8080
e8090
su containerheadscale
services:
headscale:
image: headscale/headscale
restart: unless-stopped
container_name: headscale
volumes:
# Please change <CONFIG_PATH> to the fullpath of the config folder just created
- ./config:/etc/headscale
command: serve
caddy:
build: ./dockerfile-caddy
container_name: caddy
pull_policy: build
restart: always
ports:
- 443:443
volumes:
# - ./caddy:/usr/bin/caddy # Your custom build of Caddy.
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-config:/config
- ./caddy-data:/data
environment:
- DOMAIN=https://hs-devstone.duckdns.org # Your domain.
- EMAIL=luca201194@gmail.com # The email address to use for ACME registration.
- DUCKDNS_TOKEN=aaa33e43-1333-4e92-93ad-994737b01dee # Your Duck DNS token.
- LOG_FILE=/data/access.log
- Creazione e run del container
docker compose up -d --build # crea container e run in background
docker logs --follow headscale # seguiamo i log
docker compose ps # vediamo se è partito
Esempio di log
❯ docker logs --follow headscale
headscale | 2025-03-07T13:55:13Z INF No private key file at path, creating... path=/var/lib/headscale/noise_private.key
headscale | 2025-03-07T13:55:13Z INF Opening database database=sqlite3 path=/var/lib/headscale/db.sqlite
headscale | 2025-03-07T13:55:13Z INF home/runner/work/headscale/headscale/hscontrol/app.go:570 > Clients with a lower minimum version will be rejected minimum_version=v1.62.0
headscale | 2025-03-07T13:55:13Z WRN Listening without TLS but ServerURL does not start with http://
headscale | 2025-03-07T13:55:13Z INF listening and serving HTTP on: 0.0.0.0:8080
headscale | 2025-03-07T13:55:13Z INF listening and serving debug and metrics on: 0.0.0.0:9090
Verifica che tutto funzioni andando su https://hs-devstone.duckdns.org/windows
e vediamo se il certificato è autentico 5. Creazione utente
docker exec -it headscale headscale users create myfirstuser
Registrazione clients
Android
Per aggiungere un server esterno basta andare in settings/Accounts/
e cliccare sui 3 puntini
Aggiungiamo uno o più nodi a headscale:
docker exec -it headscale headscale nodes register --user myfirstuser --key TNXkxpAYUeDHunCIz7aigkDh
> Node localhost registered
Mac Os
Funziona allo stesso modo di Android, viene generato un link di associazione
Test finale
Headscale in combinazione con i client Tailscale permette di creare una Rete VPN Mesh e lo fa in modo estremamente semplice.
Questo ha effetti positivi nelle performance dato che possiamo instaurare connessioni punto-punto senza dover passare per un accentratore.
Come vediamo in Local Send abbiamo 2 reti a cui è connesso il dispositivo.