I thought about making the title of this blog post “Creating a uni-directional Azure Virtual Network Peering,” but it would have been a bit too click-baity. Still, conceptually, what I am describing in this post is along those lines.
Virtual Network Peering and the VirtualNetwork Service Tag
When two Virtual Networks (VNets) are peered, the definition of the VirtualNetwork service tag changes to include the IP addresses of the peered network. When subnets have a default Network Security Group (NSG) or no NSG applied, all traffic is allowed to and from the VirtualNetwork service tag:
Practically speaking, this means that resources in either VNet can communicate unrestricted (permit me to ignore any NSGs applied on VMs or host firewalls for this discussion).
In some scenarios, such as secure research enclaves (maybe I’ll have an opportunity to blog about those in the future), that’s not desirable. You might need to enable communication between a hub and a spoke VNet, but more tightly control what communication is allowed. While you can always resort to deny rules, those can get complicated quickly.
However, there’s a way to change the peering configuration on either or both sides so that the VirtualNetwork service tag is not modified. In doing so, communication will not be allowed, unless you specifically allow it using NSG allow rules.
It should be noted that NSGs are applied to subnets, not to VNets. You’ll need to create allow rules in each NSG for each of the subnets you want to allow communication to and from. If you have NSGs on individual resources (VMs), you’ll need to add allow rules there as well.
Here’s how to do it step-by-step for the case where you care that the spoke network can only communicate with the hub to select IPs, ports, or protocols.
First, if you need a good introduction to Azure Virtual Network Peering, check out the video by John Savill below.
For my example, assume a hub network with range 10.3.0.0/24 and a spoke with range 10.4.0.0/24. First, create a network peering as usual and ensure that the resources can communicate as expected. You might for example test with ICMP echo in both directions.
Then, modify the peering on the spoke side and block traffic to remote network, as shown in the screenshot below:
At this point, resources in either VNet cannot communicate across the peering anymore. Even though the VirtualNetwork service tag in the hub network is unmodified and the hub considers the spoke as part of its VirtualNetwork, the incoming connection is blocked by the spoke.
Now, let’s add allow rules in the NSG of a subnet in the spoke. I am going to use HTTP as an example. This means the subnet will need to allow traffic from the IP range of the hub inbound on port 80 and outbound from port 80. To facilitate identifying the webserver VM in the spoke, I created an Application Security Group (ASG). Even with only a single VM, this is beneficial because I don’t have to worry about the IP of the VM changing or future scale out with additional webserver VMs.
Here’s a screenshot of the inbound and outbound rule created to allow TCP 80 (HTTP) traffic from the hub to the spoke and the response back to the hub.
Notice the port range in the outbound rule: it is 1024-65535. This is because the port range in the screenshot is the destination port range. (The source port for the outbound rule is 80.) You can’t determine which port a client in the hub will use to open the connection to the webserver in the spoke (but it should be >= 1024), so we need to allow that range to be the destination range because the webserver will respond to the client on the same port it received the request from.
Remember, if you applied NSGs to the webserver’s NIC, you’ll need to create these allow rules there too.
We peer Azure Virtual Networks to enable resources in these separate VNets to communicate. If your scenario calls for limiting communication between peered VNets, the steps above will allow you to switch the “default allow” to a “default deny,” saving you from having to devise (and troubleshoot) potentially complex deny rules.