
Quando si sviluppa un'applicazione sicura, spesso le si impedisce di uscire dalla propria Virtual Private Cloud (VPC). A volte, però, è necessario aprire un varco: ad esempio, quando l'applicazione deve raggiungere un'API di terze parti.

Gateway to Domain, in stile Lovecraft. Credit: StableDiffusion
L'approccio classico consiste nel consentire l'egress solo verso gli indirizzi IP necessari, configurandoli tramite il Firewall di Google Cloud Platform o tramite le Network ACL su AWS. Gli indirizzi IP, però, possono cambiare nel tempo, mentre il Fully Qualified Domain Name (FQDN), come ad esempio api.example.com, offre un endpoint pubblico stabile e noto. La maggior parte delle applicazioni è infatti configurata per raggiungere un FQDN anziché un indirizzo IP.

In questo articolo passerò in rassegna i metodi per consentire l'egress solo verso uno specifico FQDN, mettendo in luce vantaggi e svantaggi di ciascun approccio.
Cercheremo soluzioni economiche, facili da mantenere, robuste e lineari.
Valuteremo inoltre opzioni con il valore aggiunto della Kubernetes-awareness: se ad esempio l'applicazione gira su Kubernetes, potresti voler consentire l'egress da un determinato namespace Kubernetes e non da altri.
Potremmo anche volere un controllo granulare a livello di dominio, dato che un singolo indirizzo IP può ospitare più domini. La maggior parte delle soluzioni qui presentate non lo prevede: se autorizzi l'accesso a un dominio tramite un determinato indirizzo IP, l'egress sarà consentito verso tutti i domini ospitati su quell'indirizzo. Spesso non si tratta di un problema di sicurezza, perché di norma tutti i domini su un singolo indirizzo IP fanno capo a un'unica entità. Tuttavia, il virtual hosting basato sul nome rende possibile questo scenario, e quindi presenteremo anche alcune soluzioni che lo supportano.
Le opzioni che esaminerò sono:
- Squid, come esempio di proxy auto-gestito
- AWS Network Gateway, con deep packet inspection, che consente il controllo a livello di dominio anche in presenza di virtual hosting.
- Una nuova funzionalità di Google Firewall, che offre il controllo FQDN con la comodità di un servizio serverless
- Il nuovo Google Secure Web Gateway, che aggiunge un controllo granulare fino al livello di dominio e persino di URL.
- Soluzioni Kubernetes-aware: Cilium e Istio.
(Una nota sui livelli OSI: poiché i nomi di dominio e il DNS si collocano al "livello applicativo" del modello di rete OSI, ovvero il Layer 7, l'FQDN Egress Control viene talvolta chiamato "Layer 7 Egress Control". Il Layer 3, invece, è quello in cui sono definiti gli indirizzi IP ed è il livello su cui agiscono i firewall tradizionali o le Network ACL.)
Implementarlo in autonomia
Vediamo innanzitutto come potremmo realizzare tutto questo in autonomia. Non è la strada che consiglio, ma può aiutare a capire cosa fanno queste soluzioni "sotto il cofano".
Anche se l'applicazione è configurata con il FQDN dell'API di terze parti, la soluzione deve bloccare i pacchetti a livello di indirizzo IP, perché tutto il traffico di rete usa proprio quelli. I nomi di dominio entrano in gioco solo prima del tentativo di connessione, quando il client risale all'indirizzo IP a partire dal nome di dominio.
Va anche notato che a un singolo FQDN possono corrispondere più indirizzi IP. Non è un problema, perché una normale risoluzione DNS li restituisce tutti, ed è quindi possibile autorizzare l'accesso a un elenco di indirizzi IP.
Hai a disposizione un Firewall o una Network ACL che blocca tutto il traffico tranne quello verso gli indirizzi IP autorizzati.
Scrivi e distribuisci un'applicazione che interroga periodicamente il DNS per ricavare l'indirizzo IP corrente del FQDN dell'API, api.example.com. (Una buona scelta a basso costo per eseguirla è GCP Cloud Functions o AWS Lambda con un trigger periodico.) Nei rari casi in cui l'indirizzo IP sia cambiato, l'applicazione aggiorna il Firewall o la Network ACL.
Reverse web proxy auto-gestiti
Una soluzione "classica" per l'FQDN Egress Control è il reverse web proxy, di cui Squid rappresenta l'opzione open source più nota. Si utilizza il servizio di routing del proprio cloud per convogliare tutto il traffico in uscita attraverso una VM che esegue il proxy Squid; quest'ultimo verifica la corrispondenza tra indirizzo IP e nome di dominio — definita in una whitelist ACL — e, in caso di match, lo inoltra.
Squid è disponibile su AWS Marketplace; vedi questa analisi dell'architettura. È disponibile anche su GCP Marketplace; vedi questa configurazione di rete. Vedi anche questo approfondimento sull'FQDN egress control in Squid e in altri proxy come DiscrimiNAT e Aviatrix.
I proxy come Squid eseguiti su una VM comportano un costo di gestione, ad esempio per gli aggiornamenti dei sistemi operativi e la gestione dei crash. Poiché tutto il traffico di rete passa attraverso un'unica VM (a meno di non predisporre, con ulteriore impegno, un deployment con bilanciamento del carico), il carico può diventare elevato, mettendo a rischio la robustezza e costringendo a sostenere il costo di una VM più grande attiva 24x7, anche quando non è pienamente sfruttata.
AWS Network Firewall
AWS Network Firewall esegue deep packet inspection, ottenendo così una capacità di filtraggio superiore. Per questo non è del tutto paragonabile a Google Firewall, che si avvicina di più alle Network ACL di AWS.
AWS Network Firewall supporta l'FQDN Egress Control tramite stateful domain list rule groups. Sfruttando il Server Name Indicator (SNI) inviato durante la negoziazione di una connessione TCP per il traffico HTTPS, riesce a distinguere tra domini negli scenari di virtual hosting.
Network Firewall può essere integrato con Route 53 DNS Firewall, che blocca i tentativi di risoluzione DNS: in questo modo, ad esempio, una query DNS per api.example.com proveniente da un'applicazione all'interno della VPC non viene risolta in un indirizzo IP. Da solo, però, il DNS Firewall non impedisce l'accesso a quell'indirizzo IP: a farlo è Network Firewall.
Network Firewall è una buona scelta, ma può rivelarsi costoso: è pensato per ambienti enterprise complessi e multi-rete. ( Vedi il mio articolo sul DoiT Blog in cui confronto i casi d'uso dei numerosi servizi simili a un Firewall su AWS.)
Google Firewall e Web Gateway
Affidarsi a una soluzione completamente gestita dal cloud provider è più semplice che gestire la VM in autonomia. E Google sta proprio ora rilasciando alcune soluzioni in questa direzione. In un prossimo articolo entrerò nel dettaglio sul loro utilizzo, ma intanto ecco i punti salienti.
Google Firewall offre una nuova funzionalità FQDN Objects, attualmente in Preview limitata. Utilizza Cloud DNS ogni 30 secondi per recuperare l'indirizzo IP corrente del servizio esterno.
Anche un altro servizio in Preview limitata, Secure Web Gateway, consente il controllo a livello di dominio. Per farlo, gli si concede l'accesso ai certificati SSL custoditi in GCP Certificate Manager, così che possa decifrare e cifrare il traffico HTTPS. Questo accesso profondo gli permette di controllare l'egress a livello di dominio, anche negli scenari di virtual hosting. E poiché vede l'intera richiesta HTTP, consente perfino il controllo a livello di URL.
Cilium
Le soluzioni precedenti operano a livello di VPC. Se però l'applicazione gira su Kubernetes, è probabile che si voglia un controllo dell'egress integrato con i concetti di Kubernetes. A questo scopo puoi adottare CiliumNetworkPolicy. Si tratta di una Custom Resource Definition (CRD) che gestisce la logica di risoluzione dei nomi di dominio in indirizzi IP e poi blocca o consente il traffico sul livello di rete Cilium basato su eBPF. (Vedi due articoli sul DoiT blog.) La CRD è Kubernetes-aware: puoi quindi distinguere i pod per namespace, autorizzando alcuni all'accesso all'API esterna ed escludendone altri. Un'altra CRD, CiliumClusterwideNetworkPolicy, fa lo stesso, ma la sua configurazione si applica trasversalmente a tutti i namespace, all'intero cluster.
Questa soluzione introduce una certa complessità nel cluster, dovuta alla necessità del livello di rete Cilium aggiuntivo. In un futuro prossimo, come indicato nella documentazione di Cilium, "tutta la funzionalità verrà integrata nel formato standard delle risorse e questa CRD non sarà più necessaria". Una specifica standard non è ancora disponibile, ma il Kubernetes Networking Special Interest Group ci sta lavorando.
Istio
La soluzione più ricca di funzionalità è offerta dalla service mesh Istio. Istio controlla il traffico in modo completo, permettendo di bloccare tutto l'egress, salvo quanto definito in una ServiceEntry. Specificando resolution: DNS, chiedi a Istio di non affidarsi all'indirizzo IP verso cui il client (un pod) si sta connettendo, ma di risolvere periodicamente il nome di dominio tramite DNS. Il servizio Istio può essere esposto solo ai namespace che scegli. Istio offre il massimo livello di controllo, ma introduce più complessità rispetto a Cilium, con tutta la potenza e le funzionalità di un livello di service mesh.
Cosa fare?
Hai a disposizione un ventaglio di opzioni: il collaudato Squid (o un altro reverse web proxy); i nuovi servizi gestiti, Google Firewall FQDN Objects e AWS Network Firewall; il Secure Web Gateway con proxy HTTP; e, in aggiunta, le soluzioni Kubernetes-aware Cilium e Istio.
Se cerchi una soluzione stabile e gestita, il mio consiglio è di puntare sul nuovo Google Firewall (una volta maturo) e su AWS Network Firewall (se il prezzo rientra nel tuo budget). Se ti serve il controllo a livello di namespace Kubernetes, la soluzione più semplice è una CRD Cilium; quando uscirà lo standard Kubernetes-native, passa a quello.