Perché una Virtual Private Cloud
All’inizio della mia esperienza come self-hoster, gestivo pochi servizi ad
uso prettamente personale e quindi ho preso la decisione di esporli
direttamente su internet, solitamente installandoli su una VPS (Virtual
Private Server) che noleggiavo su $meno_noto_provider_tedesco
oppure
esponendo le risorse direttamente da casa mia utilizzando il mio Raspberry Pi
e Nginx Proxy Manager.
La necessità che questi servizi si parlassero fra di loro per scambiarsi dati/informazioni e, nel farlo, non “esponessero” tali informazioni passandole “in chiaro” sull’Internet mi ha fatto percepire abbastanza prontamente l’esigenza di costruire quella che, in seguito, avrei scoperto si definisce una Virtual Private Cloud, ovvero una rete privata fra host in cloud e potenzialmente geograficamente distribuiti.
Ho già implementato questa VPC diversi anni fa e con soddisfazione utilizzando ZeroTier, che è una soluzione tecnicamente complessa ma molto valida e di semplice implementazione. È usata “in produzione” da diverse aziende, nonché integrata e supportata nativamente da alcuni produttori hardware (per esempio, Mikrotik permette di utilizzarla sulle loro macchine con architettura ARM).
Il loro modello di business è basato sul SaaS (Software as a Service), pertanto richiedono una subscription ai loro servizi cloud per la gestione della VPN, con diversi piani sulla base principalmente del numero di dispositivi da gestire o delle reti private da configurare. Offrono ovviamente anche un piano gratuito, che per l’uso privato o per un piccolo laboratorio è probabilmente più che sufficiente.
La configurazione di un client di una rete ZeroTier è imbarazzantemente semplice: si installa il client, disponibile per diverse piattaforme e device, si indica al client che si vuole raggiungere una specifica rete privata, indicata da un hash a 10 byte, e il gioco è fatto.
Perché ZeroTier mi sta stretta
ZeroTier resta un ottimo prodotto per realizzare delle VPN in maniera estremamente semplice e rapida, tuttavia ha alcuni svantaggi che non mi soddisfano completamente:
- È una soluzione che richiede di iscriversi alla loro piattaforma per essere utilizzata;
- Esiste la possibilità di self-hostare un Controller ZeroTier, tuttavia i client sono configurati per richiedere informazioni sulla rete privata a cui devono essere aggiunti in prima battuta ai controller di ZeroTier Inc (tornerò su questo discorso più sotto);
- L’implementazione del client ha una limitazione: il processo
zerotier-one
, che gestisce sull’host il traffico e la cifratura, è single-threaded: le performance di trasferimento di file nella rete privata sono quindi strettamente vincolate alla velocità di clock del singolo core della CPU della macchina su cui è installato il client (e quindi non può essere utilizzato efficientemente per grossi traffici con macchine a basso consumo energetico).
Utilizzavo già in precedenza un Controller privato di ZeroTier, implementato usando il client ZeroTier ma anche ztncui, che mi risulta essere l’unica implementazione libera del controller ZeroTier e con la quale si può effettivamente fare self-hosting. Tuttavia, quanto detto in precedenza rimane valido: in fase di discover della rete privata, data come input al client (nella terminologia di ZeroTier, network), l’hash a 10 byte viene richiesto prima ai controller del cloud di ZeroTier Inc., i quali rimandano sì al Controller implementato, ma che nel frattempo hanno ricevuto del traffico (e possono quindi controllarlo in qualche maniera).
Non ho mai avuto mezzo problema in tal senso, per carità, e sono assolutamente convinto della serietà di ZeroTier Inc. nel trattamento di eventuali informazioni; è sempre bene domandarsi, tuttavia, se si è disposti a cedere informazioni (e quali si sia disposti a cedere) per l’utilizzo di un servizio. Se è possibile, preferisco semplicemente non cederne.
L’altra soluzione SaaS: Tailscale
Esiste un’altra soluzione di VPN privata avanzata disponibilile in modalità SaaS: Tailscale. La soluzione è interessante perché offre un protocollo sottostante nativamente libero, testato e certamente performante: Wireguard. Questo risolverebbe il mio terzo problema in maniera molto brillante.
Fra le altre feature decisamente comode di Tailscale, rispetto a ZeroTier:
- Servizio DNS interno (MagicDNS) con cui risolvere gli hostname degli altri client della rete privata (anche se il nome della rete privata è generato automaticamente e casualmente o può essere cambiato solo con scelte proposte dalla piattaforma e non liberamente);
- Definizione di policy di traffico all’interno della singola rete
(tecnicamente delle ACL nel formato: sorgente, destinazione, azione -
accept
odrop
); - Uso di un Identity Provider (IdP) per l’autenticazione, quelli più noti commerciali oppure quelli che supportano lo standard OpenID Connect (quindi tutti quelli che si possono self-hostare, per esempio Keycloak oppure authentik);
- Rilascio di certificati SSL con Letsencrypt nella VPN;
- Supporto alle passkey;
- Gestione della device posture: è possibile individuare delle caratteristiche minime per i client che si devono collegare alla rete (per esempio, versione del client Tailscale).
Per quanto riguarda il punto 1, internamente alla mia VPC integravo già un servizio DNS distribuito fra vari host basato su dnsmasq e su Pi-hole a casa; ovviamente però è una soluzione manuale che deve essere poi manutenuta.
Ciò detto, la soluzione però ha lo stesso problema di ZeroTier in merito all’utilizzo di una piattaforma cloud terza; in questo caso, esiste Headscale che permette di avere un server di controllo per Tailscale come software libero (il controller nativo di Tailscale è proprietario, così come sono proprietari i client per sistemi operativi proprietari), con un set di feature che rincorre la sua controparte proprietaria. Non ho molto altro da aggiungere in merito, perché non ho provato Headscale (Tailscale sì e mi è anche capitato di consigliarlo, in alcuni casi in cui un setup più professionale e manuale non era perseguibile).
Una soluzione self-hosted: Netbird
Parlando di VPN con un mio collega di LUG, mi ha fatto scoprire (per la verità qualche mese fa) Netbird.
È una soluzione di Virtual Private Network basata sul più diffuso ed eccellente Wireguard che ricalca, molto da vicino, le funzionalità e l’essere multipiattaforma di Tailscale; il feature set non è completo, ma le funzionalità che sono attualmente integrate sono più che sufficienti.
Ciò detto, sto ancora testando la soluzione, anche se l’ho “affiancata” alla mia già presente VPC; il presente blogpost doveva servire, più che altro, come posto per appuntarmi alcune configurazioni specifiche per cui ho trovato poca documentazione o sparpagliata.
Reti zero trust: Cloudflare, Twingate e FerrumGate
Menzionerei queste tre soluzioni, per il motivo che implementano il paradigma Zero-Trust Network, ovvero che debba essere l’amministratore di rete che, tramite controlli di device posture e regole di policy basati su gruppi, autorizza l’accesso del singolo client al singolo servizio esposto in rete privata (e, quindi, i servizi non sono automaticamente esposti se presenti in VPN). Questi tre servizi sono: Cloudflare, Twingate e FerrumGate.
Il caso d’uso di una Zero Trust Network è tuttavia decisamente differente dalle necessità di integrazione e connettività di host geograficamente distribuiti, tipico di una VPC. Ovviamente dal punto di vista della sicurezza, il paradigma Zero Trust è un approccio vincente e evoluto.
Cominciamo con dire una caratteristica comune ai primi due servizi: sono soluzioni proprietarie.
Cloudflare nasce come provider di servizi DNS, ma che ha poi integrato una serie di tecnologie per offrire un servizio più efficiente e potente ai suoi clienti. Nella sua offerta sono presenti due tecnologie, Tunnel e Zero Trust per l’appunto, che permettono l’implementazione di una VPN con questo paradigma di sicurezza.
Il problema di Cloudflare risiede ancora nell’accettare l’affiliazione e il transito dei dati (che in questo caso è ancora più intenso: qualsiasi connessione è veicolata in un tunnel cifrato dall’infrastruttura di Cloudflare — per inciso, non possiamo sincerarci di escludere comportamenti tipici degli attacchi Man in the Middle, MITM, da parte di Cloudflare); per poter utilizzare tali servizi è inoltre necessario aver configurato e gestire attivamente un dominio DNS all’interno della piattaforma Cloudflare.
Twingate è un servizio di VPN Zero Trust completo, ma è completamente proprietario/SaaS. Sono previsti client per i principali sistemi operativi, ma siete completamente alla mercé di Twingate Inc..
Molto interessante, invece, è FerrumGate: è una VPN Zero Trust completamente open source e self-hostable. Nuovamente, il paradigma Zero Trust non si confà con le necessità di una VPC, però l’ho provato ed è efficace. I difetti più importanti che gli trovo sono una certa gioventù del progetto, la complessità delle componenti da configurare (ogni rete geografica separata ha bisogno di un suo “proxy” per esporre servizi) e la documentazione non è proprio completa.
Netbird: installazione di test
Per l’installazione di test, ho provveduto semplicemente a noleggiare una VPS con un suo indirizzo IP pubblico, su cui ho poi installato Docker; i servizi esposti non sono pochi e alcuni sono serviti su porte standard (80/tcp e 443/tcp) che quindi male si confanno a convivere con altri servizi.
In realtà la documentazione avanzata di installazione è completa e passo-passo e include una sezione per la configurazione dietro un reverse-proxy: penso proprio che il passaggio che farò, se effettivamente deciderò di mettere in produzione Netbird, sarà quello di provare a metterlo dietro Traefik.
L’installazione di base del sistema includerebbe un IdP, Zitadel, ma avevo già un mio IdP (per inciso, authentik) e quindi volevo integrarlo nella mia infrastruttura preesistente.
Netbird: gestione del servizio DNS interno
Netbird offre nativamente, come Tailscale, un servizio DNS per risolvere gli
hostname dei client che sono collegati alla rete; tuttavia, questa gestione
funziona correttamente e nativamente su GNU/Linux solo nei sistemi che
utilizzano systemd-resolved
per la gestione dei DNS. Inutile dire che, fatti
salvi i portatili su cui uso distribuzioni desktop-based, su nessuno dei
miei sitemi è normalmente installato e configurato systemd-resolved
(e anzi,
ho avuto spesso problemi quando ho scelto di usarlo).
Normalmente il servizio DNS è gestito dal servizio client netbird
, ma è noto
che abbia qualche problema d’integrazione sui sistemi che utilizzano
dnsmasq
: di nuovo, è il mio caso d’uso. Tuttavia, pur non essendo
pubblicizzatissimo nella documentazione, c’è un parametro che può essere
passato a Netbird per esporre il servizio DNS interno su una porta specifica
e, quindi, poterlo separare e integrare in dnsmasq.
È quindi possibile specificare un indirizzo IP su cui esporre il servizio DNS
interno (non solo per l’host collegato, ma anche per la sua eventuale rete),
utilizzando il parametro --dns-resolver-address
con un indirizzo IP e una
porta:
netbird down # non si può applicare 'live'
netbird up --dns-resolver-address 127.0.0.1:5053
127.0.0.1:5053
ovviamente imposta un servizio che è disponibile solo sulla
macchina locale; se si usa, per esempio, l’indirizzo IP che il client
otterrebbe nella rete Netbird, è possibile condividere quel resolver su più
reti.
A questo punto non resta che configurare quel resolver quantomeno per il dominio della rete di Netbird nella configurazione di dnsmasq, quindi riavviare il servizio:
server=/netbird.selfhosted/127.0.0.1#5053
Configurazione di Netbird client su OpenWrt
OpenWrt è un sistema operativo libero basato su GNU/Linux per un gran numero di dispositivi di rete (principalmente router casalinghi); in considerazione della possibilità, per casa mia, di inserire un firewall basato su OpenWrt, volevo testarne la funzionalità sull’ultima versione di questo sistema operativo, 23.05.5.
Nei repository di pacchetti di OpenWrt c’è un pacchetto netbird
(al momento
in cui scrivo in versione 0.24.3 — non esattamente aggiornatissimo). Tuttavia,
l’installazione di questo solo pacchetto non è sufficiente per far funzionare
netbird.
L’installazione completa (documentata in una issue su GitHub) e funzionante si compone questi passaggi:
opkg update
opkg install netbird luci-proto-wireguard kmod-wireguard wireguard-tools
A questo punto si consiglia un riavvio, quindi va configurato il client netbird con le istruzioni che si trova nella console di Management.
Accedendo poi a LuCI, recarsi in Network > Interfaces, quindi premere Add
new interface…; usare “Netbird” come nome, Unmanaged come protocollo,
indicare wt0
come Device. Salvare e applicare.
Recarsi in Network > Firewall, quindi Zones; quindi premere su Add e aggiungere la seguente zona:
- Name: Netbird
- Input: accept
- Output: accept
- Forward: accept
- Covered networks: impostare l’interfaccia Netbird.
- Allow forward to destination zones: “lan” sicuramente, se si vuole utilizzare il dispositivo come exit node includere anche “wan”
- Allow forward from source zones: “lan”
- Salvare la configurazione su Save
Dopo aver salvato ed applicato la configurazione, Netbird dovrebbe correttamente funzionare.