Azure Basics : les Network Security Groups

Dans ce nouvel article, je vous propose une revue des Network Security Groups (NSG), ces petits objets agissant comme firewall distribués dans vos environnements Azure.
Au programme :
- Network Security group 101
- Recommandations pour utiliser les NSG
- Scénarios de flux réseaux gérés avec des NSGs
- Ce que vous devriez retenir
Network Security Group 101
En soi, un NSG n’est rien de plus qu’un firewall distribué. On le qualifie de « statefull », terme sur lequel nous reviendrons un peu plus tard.
Que fait un NSG ?
Ce que fait le NSG :
- Il filtre le trafic réseau sur des objets vivant dans le réseau Virtual Azure (Vnet) uniquement. Plus exactement il filtre le trafic sur les cartes réseaux dans le Vnet.
- Il peut être appliqué au niveau d’un subnet ou d’une carte réseau directement.
- Il fonctionne avec des règles, pour des flux dans les directions entrantes ou sortantes. Nous parlerons respectivement d’ingress et egress, ou d’inbound et outbound.
- Il a des règles par défaut qui ne peuvent pas être supprimées. Ces règles par défaut sont affichées ci-dessous :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 65000 | AllowVnetInBound | Inbound | Allow | * | * | * | VirtualNetwork | VirtualNetwork |
| 65001 | AllowAzureLoadBalancerInBound | Inbound | Allow | * | * | * | AzureLoadBalancer | * |
| 65500 | DenyAllInBound | Inbound | Deny | * | * | * | * | * |
| 65000 | AllowVnetOutBound | Outbound | Allow | * | * | * | VirtualNetwork | VirtualNetwork |
| 65001 | AllowInternetOutBound | Outbound | Allow | * | * | * | * | Internet |
| 65500 | DenyAllOutBound | Outbound | Deny | * | * | * | * | * |
- Les règles de NSG ont une priorité définie par un nombre compris entre 100 et 4096. Le nombre le plus proche de 100 indique une plus grande priorité.
- L’évaluation des règles de NSG suit le schéma suivant, que l’on retrouve sur la documentation Azure

Une règle de NSG peut être de type allow ou deny.
Une règle de NSG peut être enrichie avec des Service Tags et/ou des Applications Security Groups.
Le NSG est stateful, ce qui signifie ici que le trafic retour est implicitement autorisé.
Service Tags et Application Security Groups
Avant de continuer, un mot sur les Service Tags et les Application Security Groups.
Un Service Tag est, comme son nom le laisse supposer, un tag ou une étiquette permettant d’identifier des ranges d’IPs connus, comme Internet, AzureCloud, LoadBalancer, VirtualNetwork…
En utilisant ces tags, on peut limiter l’utilisation d’IP dans les règles de NSG, notamment dans le cas de range important ou pouvant bouger dans le temps comme Internet ou AzureCloud.
Un Application Security Group (ASG), d’une manière similaire à un Service Tag, est un tag custom géré par l’utilisateur, lui permettant de désigner une VM ou un groupe de VMs plutôt que d’utiliser les adresses IP.
Maintenant que nous avons défini les bases, voici quelques recommandations sur l’utilisation des NSG.
Recommandation pour l’utilisation des Network Security Groups
Voici quelques recommandations dans l’usage des NSG, pour limiter la complexité, et s’assurer d’un bon filtrage :
- Lire la documentation Azure concernant le service à utiliser. En général, les prérequis en termes de flux sont indiqués, et les règles de NSG requises le sont également.
- Se limiter sur l’application des NSG au niveau des subnets. L’usage de Service Tag et d’ASG nous permet de définir les règles de manière granulaire.
- Regarder le filtrage pour chaque objet connecté au Vnet.
- Se concentrer avant tout sur le trafic entrant. Les règles Outbound peuvent se limiter au filtrage de ce qui sort d’Azure. Tant que l’on filtre du trafic dans un Vnet, on peut se contenter de règles Inbound.
- Définir un standard pour la définition des priorités, comme par exemple :
| Priority range | Rule type | Description |
| 1000 – 1500 | Project specific allow rule | Allow rules that should be defined with project team, at design stage, and that may override default infrastructure rules |
| 1500 – 2000 | Project specific deny rule | Deny rules that should be defined with project team, at design stage |
| 2000 – 3000 | Infrastructure default allow | Allow rules defined to ensure that Azure environment and services are working correctly |
| 3000 – 4000 | Infrastructure default deny | Deny rules defined to provide default network flows configuration and comply with Security policies |
À noter : on gardera à l’esprit que certains services, comme Bastion ou Application Gateway, vivant dans un subnet dédié ont leurs règles spécifiques définies. Ces règles devraient être incluses dans le design par défaut, afin de permettre l’intégration systématique par Infrastructure as Code.
- Définir les règles par défaut, par exemple :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 4000 | DefaultDenyAll | Inbound | Deny | * | * | * | * | * |
| 3000 | DefaultAllowAlltoAzureCloud | Outbound | Allow | * | * | * | * | AzureCloud |
| 4000 | DefaultDenyAllToOnPremise | Outbound | Deny | * | * | * | * | On-Premise Ranges |
| 4010 | DefaultDenyAllInternet | Outbound | Deny | * | * | * | * | Internet |
Scénarios de flux réseaux gérés avec des NSGs
Avec ces quelques concepts définis, regardons quelques exemples.
Gérer les flux réseaux pour une VM isolée dans un Vnet
Il s’agit du scénario le plus simple et le plus évident, mais il faut bien commencer par quelque chose.
On considère ici une seule VM, dans un subnet d’un Vnet. Suivant ce que nous avons défini plus tôt, nous avons un NSG au niveau du subnet.

Au départ, nous n’avons que les règles par défaut du NSG :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 65000 | AllowVnetInBound | Inbound | Allow | * | * | * | VirtualNetwork | VirtualNetwork |
| 65001 | AllowAzureLoadBalancerInBound | Inbound | Allow | * | * | * | AzureLoadBalancer | * |
| 65500 | DenyAllInBound | Inbound | Deny | * | * | * | * | * |
| 65000 | AllowVnetOutBound | Outbound | Allow | * | * | * | VirtualNetwork | VirtualNetwork |
| 65001 | AllowInternetOutBound | Outbound | Allow | * | * | * | * | Internet |
| 65500 | DenyAllOutBound | Outbound | Deny | * | * | * | * | * |
Dans ce cadre, la VM est bien isolée, et nous n’avons pas eu besoin de spécifier de règles additionnelles.
Suivant la logique d’évaluation des règles pour le trafic entrant :
- Il n’y a rien dans le Vnet à l’exception de la VM, donc rien qui permette de matcher la règle 65000.
- Il n’y a pas d’Azure Load Balancer, donc pas de match non plus pour la règle 65001.
- Il y a bien, en revanche, des éléments en dehors du Vnet, ce qui correspondrait ici à du trafic Internet. La règle 65500 matche tous ces cas et bloque de facto le trafic entrant.
Pour le trafic sortant :
- La règle 65000 autorise la VM dont l’IP matche le Service Tag VirtualNetwork à atteindre un autre objet connecté au Vnet. Mais puisqu’il s’agit d’une VM unique, il n’y a rien à matcher ici.
- La règle 65001 commence à nous donner des choses intéressantes. Elle spécifie « * », ce qui veut dire que tout le trafic, incluant la VM, peut accéder à Internet. On peut donc aller un peu partout sur Internet depuis cette VM.
- Enfin, la règle 65500 bloque tout le trafic sortant restant. Cela étant dit, nous avons déjà autorisé beaucoup avec la règle précédente.
Tout cela étant relativement simple, je vous propose à présent d’ajouter un peu de trafic.
Cette fois ci, nous considérons notre VM comme un serveur Web, qui doit donc être accessible depuis Internet. Nous devons donc ajouter une règle pour autoriser Internet à accéder à notre serveur Web.
Cependant, nous ne voulons pas gérer de règle avec des IPs. Nous allons donc ajouter un ASG et l’associer à notre VM. Dans le cas présent, nous allons créer un ASG WebServer.
Il nous faut également une IP publique pour rendre la VM accessible depuis Internet.

| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 1010 | AllowWebServerInbound | Inbound | Allow | TCP | * | 443 | Internet | WebServer |
Pour l’instant, cela reste toujours assez simple, donc continuons.
Gérer les flux réseaux pour 2 VMs dans un Vnet
Cette fois-ci, nous avons une seconde VM dans le même Vnet. Cette VM est dans un subnet différent.

Ce second subnet est également associé à un NSG, sans aucune autre règle que celle par défaut pour commencer.
Cette VM est-elle accessible depuis Internet ?
En suivant la même logique d’évaluation que précédemment, il n’y a rien qui permette le trafic entrant sur cette nouvelle VM. Ajoutons également qu’en l’absence d’une IP publique, elle n’est pas accessible de toute façon. Donc la réponse est non.
La première VM est-elle en capacité d’accéder à cette nouvelle VM ?
Encore une fois, en suivant la logique d’évaluation, on constate que la VM WebServer matche la règle Inbound 65000 :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 65000 | AllowVnetInBound | Inbound | Allow | * | * | * | VirtualNetwork | VirtualNetwork |
Maintenant, si nous voulons être un peu plus sélectifs, nous pouvons envisager les étapes suivantes :
- Ajouter un nouvel ASG sur la nouvelle VM, que nous appelons ici BackendServer.
- Ajouter une nouvelle règle qui autorise spécifiquement le trafic depuis le web server vers le serveur de backend, avec les deux ASG WebServer et BackendServer. Pour notre exemple, nous utiliserons en port cible le TCP 1433.
- Enfin, pour restreindre le trafic à ce port uniquement, nous ajouterons une autre règle qui interdira explicitement tout autre trafic sur le serveur Backend.
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 1010 | AllowWebServerToBackEndServer | Inbound | Allow | TCP | * | 1433 | WebServer | BackendServer |
| 3010 | DenyAllToBackendServer | Inbound | Deny | * | * | * | * | BackendServer |

On notera que nous n’avons pas besoin d’ajouter de règle Outbound sur le NSG du WebServer pour gérer le trafic sortant de ce dernier.
Continuons avec un autre scénario.
Gérer les flux réseaux pour 2 VMs dans 2 Vnets appairés
Cette fois-ci, nous ajoutons un autre Vnet et une nouvelle VM. Sans autre configuration, la nouvelle VM peut sortir sur Internet, et donc accéder au WebServer à travers la règle que nous avons configurée pour rendre ce serveur accessible depuis l’extérieur.
Ajoutons un peering entre nos 2 Vnets : cela nous permet d’autoriser le trafic entre nos deux Vnets.

Notons que par défaut, le peering est configuré pour autoriser le trafic entre les Vnets appairés.


Ce point a une importance particulière vis-à-vis du Service Tag VirtualNetwork. En effet, le peering étend les 2 Vnets et, lorsque l’on autorise le trafic entre les Vnets avec l’option illustrée plus haut, ajoute pour cela le range réseau du partenaire d’appairage.
On ne peut malheureusement pas le voir facilement, sans une VM (et donc une NIC) dans l’un des Vnet en question :

Revenons à notre scénario : par défaut la VM dans notre second Vnet va matcher la règle qui inclut le service tag VirtualNetwork.
Si l’on considère la machine WebServer, cela signifie que la règle 65000 autorise l’accès :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 65000 | AllowVnetInBound | Inbound | Allow | * | * | * | VirtualNetwork | VirtualNetwork |
Si l’on considère le BackendServer, parce que nous avons rajouté la règle 3010, dont la priorité est plus importante que la règle 65000, le trafic est explicitement interdit :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 1010 | AllowWebServerToBackEndServer | Inbound | Allow | TCP | * | 1433 | WebServer | BackendServer |
| 3010 | DenyAllToBackendServer | Inbound | Deny | * | * | * | * | BackendServer |
Pour autoriser, on pourrait imaginer passer par un ASG, ce qui est après tout bien commode. Toutefois, en lisant attentivement la documentation Azure, on aura relevé que l’ASG n’est pas utilisable pour gérer du trafic à travers plusieurs Vnets appairés. Lorsque l’on essaye, on obtient le message d’erreur suivant :
De fait, la gestion du trafic avec les NSG entre Vnet appairé ne peut se faire qu’à travers les adresses IP, ce qui est une des plus grandes limites des NSG.
Concrètement, pour autoriser le trafic depuis notre VM du Vnet appairé vers la VM Backend, on devrait avoir une configuration comme ci-dessous :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 1010 | AllowWebServerToBackEndServer | Inbound | Allow | TCP | * | 1433 | WebServer | BackendServer |
| 1020 | AllowHubServerToBackEndServer | Inbound | Allow | TCP | * | 1433 | IP_Of_HubVM | BackendServer |
| 3010 | DenyAllToBackendServer | Inbound | Deny | * | * | * | * | BackendServer |
Passons à présent à notre dernier scénario.
Gérer les flux réseaux dans une topologie Hub & Spokes
Dans ce scénario, un peu comme dans le précédent, nous avons un Vnet Hub connecté à plusieurs Vnet Spokes.
Comme ce modèle repose sur du peering de Vnets, ce que nous avons vu précédemment reste valide.
Toutefois, le peering n’étant pas transitif par défaut, aucune route n’est propagée par défaut pour permettre le trafic d’un spoke à un autre à travers le hub. Il nous faudrait ajouter un élément pour jouer le rôle de router dans le hub et valider la configuration de routage avec des UDR. Cet article étant concentré sur les NSG, nous ne rentrerons pas dans ce genre de détail ici.
Nous sommes donc dans un scénario similaire au précédent :
- Le Service Tag VirtualNetwork est étendu pour un spoke avec son partenaire de peering direct, c’est-à-dire le hub.
- Le Service Tag VirtualNetwork est étendu pour le Hub avec l’ensemble de ses partenaires de peering direct, à savoir chaque spoke.
- Les ASG ne peuvent toujours pas être utilisés pour filtrer le trafic inter-spoke.
Si l’on considère le schéma ci-dessous :

Pour la VM1 dans spoke1, la configuration par défaut du peering et la règle 65000 autorise le trafic vers la VM2 dans le Hub :
| priority | name | direction | access | protocol | source Port Range(s) | destination Port Range(s) | source Address Prefix(es) | destination Address Prefix(es) |
| 65000 | AllowVnetInBound | Inbound | Allow | * | * | * | VirtualNetwork | VirtualNetwork |
Et il en est de même pour la VM3 dans spoke2.
Pour le trafic allant de VM3 vers VM1, il n’y a pas de règle autorisant le trafic :
- Le Service Tag VirtualNetwork dans le spoke 1 n’inclut pas le range du spoke 2. De ce fait, la règle Inbound 65000 n’autorise pas le trafic entrant depuis spoke2.
- Le Service Tag VirtualNetwork dans le spoke 1 n’inclut pas le range du spoke 2. De ce fait, la règle Outbound 65000 n’autorise pas le trafic sortant vers spoke1.
- Il n’est pas possible d’utiliser 1 ASG dans spoke1 pour identifier VM3.
- Il n’est pas possible d’utiliser 1 ASG dans spoke2 pour identifier VM1.
- Il n’est pas non plus possible d’identifier VM2 dans aucun des spokes avec un ASG.
- Il n’y a pas de route définie entre les spokes, donc même l’ajout de règle ne suffirait pas en l’état à permettre le trafic entre VM1 et VM3.

Ce qu’il faut retenir
Les NSG peuvent être utilisés pour gérer les flux réseaux d’une façon distribuée, en appliquant un NSG au niveau du subnet, de préférence, ou d’une VM.
Il est plus facile de gérer les règles de NSG à l’aide des ASG et des Service Tags.
Le NSG est idéal pour la gestion du trafic intra Vnet, mais moins pour la gestion du trafic inter Vnet, en raison de la limitation sur les ASG.
Le peering a un impact sur le Service Tag VirtualNetwork, et implique donc de bien maitriser les règles de base NSG et/ou de réaliser une configuration custom du peering.
Sans configuration de routage, la communication spoke-to-spoke n’est pas possible à travers le Hub.
Pour finir, nous n’avons abordé que des aspects purement NSG, sans regarder d’autres outils disponibles comme Network Watcher, Network Manager ou tout simplement l’observabilité des flux à travers les logs disponibles. Tous ces sujets méritent suffisamment de matière pour rendre cet article beaucoup trop long, donc nous en resterons la pour le moment.
