Introduction
I looked into virtual network peering peering in Azure and I saw something that looked rather strange to me. Let me explain what it was, how VNet peering works and what you should be aware of from a security perspective.
Situation
I have two virtual networks: one for 10.1.0.0/16 addresses and one for 10.2.0.0/16 addresses. Both networks have one 10.1-or-2.1.0/24 subnet, to keep it simple. In both networks I enrolled one virtual machine via the portal. When the VNet peering works I expect to be able to ping from one VM to the other VM.
Because I got the VMs via the portal, I also got a public IP address and a network security group for both of them. In the VNet for the first network, I switched on VNet peering, and I used the defaults:
I just wanted to do pings from the first network to the second network. So I configured the two Network Security Groups (NSGs) to allow ping traffic between the two networks. For example, the NSG for the first network looks like:
Then it was time to go to the first VM, and do a ping. And, not surprisingly, this works.
Blocking network traffic
But then I was intrigued: the first configuration in the peering was about restricting network traffic between the two networks. Why we would do that? Well, the information icon tells us what the use case for this setting is. There is also a warning when you try to switch off this setting:
To find out what would happen when I used this switch, I disabled this setting and then tried the ping again. And, to my surprise, the pings were still answered. The reason for this is also in the information balloon: when you enable this setting, then VNet10_2 address space (10.2.0.0/16) is added to the Virtual_Network tag for the first network. It turns out that this setting is not blocking any traffic, as the name suggests. This setting is only used in the Network Security Group to allow (or not allow) all traffic between the connected networks.
It turned out that I was too eager to add the security rules for the ping traffic to the Network Security Groups: when I wouldn’t have done that, the pings would also be possible (as long as the switch is turned “on”). And because I added the extra security rules for ICMP traffic, my pings were still allowed, even when the switch was turned “off”.
Security
But wait, shouldn’t we use something like “least privileged access control”? When we use the default settings and a hacker is able to hack my first virtual machine, than he or she can travel through all the networks that are connected via VNet peering. In fact, I was able to ssh from the first to the second VM even without knowing that I could do so. That’s in general not what we want…
So instead of deleting my own security rules for ICMP traffic, it would be better to delete the default rule that allows the network traffic for VirtualNetwork. Unfortunately deleting these default rules is impossible, so I added an extra block rule for all the traffic that is not explicitly mentioned in other security rules with a higher priority than the default rules. And while I was doing that, I was also securing port 22 traffic to only allow traffic from my own PC….
Policy
I think that this option is a security risk. Fortunately, Azure has a way of dealing with this: it is possible to add a policy to prevent chancing some settings. There is no default policy to check (or enforce) disabling this setting, so I added a policy myself:
{
"properties": {
"displayName": "AMIS: Least Privileged: Traffic to remote virtual network should be disabled in VNet Peering",
"policyType": "Custom",
"mode": "all",
"description": "Traffic to remote virtual network should be disabled in VNet Peering",
"metadata": {
"version": "0.0.1",
"category": "Access Control"
},
"parameters": {},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"field": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings[*].allowVirtualNetworkAccess",
"equals": "true"
}
]
},
"then": {
"effect": "deny"
}
}
}
When I used this policy, I would expect that the policy would prevent me from switching on the switch again. Unfortunately this didn’t happen. Even though there is a deny in this policy, the switch could be toggled and the settings could be saved. I think this might be a bug. Having a policy to know that this is not compliant or that has been changed is a nice feature anyway.
Play along
As usual, I created a script to enroll this solution in your own environment [1] to make it possible to follow along. In fact, there are two scripts: one for the enrollment of the policy definition and one for the other resources. First, start the script for the deployment of the policy via the following command:
New-AzDeployment -Name SubscrDeployment -TemplateFile .\VNetPeering-subscription.json -Location WestEurope
Then, create a resource group yourself. In the script, I assume that you name this AMISBlog, but you can change the parameter of the ARM template to match your own name if you need to. The resources are deployed in this resource group via the following command:
New-AzResourceGroupDeployment -Name RGDeployment -ResourceGroupName AMISBlog -TemplateFile ".\VNetPeering-resourceGroup.json"
When you are done playing around, you can destroy the AMISBlog resource group. After that, open the Policies part of Azure and destroy the custom policy “AMIS: Least Privileged: Traffic to remote virtual network should be disabled in VNet Peering”.
Links
[1] See https://github.com/FrederiqueRetsema/AMIS-Blog-Azure-2021 , directory “VNet peering”