
Lorsque vous concevez une application sécurisée, vous lui interdisez souvent toute connexion sortante depuis son Virtual Private Cloud (VPC). Mais il faut parfois entrouvrir la porte, par exemple quand votre application doit appeler une API tierce.

Gateway to Domain, façon Lovecraft. Crédit : StableDiffusion
La méthode habituelle consiste à autoriser l'egress uniquement vers les adresses IP concernées, via le Firewall sur Google Cloud Platform ou via les Network ACLs sur AWS. Or les adresses IP peuvent évoluer dans le temps, alors que le Fully Qualified Domain Name (FQDN) — par exemple api.example.com — fournit un endpoint stable et publiquement connu. La plupart des applications sont d'ailleurs configurées pour cibler un FQDN plutôt qu'une adresse IP.

Dans cet article, je passe en revue les différentes manières d'autoriser l'egress uniquement vers un FQDN précis, avec les avantages et les inconvénients de chaque approche.
L'objectif : trouver des options peu coûteuses, faciles à maintenir, robustes et simples.
Nous étudierons aussi des options compatibles Kubernetes : si votre application tourne sur Kubernetes, vous voudrez peut-être autoriser l'egress depuis un namespace Kubernetes donné, et pas depuis les autres.
Un contrôle granulaire au niveau du domaine est également souhaitable, puisqu'une même adresse IP peut héberger plusieurs domaines. La plupart des solutions présentées ici n'en tiennent pas compte : si vous autorisez l'accès à un domaine pointant vers une adresse IP donnée, elles autoriseront l'egress vers tous les domaines hébergés derrière cette adresse. Ce n'est généralement pas un problème de sécurité, car les domaines partageant une même adresse IP sont en principe contrôlés par une seule entité. Mais le virtual hosting basé sur le nom rend ce scénario possible : nous présenterons donc quelques solutions qui le prennent en charge.
Voici les options examinées :
- Squid, comme exemple de proxy auto-géré
- AWS Network Gateway, avec deep packet inspection, qui permet un contrôle au niveau du domaine, même en virtual hosting.
- Une nouvelle fonctionnalité de Google Firewall, qui apporte un contrôle FQDN avec la simplicité d'un service serverless
- Le nouveau Google Secure Web Gateway, qui ajoute un contrôle granulaire jusqu'au niveau du domaine, voire de l'URL.
- Solutions compatibles Kubernetes : Cilium et Istio.
(Une remarque sur les couches OSI : les noms de domaine et le DNS relevant de la couche application du modèle réseau OSI, soit la couche 7, le contrôle FQDN Egress est parfois appelé contrôle Egress de couche 7_. À l'inverse, la couche 3 est celle où sont définies les adresses IP, gérées par les firewalls classiques ou les Network ACLs.)_
L'implémenter soi-même
Voyons d'abord comment l'implémenter par nous-mêmes. Non que je le recommande, mais cela permet de comprendre ce que ces solutions font sous le capot.
Même si l'application est configurée avec le FQDN de l'API tierce, votre solution doit bloquer les paquets au niveau de l'adresse IP, puisque c'est par là que transite tout le trafic réseau. Les noms de domaine ne sont pertinents qu'avant l'établissement de la connexion, lorsque le client résout l'adresse IP à partir du nom de domaine.
Notez aussi qu'un même FQDN peut correspondre à plusieurs adresses IP. Ce n'est pas un problème : une résolution DNS classique les renvoie toutes, et vous pouvez ainsi autoriser l'accès à une liste d'adresses IP.
Vous disposez d'un Firewall ou d'une Network ACL qui bloque tout le trafic, à l'exception des adresses IP concernées.
Vous écrivez et déployez une application qui interroge périodiquement le DNS pour récupérer l'adresse IP courante du FQDN de l'API, api.example.com. (Pour exécuter cela à moindre coût, GCP Cloud Functions ou AWS Lambda déclenchés périodiquement constituent un bon choix.) Dans les rares cas où l'adresse IP a changé, votre application met à jour le Firewall ou la Network ACL.
Reverse web proxies auto-gérés
Une solution classique au contrôle FQDN Egress est le reverse web proxy, dont Squid est la référence open source la plus connue. Vous utilisez le service de routage de votre cloud pour acheminer tout le trafic sortant vers une VM exécutant le proxy Squid ; celui-ci vérifie alors que l'adresse IP correspond bien au nom de domaine — tel que défini dans une whitelist ACL — et relaie le trafic en cas de correspondance.
Squid est disponible sur l'AWS Marketplace ; voir cette discussion d'architecture. Il est également disponible sur le GCP Marketplace ; voir cette configuration réseau. Voir aussi cette discussion sur le contrôle FQDN egress avec Squid et d'autres proxys, comme DiscrimiNAT et Aviatrix.
Les proxys de type Squid tournant sur une VM impliquent un coût de maintenance, ne serait-ce que pour mettre à jour les systèmes d'exploitation et gérer les crashs. Comme tout le flux de trafic réseau passe par une seule VM (à moins de mettre en place un déploiement load-balancé, ce qui ajoute du travail), la charge peut devenir lourde, ce qui fragilise la robustesse et peut imposer le coût d'une VM plus puissante tournant 24x7, même quand ce n'est pas indispensable.
AWS Network Firewall
AWS Network Firewall effectue de la deep packet inspection, ce qui lui confère une plus grande puissance de filtrage. À ce titre, il n'est pas strictement comparable à Google Firewall, qui se rapproche davantage des Network ACLs d'AWS.
AWS Network Firewall prend en charge le contrôle FQDN Egress via des stateful domain list rule groups. En s'appuyant sur le Server Name Indicator (SNI) transmis lors de la négociation TCP du trafic HTTPS, il sait distinguer les domaines dans des scénarios de virtual hosting.
Network Firewall peut être intégré à Route 53 DNS Firewall, qui bloque les tentatives de résolution DNS : ainsi, par exemple, une requête DNS pour api.example.com émise depuis une application située dans le VPC ne se résout pas en adresse IP. Mais le DNS Firewall n'empêche pas réellement l'accès à cette adresse IP : c'est Network Firewall qui s'en charge.
Network Firewall est un bon choix, mais il peut devenir coûteux : il est conçu pour des environnements d'entreprise multi-réseaux complexes. ( Voir mon article sur le DoiT Blog qui compare les cas d'usage des nombreux services de type Firewall sur AWS.)
Google Firewall et Web Gateway
Il est plus simple d'opter pour une solution entièrement managée par le fournisseur cloud que de gérer la VM soi-même. Et Google sort justement plusieurs solutions allant dans ce sens. J'y reviendrai en détail dans un prochain article ; voici déjà les points saillants.
Google Firewall propose une nouvelle fonctionnalité FQDN Objects, actuellement en Preview limitée. Elle interroge Cloud DNS toutes les 30 secondes pour récupérer l'adresse IP courante du service externe.
Autre service en Preview limitée, Secure Web Gateway permet également un contrôle au niveau du domaine. Pour cela, vous lui donnez accès à vos certificats SSL via le GCP Certificate Manager, afin qu'il puisse déchiffrer et chiffrer votre trafic HTTPS. Ce niveau d'accès lui confère la capacité de contrôler l'egress au niveau du domaine, même en virtual hosting. Et comme il voit la requête HTTP complète, il vous offre même un contrôle au niveau de l'URL.
Cilium
Les solutions ci-dessus opèrent au niveau du VPC. Mais si votre application tourne sur Kubernetes, vous voudrez peut-être que le contrôle d'egress s'appuie sur les concepts Kubernetes. Pour cela, vous pouvez introduire CiliumNetworkPolicy. Il s'agit d'une Custom Resource Definition (CRD) qui exécute la logique de résolution des noms de domaine en adresses IP, puis bloque ou autorise le trafic au niveau de la couche réseau Cilium basée sur eBPF. (Voir deux articles sur le DoiT blog.) La CRD est compatible Kubernetes : vous pouvez ainsi distinguer les pods par namespace — certains autorisés à accéder à l'API externe, d'autres non. Une autre CRD, CiliumClusterwideNetworkPolicy, fait la même chose, mais sa configuration s'applique cross-namespace, à l'ensemble du cluster.
Cette solution ajoute une certaine complexité à votre cluster, du fait de la couche réseau Cilium supplémentaire. Prochainement, comme l'indique la documentation Cilium, toutes les fonctionnalités seront fusionnées dans le format de ressource standard et cette CRD ne sera plus nécessaire. Aucune spécification standard n'est encore disponible, mais le Kubernetes Networking Special Interest Group y travaille actuellement.
Istio
La solution la plus riche en fonctionnalités est offerte par le service mesh Istio. Istio contrôle entièrement le trafic et permet de bloquer tout l'egress, sauf ce qui est défini dans un ServiceEntry. En spécifiant resolution: DNS, vous demandez à Istio de ne pas se fier à l'adresse IP à laquelle le client (un pod) se connecte, mais de résoudre périodiquement le nom de domaine via DNS. Le service Istio peut être exposé uniquement aux namespaces de votre choix. Istio offre le contrôle le plus poussé, mais ajoute plus de complexité que Cilium, avec toute la puissance et les fonctionnalités d'une couche service mesh.
Que faire ?
Vous disposez d'un large éventail d'options : le très éprouvé Squid (ou un autre reverse web proxy) ; les nouveaux services managés Google Firewall FQDN Objects et AWS Network Firewall ; le Secure Web Gateway agissant en proxy HTTP ; et, en complément, les solutions compatibles Kubernetes Cilium et Istio.
Si vous recherchez une solution stable et managée, je recommande le nouveau Google Firewall (une fois mature) et AWS Network Firewall (si la tarification entre dans votre budget). Si vous avez besoin d'un contrôle au niveau des namespaces Kubernetes, la solution la plus simple est une CRD Cilium ; et lorsque le standard Kubernetes-native sera publié, basculez vers celui-ci.