Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Consentire il traffico in uscita per dominio

By Joshua FoxAug 28, 20237 min read

Questa pagina è disponibile anche in English, Deutsch, Español, Français, 日本語 e Português.

Quando si sviluppa un'applicazione sicura, spesso le si nega il permesso di connettersi all'esterno della propria Virtual Private Cloud (VPC). A volte, però, occorre 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 consueto consiste nel consentire l'egress soltanto verso gli indirizzi IP rilevanti, configurati tramite il Firewall su 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 api.example.com, fornisce un endpoint stabile e pubblicamente noto. Per questo motivo la maggior parte delle applicazioni viene configurata per accedere a un FQDN anziché a un indirizzo IP.

In questo articolo passerò in rassegna i vari modi per consentire l'egress solo verso uno specifico FQDN, illustrando vantaggi e svantaggi di ogni approccio.

Cercheremo opzioni economiche, semplici da gestire, robuste e di facile utilizzo.

Valuteremo anche le soluzioni con il valore aggiunto della Kubernetes-awareness: se la sua applicazione gira su Kubernetes, ad esempio, potrebbe voler consentire l'egress da un determinato namespace Kubernetes e non da altri.

Potremmo inoltre voler controllare la granularità a livello di domini, dato che un singolo indirizzo IP può ospitare più domini, come accade con il virtual hosting basato sul nome. La maggior parte delle soluzioni qui presentate non tiene conto di questo aspetto: consentendo l'accesso a un dominio con un dato indirizzo IP, autorizzano l'egress verso tutti i domini che si trovano dietro quell'indirizzo. Presenteremo anche alcune soluzioni che gestiscono questo scenario.

Le opzioni che esaminerò sono:

  • Squid, come esempio di proxy auto-gestito
  • AWS Network Firewall, con deep packet inspection, che permette 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 del dominio e persino dell'URL.
  • Le soluzioni con Kubernetes-awareness: Cilium e Istio.

(Una nota sui livelli OSI: poiché i nomi di dominio e il DNS si trovano al "livello applicativo" del modello di rete OSI, il Layer 7, il controllo dell'egress FQDN viene talvolta chiamato "Layer 7 Egress Control". Il Layer 3, invece, è quello in cui vengono definiti gli indirizzi IP ed è il livello su cui agiscono i tipici firewall o le Network ACL.)

Implementare la soluzione in autonomia

Vediamo innanzitutto come potremmo implementare questa soluzione da soli. Non che lo consigli, ma può aiutare a capire cosa fanno queste soluzioni dietro le quinte.

Anche se l'applicazione è configurata con l'FQDN dell'API di terze parti, i nomi di dominio entrano in gioco solo prima che venga avviata la connessione, quando il client risale all'indirizzo IP a partire dal nome di dominio. Da quel momento in poi, il traffico di rete viaggia su indirizzi IP, ed è proprio lì che la sua soluzione deve intervenire.

Va notato inoltre che a un singolo FQDN possono corrispondere più indirizzi IP. Non è un problema, perché una normale ricerca DNS li restituirà tutti, e potrà quindi consentire l'accesso a un elenco di indirizzi IP.

Si dispone di un Firewall o di una Network ACL che blocca tutto il traffico tranne quello diretto agli indirizzi IP rilevanti.

Si scrive e si rilascia un'applicazione che interroga periodicamente il DNS per individuare l'indirizzo IP corrente dell'FQDN dell'API, api.example.com. (Una buona scelta per eseguire questa operazione a costi contenuti è 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 il controllo dell'egress FQDN è il reverse web proxy, di cui Squid rappresenta l'opzione open-source più nota. Si utilizza il servizio di routing del proprio cloud per indirizzare tutto il traffico in uscita verso una VM su cui gira il proxy Squid; quest'ultimo verifica che l'indirizzo IP corrisponda al nome di dominio — come definito in una whitelist ACL — e, in caso di corrispondenza, lo inoltra.

Squid è disponibile nell'AWS Marketplace; veda questa discussione architetturale. È disponibile anche nel GCP Marketplace; veda questa configurazione di rete. Veda inoltre questa discussione sul controllo dell'egress FQDN in Squid e in altri proxy come DiscrimiNAT e Aviatrix.

I proxy come Squid in esecuzione su una VM comportano un onere di manutenzione, dovuto ad esempio all'aggiornamento dei sistemi operativi delle VM e alla gestione dei crash. Poiché l'intero flusso di traffico di rete passa attraverso un'unica VM (a meno di non sostenere lo sforzo aggiuntivo di configurare un deployment con load balancing), il carico può rivelarsi elevato, mettendo a rischio la robustezza e costringendo eventualmente a sostenere il costo di una VM più grande, attiva 24 ore su 24, 7 giorni su 7, anche quando non serve a pieno regime.

AWS Network Firewall

AWS Network Firewall esegue deep packet inspection e ottiene così una capacità di filtraggio superiore. Questo significa che non è strettamente paragonabile a Google Firewall, che assomiglia di più alle Network ACL di AWS.

AWS Network Firewall supporta il controllo dell'egress FQDN tramite gli stateful domain list rule groups. Sfruttando il Server Name Indicator (SNI) inviato durante la negoziazione di una connessione TCP per il traffico HTTPS, è in grado di 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 modo che, ad esempio, una query DNS per api.example.com proveniente da un'applicazione all'interno della VPC non si risolva in un indirizzo IP. Il DNS Firewall, però, non impedisce di per sé l'accesso a quell'indirizzo IP: a questo ci pensa Network Firewall.

Network Firewall è una buona scelta, ma può rivelarsi costoso: è pensato per ambienti enterprise complessi e multi-rete. (Veda il mio articolo sul blog di DoiT che mette a confronto i casi d'uso dei numerosi servizi di tipo Firewall su AWS.)

Google Firewall e Web Gateway

È più comodo affidarsi a una soluzione interamente gestita dal cloud provider piuttosto che amministrare la VM in autonomia. Proprio in questa direzione Google sta lanciando alcune novità.

Google Firewall propone una nuova funzionalità FQDN Objects, attualmente in Preview limitata. Si appoggia a Cloud DNS ogni 30 secondi per recuperare l'indirizzo IP corrente del servizio esterno.

Un altro servizio in Preview limitata, Secure Web Gateway (rinominato Secure Web Proxy), consente anch'esso il controllo a livello di dominio. Per farlo, gli si concede l'accesso ai propri certificati SSL nel GCP Certificate Manager, in modo che possa decifrare e cifrare il traffico HTTPS. Questo accesso approfondito gli permette di controllare l'egress a livello di dominio, anche negli scenari di virtual hosting. E poiché vede l'intera richiesta HTTP, consente persino il controllo a livello di URL.

Cilium

Le soluzioni viste finora operano a livello di VPC. Ma se la sua applicazione gira su Kubernetes, è probabile che voglia un controllo dell'egress in linea con i concetti di Kubernetes. A questo scopo, può introdurre CiliumNetworkPolicy: una Custom Resource Definition (CRD) che gestisce la logica di risoluzione dei nomi di dominio in indirizzi IP, bloccando o consentendo poi il traffico sul layer di rete Cilium basato su eBPF. (Veda due post sul blog di DoiT.) La CRD è Kubernetes-aware e quindi consente di distinguere i pod per namespace: alcuni a cui è permesso l'accesso all'API esterna, altri no. 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 layer di rete Cilium aggiuntivo. Come indicato nella documentazione di Cilium, in un prossimo futuro "tutte le funzionalità saranno integrate 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 integralmente il traffico, permettendole di bloccare tutto l'egress, fatta eccezione per quanto definito in un ServiceEntry. Specificando resolution: DNS, si chiede a Istio di non basarsi sull'indirizzo IP a 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 di sua scelta. Istio offre il massimo livello di controllo, ma introduce più complessità rispetto a Cilium, con tutta la potenza e le funzionalità di un layer service mesh.

Cosa scegliere?

Ha a disposizione diverse 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, Cilium e Istio con Kubernetes-awareness.

Se desidera una soluzione stabile e gestita, il mio consiglio è di puntare sul nuovo Google Firewall (una volta maturo) e su AWS Network Firewall (se il pricing rientra nel suo budget). Se le serve un controllo a livello di namespace Kubernetes, la soluzione più semplice è una CRD di Cilium; quando uscirà lo standard Kubernetes-native, sarà preferibile adottarlo.

Addendum

Agosto 2023: il mio collega

ha pubblicato di recente articoli approfonditi su diversi di questi temi, che riflettono i nuovi rilasci Google di funzionalità che erano in alpha quando ho scritto questo articolo, con maggior dettaglio tecnico.