Insight Tech APAC Blog Logo

The magic of the GatewaySubnet, BGP and Bicep CIDR functions

stephentulp
May 7, 2025

8 minutes to read

Introduction

Anyone that has established network connectivity to Azure from an on-premise environment will be familiar with the Gateway Subnet. The Gateway Subnet is a special Azure subnet used to host Azure virtual network gateways that provide hybrid connectivity between an on-premises environment and Azure.

Other key details include:

  • The gateway subnet must be named GatewaySubnet to function correctly. This specific naming convention lets Azure know that this subnet is designated for deploying virtual network gateways.
  • It requires an addressPrefix of /27 or larger, even though its technically possible for it to be a /29.
  • There are two (2) types of gateways that can be deployed, VPN and/or ExpressRoute. This enables establishing a Site to Site VPN connection and/or the termination of an ExpressRoute circuit.
  • No other resources can be deployed into the subnet.

From a resiliency perspective there are two deployment patterns;

Active / Standby

Active / Standby


By default, every Azure VPN gateway is configured with two instances in an active-standby setup. During planned maintenance or any unplanned disruption affecting the active instance, the standby instance automatically takes over (failover) and resumes the connection. This switch causes a brief interruption. For planned maintenance, connectivity is typically restored within 10 to 15 seconds. However, for unplanned issues, the recovery time can be longer, ranging from about 1 to 3 minutes in the worst-case scenario.

Active / Active

Active / Active


In an active-active configuration both instances of the gateway establish connectivity to the on-premises VPN device. Each Azure gateway instance is assigned a unique public IP address, and each one establishes a VPN tunnel to the VPN device.

Understanding the BGP Values

I was recently working on something where I needed to enable BGP in the VPN gateway deployment using Infrastructure as Code.

The diagram below outlines the subnet structure of the hub virtual network, which is a pretty common setup for a hub and spoke network topology.

Virtual Network


As we can see the GatewaySubnet is a /26, which means there are 59 usable IP addresses in the subnet (once we exclude the first 4 and last 1) as outlined here

Subnet Calculator


This means the first usable would be 10.52.0.68 and the last usable is 10.52.0.126, if splitting subnets and networking isn’t your thing then I highly recommend the Visual Subnet Calculator (Azure Edition) that can do a lot of the calculations for you.

Generally when deploying into a subnet, a virtual machine will get the first usable IP address in the subnet, so in this case I would expect this to be 10.52.0.68. I configured the Bicep template, enabled BGP, completed the deployment and then used the export template feature (which now supports ARM, Bicep and Terraform), as you can see on line 50 it actually was the last usable assigned 10.52.0.126.

No HA


That wasn’t what I was expecting! so I modified the deployment to be an Active/Active deployment where another IP would be allocated (I also updated the peering weight). Based on the above I assumed I would now get 10.52.0.125 and 10.52.0.126 as the BGP addresses.

HA


Ok now it has 10.52.0.68 and 10.52.0.69, so basically the first 2 usable addresses in the range!! This seems so strange to me and something I want to get to the bottom of at some stage.

Leveraging Bicep Functions

So now we know what the IP addresses will be, I wanted to leverage bicep to calculate these values and remove the need to hardcode or statically assign these values. There are CIDR functions in Bicep that enable you to return these values when working with CIDR.

parseCidr

  • This function parses an IP address range in CIDR notation to get various properties of the address range including network range, netmask, broadcast address, and first and last usable IP addresses.

cidrSubnet

  • Splits the specified IP address range into subnets with a new CIDR value and returns the IP address range of the subnet with the specified index.

cidrHost

  • Calculates the usable IP address of the host with the specified index on the specified IP address range in CIDR notation.

Writing the Bicep Code

Subnets


With in the template the first thing we do is define the array of subnets that we need, as you can see from the description there would normally be other attributes in here like delegation, Route Table and NSG resource Id but I have removed to make it easier to understand.

Map


We then define two variables, subnetMap and subnetProperties, which are used to process and structure the subnet parameters into a format suitable for creating Azure subnets in the virtual network.

  • subnetMap: This variable uses the Bicep map function to iterate over the subnets array. For each subnet, it creates a new object containing the name and ipAddressRange properties. This essentially transforms the subnets array into a mapped structure that makes it easier to process.

  • subnetProperties: This variable uses a for loop to iterate over the subnetMap and creates a new array of objects. Each object represents a subnet with its name and properties, where properties includes the subnet addressPrefix.

Map


Now that we have the Subnets and properties defined, we need a few variables defined;

  • gatewaySubnetCIDR: This variable extracts the addressPrefix (CIDR block) of the GatewaySubnet from the subnetProperties array. It assumes the GatewaySubnet is at index 1 in the array.

  • GatewaySubnetNoHa: This variable calculates the last usable IP address in the GatewaySubnet using the parseCidr function. This will give us the IP .126 for a non-HA deployment.

  • GatewaySubnetHA: This variable generates an array of IP addresses within the GatewaySubnet CIDR using the cidrHost function. It iterates over the range of values 3 times (which is actually 4 when you include 0) to give us the first and second usable addresses .68 and .69.

Conclusion

In conclusion, leveraging Bicep’s CIDR functions simplifies subnet and IP address calculations, making deployments more dynamic and reducing the need for hardcoded values. While unexpected behaviors in IP allocation can arise, understanding and utilising these functions ensures more efficient and adaptable infrastructure-as-code practices for Azure environments. After all of that I didn’t end up using the above but still a good learning experience either way.