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:

  1. È una soluzione che richiede di iscriversi alla loro piattaforma per essere utilizzata;
  2. 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);
  3. 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:

  1. 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);
  2. Definizione di policy di traffico all’interno della singola rete (tecnicamente delle ACL nel formato: sorgente, destinazione, azione - accept o drop);
  3. 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);
  4. Rilascio di certificati SSL con Letsencrypt nella VPN;
  5. Supporto alle passkey;
  6. 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.