Wer eine sichere Anwendung baut, untersagt ihr in der Regel jede Verbindung nach außerhalb der Virtual Private Cloud (VPC). Manchmal muss man aber doch einen Spalt öffnen – etwa, wenn die Anwendung eine Drittanbieter-API ansprechen soll.

Gateway to Domain, im Lovecraft-Stil. Bildquelle: StableDiffusion
Üblicherweise lässt man Egress nur zu den relevanten IP-Adressen zu, konfiguriert über die Firewall in der Google Cloud Platform oder über Network ACLs in AWS. IP-Adressen können sich jedoch im Laufe der Zeit ändern, während der Fully Qualified Domain Name (FQDN), zum Beispiel api.example.com, einen stabilen, öffentlich bekannten Endpunkt liefert. Deshalb sind die meisten Anwendungen so konfiguriert, dass sie einen FQDN ansprechen statt einer IP-Adresse.

In diesem Artikel zeige ich verschiedene Wege, Egress nur zu einem bestimmten FQDN zuzulassen, und beleuchte Vor- und Nachteile jedes Ansatzes.
Gesucht sind Optionen, die kostengünstig, wartungsarm, robust und einfach sind.
Außerdem schauen wir uns Optionen mit dem zusätzlichen Plus der Kubernetes-Awareness an: Läuft Ihre Anwendung in Kubernetes, möchten Sie Egress womöglich nur aus einem bestimmten Kubernetes-Namespace zulassen, aus anderen dagegen nicht.
Wünschenswert ist auch eine feinere Steuerung auf Domain-Ebene, denn hinter einer einzelnen IP-Adresse können mehrere Domains stehen – wie beim name-based virtual hosting. Die meisten der hier vorgestellten Lösungen unterscheiden das nicht: Erlauben Sie den Zugriff auf eine Domain mit einer bestimmten IP-Adresse, geben sie Egress zu allen Domains hinter dieser Adresse frei. Wir stellen einige Lösungen vor, die diese Unterscheidung beherrschen.
Im Einzelnen geht es um folgende Optionen:
- Squid als Beispiel für einen selbst betriebenen Proxy
- AWS Network Firewall mit Deep Packet Inspection, die eine Steuerung bis auf Domain-Ebene erlaubt – auch bei Virtual Hosting.
- Ein neues Feature in der Google Firewall, das FQDN-Kontrolle mit dem Komfort eines serverlosen Dienstes verbindet
- Das neue Google Secure Web Gateway, das eine granulare Steuerung bis auf Domain- und sogar URL-Ebene ermöglicht.
- Kubernetes-aware Lösungen: Cilium und Istio.
(Eine Anmerkung zu den OSI-Schichten: Da Domainnamen und DNS auf der "Anwendungsschicht" des OSI-Netzwerkmodells – Layer 7 – angesiedelt sind, spricht man bei der FQDN-Egress-Kontrolle gelegentlich auch von "Layer-7-Egress-Kontrolle". IP-Adressen liegen dagegen auf Layer 3 und werden über klassische Firewalls oder Network ACLs gesteuert.)
Selbst umsetzen
Überlegen wir zunächst, wie wir das selbst bauen könnten. Nicht, dass ich das empfehlen würde – aber es macht greifbar, was die folgenden Lösungen unter der Haube tun.
Auch wenn die Anwendung mit dem FQDN der Drittanbieter-API konfiguriert ist, spielen Domainnamen nur vor dem Verbindungsaufbau eine Rolle: dann nämlich, wenn der Client die zum Domainnamen gehörende IP-Adresse auflöst. Ab diesem Punkt läuft der Netzwerkverkehr ausschließlich über IP-Adressen – und genau die muss Ihre Lösung blockieren.
Bedenken Sie außerdem, dass ein einzelner FQDN auf mehrere IP-Adressen verweisen kann. Das ist kein Problem, da eine normale DNS-Abfrage alle zurückliefert; Sie können also den Zugriff auf eine Liste von IP-Adressen freigeben.
Sie haben eine Firewall oder Network ACL, die jeglichen Traffic außer zu den relevanten IP-Adressen blockiert.
Sie schreiben und deployen eine Anwendung, die regelmäßig per DNS die aktuelle IP-Adresse für den FQDN der API, api.example.com, ermittelt. (Eine kostengünstige Variante dafür sind GCP Cloud Functions oder AWS Lambda mit periodischem Trigger.) In den seltenen Fällen, in denen sich die IP-Adresse geändert hat, aktualisiert Ihre Anwendung anschließend die Firewall oder Network ACL.
Selbst betriebene Reverse-Web-Proxies
Ein "klassischer" Ansatz für die FQDN-Egress-Kontrolle ist ein Reverse-Web-Proxy, wobei Squid die bekannteste Open-Source-Lösung ist. Sie nutzen den Routing-Dienst Ihrer Cloud, um den gesamten ausgehenden Traffic über eine VM mit Squid-Proxy zu leiten. Der Proxy prüft, ob die IP-Adresse zum Domainnamen passt – wie in einer ACL-Whitelist definiert – und reicht den Traffic bei einem Treffer weiter.
Squid ist im AWS Marketplace verfügbar; siehe diese Architekturdiskussion. Auch im GCP Marketplace ist Squid zu finden; siehe dieses Networking-Setup. Lesenswert ist auch diese Diskussion zur FQDN-Egress-Kontrolle in Squid und anderen Proxies wie DiscrimiNAT und Aviatrix.
Proxies wie Squid auf einer VM bringen einen gewissen Wartungsaufwand mit sich – etwa beim Upgrade der VM-Betriebssysteme und beim Umgang mit Abstürzen. Da der gesamte Netzwerkverkehr durch eine einzige VM läuft (es sei denn, Sie nehmen den Mehraufwand für ein lastverteiltes Deployment in Kauf), kann die Last hoch werden. Das gefährdet die Robustheit und kann eine größere VM erfordern, die rund um die Uhr läuft – auch wenn sie nicht voll ausgelastet ist.
AWS Network Firewall
Die AWS Network Firewall führt Deep Packet Inspection durch und gewinnt dadurch deutlich mehr Filterkraft. Sie ist deshalb nicht direkt mit der Google Firewall vergleichbar, die eher den AWS Network ACLs ähnelt.
AWS Network Firewall unterstützt FQDN-Egress-Kontrolle über stateful Domain List Rule Groups. Anhand des Server Name Indicator (SNI), der beim Aushandeln einer TCP-Verbindung für HTTPS-Traffic übermittelt wird, kann sie Domains auch in Virtual-Hosting-Szenarien auseinanderhalten.
Die Network Firewall lässt sich mit der Route 53 DNS Firewall koppeln, die DNS-Auflösungsversuche blockiert – sodass etwa eine DNS-Abfrage nach api.example.com aus einer Anwendung innerhalb der VPC erst gar keine IP-Adresse zurückliefert. Den Zugriff auf die IP-Adresse selbst verhindert die DNS Firewall allerdings nicht – das übernimmt die Network Firewall.
Die Network Firewall ist eine gute Wahl, kann aber teuer werden: Sie ist für komplexe, mehrfach vernetzte Enterprise-Umgebungen ausgelegt. (Siehe meinen Artikel im DoiT Blog, in dem ich die Anwendungsfälle der vielen Firewall-ähnlichen Dienste in AWS gegenüberstelle.)
Google Firewall und Web Gateway
Eine Lösung, die der Cloud-Anbieter vollständig managt, ist deutlich bequemer, als selbst eine VM zu betreuen. Und Google bringt aktuell genau dafür einige Angebote auf den Markt.
Die Google Firewall hat ein neues FQDN-Objects-Feature, das sich derzeit in einer eingeschränkten Preview befindet. Es nutzt Cloud DNS, um alle 30 Sekunden die aktuelle IP-Adresse des externen Dienstes abzufragen.
Ein weiterer Dienst in eingeschränkter Preview, das Secure Web Gateway (umbenannt in Secure Web Proxy), ermöglicht ebenfalls eine Steuerung auf Domain-Ebene. Dazu erhält es Zugriff auf Ihre SSL-Zertifikate im GCP Certificate Manager und kann so Ihren HTTPS-Traffic ent- und verschlüsseln. Dieser tiefe Zugriff erlaubt es, Egress auf Domain-Ebene zu kontrollieren – auch in Virtual-Hosting-Szenarien. Da das Gateway den vollständigen HTTP-Request sieht, ist sogar eine Steuerung auf URL-Ebene möglich.
Cilium
Die bisher genannten Lösungen arbeiten auf VPC-Ebene. Läuft Ihre Anwendung jedoch auf Kubernetes, möchten Sie die Egress-Kontrolle vielleicht eng mit Kubernetes-Konzepten verzahnen. Dafür können Sie CiliumNetworkPolicy einsetzen. Das ist eine Custom Resource Definition (CRD), die Domainnamen in IP-Adressen auflöst und den Traffic anschließend auf der eBPF-basierten Cilium-Netzwerkschicht blockiert oder zulässt. (Siehe zwei Beiträge im DoiT Blog.) Die CRD ist Kubernetes-aware, sodass Sie Pods nach Namespace unterscheiden können: Manche dürfen auf die externe API zugreifen, andere nicht. Eine weitere CRD, CiliumClusterwideNetworkPolicy, leistet dasselbe, ihre Konfiguration gilt jedoch namespace-übergreifend für den gesamten Cluster.
Diese Lösung erhöht die Komplexität Ihres Clusters durch die zusätzlich benötigte Cilium-Netzwerkschicht. Wie in der Cilium-Dokumentation angekündigt, soll "die gesamte Funktionalität demnächst in das Standard-Ressourcenformat überführt werden, sodass diese CRD nicht mehr nötig ist." Eine standardisierte Spezifikation gibt es zwar noch nicht, doch die Kubernetes Networking Special Interest Group arbeitet bereits daran.
Istio
Die funktionsreichste Lösung bietet das Istio Service Mesh. Istio kontrolliert den Traffic vollständig und erlaubt es Ihnen, jeglichen Egress zu blockieren – außer dort, wo dies in einer ServiceEntry definiert ist. Mit der Angabe resolution: DNS weisen Sie Istio an, sich nicht auf die IP-Adresse zu verlassen, mit der sich der Client (ein Pod) verbindet, sondern den Domainnamen periodisch per DNS aufzulösen. Den Istio-Dienst können Sie gezielt nur den Namespaces zugänglich machen, die Sie auswählen. Istio bietet die größte Kontrolle, bringt aber mehr Komplexität mit sich als Cilium – mit dem vollen Funktionsumfang einer Service-Mesh-Schicht.
Was tun?
Sie haben eine ganze Bandbreite an Optionen: das bewährte Squid (oder einen anderen Reverse-Web-Proxy), die neuen Managed Services Google Firewall FQDN Objects und AWS Network Firewall, das HTTP-proxyende Secure Web Gateway sowie zusätzlich die Kubernetes-aware Lösungen Cilium und Istio.
Wenn Sie eine stabile, verwaltete Lösung suchen, empfehle ich die neue Google Firewall (sobald sie ausgereift ist) und die AWS Network Firewall (sofern das Pricing in Ihr Budget passt). Brauchen Sie Steuerung auf Ebene von Kubernetes-Namespaces, ist eine Cilium-CRD die einfachste Lösung; sobald der Kubernetes-native Standard verfügbar ist, sollten Sie auf diesen wechseln.
Nachtrag
August 2023: Mein Kollege
hat kürzlich ausführliche Artikel zu mehreren dieser Themen veröffentlicht. Sie spiegeln neue Google-Releases wider, die zum Zeitpunkt meines Artikels noch im Alpha-Stadium waren, und gehen technisch stärker in die Tiefe.