Construire un Secure Hub dans Azure avec Virtual WAN

Après un précédent article sur la découverte d’Azure Virtual WAN, nous allons à présent nous intéresser aux concepts de Secure Hub. Nous adopterons dans cette publication une approche pragmatique comme la dernière fois, afin de construire de manière itérative un environnement qui nous servira à illustrer les concepts abordés.
Au programme :
- Les Concepts :
- Passer d’un Virtual Hub à un Secure Hub
- Pourquoi un Secure Hub ? Cas d’usage d’un firewall centralisé dans le Cloud
- Un aperçu des options disponibles
- Construire un Secure Hub en partant de zéro :
- Construction d’un Virtual Hub
- Ajouter un Firewall pour passer à un Secure Hub
- Configurer le routage et les règles de Firewall
- Considérations supplémentaires
Passer d’un Virtual Hub à un Secure Hub
Si vous avez déjà lu la documentation Azure sur le Virtual WAN, ou notre dernier article sur le sujet, vous savez déjà que dans une topologie réseau s’appuyant sur Virtual WAN, nous déployons à l’intérieur de ce dernier un ou plusieurs Virtual Hubs.
Vous savez également que le Virtual Hub est une bonne solution pour simplifier le trafic Est-Ouest entre les différents spokes, grâce aux routeurs managés qui s’occupent de la propagation des routes dans le Virtual Hub. Plus besoin de User Defined Route dans ces mêmes spokes.
Toutefois, dans ce scénario simple et malgré tout efficace, nous manquons d’options pour filtrer le trafic entre ces spokes, ou en provenance de ces spokes vers des destinations hors Azure.
Nous pouvons, dans les faits, utiliser des Network Security Groups, mais nous restons soumis à leurs limitations :
- Des règles qui prennent en compte uniquement la couche 4 ;
- L’impossibilité d’utiliser les Applications Security Groups pour du trafic externe au Virtual Network local.

Une réponse proposée à travers la topologie Virtual WAN est le modèle Secure Hub.
Dans ce scénario, un appliance réseau est déployé dans le Virtual Hub et permet, de ce fait, de disposer d’une solution de filtrage réseau centralisé.
⚠️ Point important : à aucun moment cette solution ne vient en remplacement des NSGs qui forment une partie essentielle d’une approche Zero Trust. Tout d’abord, parce que le principe même du Zero Trust est la défense en profondeur, et qu’elle s’appuie sur une sécurité distribuée sur plusieurs couches. Et d’autre part parce que d’un point de vue Spoke, sortir du réseau pour aller dans le hub, se voir appliquer du filtrage, et revenir dans le même réseau serait une idée saugrenue…
Avec l’ajout de notre appliance, nous obtenons la topologie suivante :

À ce stade, nous n’avons pas encore finalisé la configuration, et notamment la partie routage. C’est ce que nous allons faire dans la suite de l’article.
Pour le moment, nous avons un firewall central dans notre Virtual Hub, qui transforme de fait celui-ci en un Secure Hub. Comme discuté précédemment, certains de ses cas d’usage sont :
- Fournir une solution de filtrage inter-spokes.
- Mettre à disposition des capacités de filtrage supplémentaire comme des règles de niveau 7.
- Fournir un moyen de sortie Internet centralisé, disposant d’une IP clairement identifiée. (un point important, dans la mesure où la sortie Internet par défaut des Vnets va bientôt disparaitre).
Un autre aspect intéressant de cette approche est justement son attribut centralisé, notamment pour une équipe réseau souhaitant un point de contrôle sur tout ce qui rentre ou sort d’un spoke.
Intéressons-nous à présent aux options disponibles pour le Virtual Network appliance.
Par son aspect managé, le Virtual Hub ne nous offre pas les mêmes options qu’un Virtual Network standard.
Dans un Virtual Hub, la première option disponible est l’Azure Firewall. Disponible également dans un modèle de déploiement direct dans un Virtual Network, il est entièrement managé et intégré à Azure, et est zone-redundant. Par son intégration dans le paysage Azure, son déploiement et sa gestion peuvent être réalisés avec les mêmes outils que toute la plateforme Azure. D’un autre côté, il diffère des solutions auxquelles sont habituées les équipes de réseau et sécurité.
Dans le cas où les fonctionnalités du Firewal Azure seraient considérées comme insuffisantes, il est possible de se tourner sur une des options du catalogue de partenaires Virtual WAN.
À l’heure actuelle, les partenaires de sécurité incluent CheckPoint, Fortigate et également Palo Alto, en tant qu’offre SaaS.
Voilà qui finalise les aspects théoriques. Passons maintenant à la pratique.
Construire un Secure Hub en partant de zéro
Pour ajouter un peu de fun à notre expérience, nous allons utiliser Terraform pour créer l’ensemble de nos ressources.
Construction d’un Virtual Hub
Pour commencer, nous avons besoin des ressources suivantes :
- Un Virtual WAN
- Un Virtual Hub
Une recherche rapide dans la documentation Terraform nous donne le code ci-dessous :
Nous voulons également ajouter quelques spokes, et une fois leur création finalisée, nous ajoutons une Network Connection depuis le Virtual Hub :
Voyons maintenant comment passer à un Secure Hub.
Ajouter un Firewall pour passer à un Secure Hub
Pour passer au Secure Hub, il nous faut ajouter un Azure Firewall :
On remarquera la configuration simplifiée par rapport à un Azure Firewall déployé directement dans un Virtual Network.
Dans notre cas, nous devons spécifier le bloc virtual_hub. Nous devons également spécifier le sku_name à la valeur AZFW_Hub.
Enfin on remarquera l’argument firewall_policy_id, qui, bien qu’optionnel, nous permet d’attacher une Firewall Policy au Firewall. Il nous faut dans ce cas créer une ressource supplémentaire avec le code ci-dessous :
Cette configuration permet de créer la Firewall policy, mais sans règle pour le moment.
D’autre part, bien que nous ayons notre conteneur de règles avec le firewall et la policy, le routage dans son état actuel propage les routes sans passer par le firewall.
La topologie disponible dans le portail nous affiche ceci :

Si nous regardons le firewall, nous pouvons observer quelques informations relatives aux IPs :

Si l’on regarde la configuration de routage entre 2 machines dans 2 spokes, nous pouvons confirmer que le next hop entre ces VMs n’est pas le firewall pour le moment :

Nous avons la configuration de routage par défaut dans notre Virtual Hub, utilisant la route créée par défaut.

Avec les routes pour chaque spoke propagé sur cette route par défaut à la création de la network connection.

Configurer le routage et les règles de Firewall
Ajoutons une table de routage custom, afin de forcer le trafic à travers le Firewall.
Avec cette nouvelle table de routage, nous pouvons changer les Network Connections. Pour nos tests, nous ne changeons que les spokes 2 et 4.
On remarquera le paramètre internet_security_enabled qui peut être configuré à true ou false (comme nous le verrons plus en détail dans la suite de l’article).
Dans le bloc routing, on peut voir l’argument associated_route_table_id pointant vers notre nouvelle table de routage. On peut également voir dans le bloc propagated_route_table une valeur égale à noneRouteTable. À travers cette configuration, on empêche la propagation des routes pour les spokes dans la table de routage custom.
On peut vérifier les changements sur les Network Connections :

À noter : si l’on souhaite repasser sur la route par défaut, il ne suffit pas de retirer le bloc routing. Il est nécessaire de reconfigurer ce bloc pour faire pointer le routage sur la table de routage par défaut et d’indiquer la propagation vers cette même table de routage.
Avec var.CustomRouteTableName configurer avec la valeur « defaultRouteTable ».
Regardons à nouveau Network Watcher pour avoir l’information sur le next hop. D’abord, sur 2 VMs dans le même Virtual Network :


Si l’on ajoute une IP publique, avec la configuration NSG appropriée, nous pouvons accéder à notre VM, et vérifier que nous accédons bien à notre seconde VM.
Maintenant, regardons la configuration de routage pour 2 VMs dans les 2 spokes que nous avons configurés avec la table de routage custom.


On note l’adresse IP du next hop cette fois ci, qui correspond à l’IP privée de notre Firewall.
Si l’on essaye d’accéder à la seconde VM depuis la première, nous n’avons pas de réponse, puisque nous n’avons pas de flux défini au niveau du Firewall :
Ajoutons quelques règles sur notre Firewall. Pour notre scénario, nous allons créer une collection de règles par spoke, pour définir à un endroit ce qui entre et sort d’un spoke. Dans le cas présent, nous avons juste besoin de valider que le Firewall fait son travail ; nous nous contenterons donc d’autoriser le trafic ICMP depuis tout le spoke, et le trafic SSGH uniquement depuis l’un des subnets du spoke :
On notera dans les sources et destinations, l’usage d’IP Groups, des objets Azure qui nous permettent de définir des tags custom pour un Azure Firewall.
L’output de cet objet nous donne ceci :
Il nous serait possible d’écrire des règles en utilisant la propriété cidrs de l’IP Group, en lieu et place de son ID. On changerait dans ce cas la règle avec les arguments destination_addresses et source_addresses.
Cependant, l’affichage des règles dans le portail nous donne dans ce cas le range IP plutôt que le nom de l’IP Group.

Cette étape validée, le trafic ICMP est à présent autorisé sur le second spoke depuis l’ensemble du premier, tandis que le trafic SSH est uniquement autorisé depuis la VM1 du premier spoke.
Considérations supplémentaires
Trafic sortant sur le Firewall
À ce stade, nous avons notre Secure Hub et nous savons gérer le flux interspoke avec l’Azure Firewall.
Revenons à présent sur l’argument internet_security_enabled. Pour rappel, nous avons créé un premier spoke avec ce paramètre configuré à false et un second spoke configuré à true.
La VM du spoke avec internet_security_enabled = false est accessible depuis Internet, et nous n’avons pas de problème pour accéder aux dépôts Ubuntu.
Pour la VM dans le spoke avec internet_security_enabled = true, dans la configuration réseau actuelle, nous ne pouvons pas accéder à ces mêmes dépôts :
Nous devons donc ajouter des règles de préférence en ciblant des fqdns.
D’un point de vue Network Watcher, le next hop pour l’adresse 8.8.8.8 depuis la VM dans le spoke avec internet_security_enabled = false utilise toujours la System Route du Virtual Network.

En revanche, le spoke avec internet_security_enabled = true donne un next hop dont l’IP correspond au Firewall.

Ce paramètre n’est pas sur la valeur true par défaut depuis le portail. De fait, son équivalent GUI n’est pas internet_security_enabled mais Propagate Default Route, ce qui est peu parlant.

Trafic entrant depuis Internet avec un SecurityEnabled spoke
Maintenant, que se passe-t-il si nous voulons accéder à une VM dans un spoke avec internet_security_enabled = true depuis Internet ?
Nous allons lui associer une adresse IP et configurer une règle sur le NSG, comme d’habitude.
Mais… cela ne marche pas. Ce qui est logique, au regard du résultat de Network Watcher. Nous pouvons potentiellement entrer sur la VM, mais le trafic retour doit passer par le Firewall, et ainsi, pas d’accès.
Il est possible d’envisager des scénarios avec une granularité au niveau subnet, mais nous garderons ça pour une autre fois.
Gérer plusieurs tables de routage
Un dernier scénario avant de conclure ; ce cas est plutôt bien documenté sur la documentation Azure dans la section Isolate Vnets custom scenario.
Dans le cas présent, nous avons des spokes que l’on considère comme privés, et de ce fait derrière le firewall Azure à travers une table de routage custom. Les autres spokes, que l’on considère comme publics, utilisent la table de routage par défaut.

Les spokes privés sont… privés, sauf peut-être celui avec internet_security_enabled = true.
Les spokes publics utilisent la table de routage par défaut qui ne route pas le trafic interspoke à travers le Firewall. D’un côté, les spokes privés ont une route pour trouver les spokes publics, à travers les routes que nous avons déjà définies.

L’inverse n’est en revanche pas vrai :

Pour résoudre ce problème, nous devons ajouter une route vers les spokes privés sur la table de routage par défaut.
Nous ne pouvons pas nous contenter de propager la route à travers la Network Connection, puisque nous n’utiliserions pas dans ce cas le Firewall.
Nous devons à la place ajouter une route pour chaque spoke privé sur la table de routage par défaut :
Une fois appliqué, le résultat Network Watcher nous indique bien le Firewall comme next hop.

En ajoutant un peu de règles sur le firewall :
Nous sommes en mesure d’accéder à une VM sur un spoke privé depuis une autre dans un spoke public :
Voilà qui finalise notre épopée dans le Secure Hub.
L’essentiel à retenir
Passer d’un Virtual Hub à un Secure Hub implique de déployer un appliance de sécurité pour faire office de Firewall. Dans notre cas, nous avons utilisé un Azure Firewall qui reste relativement simple à déployer par Terraform.
Au-delà de la présence de ce firewall, nous devons également prendre en considération le routage. Nous devons notamment configurer :
- Les Network Connections des spokes avec les paramètres de routage ;
- Des routes additionnelles sur la table de routage par défaut pour autoriser le routage entre public et private spoke.
Il est nécessaire de gérer, bien évidemment, les règles à un niveau du Firewall. Sur ce sujet, nous pourrions regarder encore un certain nombre de choses, mais nous avons vu les bases avec les Network rules et les Application rules.
Nous avons vu le paramètre internet_security_enabled qui nous permet :
- S’il est configuré sur true, de forcer le trafic à destination d’Internet à passer par le Firewall, empêchant au passage une exposition Internet directe dans le spoke.
- S’il est configuré sur false, de garder la priorité de la System Route Table du VNet, et ainsi de ne pas passer par le Firewall du Hub en sortie.
Autres sujets que nous garderons pour une prochaine fois :
- Accéder et rechercher dans les logs de Firewall (NSG et Azure Firewall)
- Suivre les évolutions du Virtual WAN avec par exemple les Routing Intents.
Rendez-vous bientôt donc pour d’autres articles sur le sujet !
D’ici là, vous souhaitez en savoir plus et échanger avec un expert ? Contactez-nous !