Managed and secured hub-spoke architecture using Azure WAN and Firewall Manager
Azure Virtual WAN is a managed hub-spoke architecture, that supports public (VPN) and private (Express Route) connectivity. The hub enables transitive connectivity between endpoints that may be distributed across different types of spokes. Traffic from the branches enters Microsoft’s network at the Microsoft edge, or Point of Presence (PoP) sites closest to a given branch office and traverse Microsoft backbone to reach the virtual hub. In this architecture, there is a single hub per region, and all sites from that region connect to the closest hub. You can also connect to a hub in a different region, but for latency-sensitive connections, this probably is not a good idea. Hub-to-hub connection (in preview at the time of writing) enables full mesh between the hubs enabling, for example, vnet-to-vnet or branch-to-branch connectivity through the hubs.
There are two types of SKUs for Azure Virtual WAN:
- Basic: supports only Site-to-site VPN connectivity
- Standard: supports ExpressRoute, Point-to-site VPN, Site-to-site VPN, Inter-hub and vnet-to-vnet connectivity
Secured virtual hub (in public preview) is an Azure Virtual WAN Hub with associated security and routing policies configured by Azure Firewall Manager. It enables the easy creation of hub-and-spoke architectures with cloud-native security services for traffic governance and protection. A secured virtual hub can also be used as a managed central virtual network with no on-prem connectivity.
Pricing
Several components of the architecture are involved in the pricing (prices below are for the West Europe region):
Connectivity unit
- Site-to-site VPN / Express Route: €0.043/hour
- User VPN (Point-to-site) : €0.011/hour
Scale unit (Aggregate throughput of a hub gateway)
- 1 VPN Scale Unit = €0.305/hour (500 Mbps)
- 1 ExpressRoute Scale Unit = €0.355/hour (2 Gbps)
Virtual Hub
- Basic Virtual WAN Hub : No charge
- Standard Virtual WAN Hub : €0.211/hour,
- Secure Virtual WAN Hub: €0.528/hour (preview price)
- Virtual WAN Hub data processing: €0.014/GB
- Secured Virtual WAN Hub data processing: €0.007/GB (preview price)
Deployment
For the demo, we are going to create a Virtual WAN with a secured virtual hub. We will create two spokes (Shared Services and WebApp spoke),deploy an Application Gateway in the Shared Services spoke and publish the nginx from the WebApp spoke through the previously created Application Gateway. To enable communication between the spokes, we will create a Firewall Policy. You can find the full script here.
Note: If we want to route Internet traffic from the spokes through the Azure Firewall deployed in the hub, we will lose the connectivity to the services that are using public IP in the spokes (in our case Application Gateway). Probably, this is some limitation of the public preview of Azure Firewall Manager.
Let’s start.
1. Set the value of the variables we are going to use during the deployment
resourceGroupName="rg-wan"
location="westeurope"
wanName="tosokr-wan"
virtualHubName="tosokr-westEurope-hub"
virtulHubAddressPrefix="10.0.0.0/16"
sharedServicesVnetName="vnet-sharedServices"
sharedServicesVnetAddressPrefix="10.1.0.0/16"
sharedServicesVnetSubnet1Name="default"
sharedServicesVnetSubnet1AddressPrefix="10.1.0.0/24"
spokeVnetName="vnet-spoke"
spokeVnetAddressPrefix="10.2.0.0/16"
spokeVnetSubnet1Name="default"
spokeVnetSubnet1AddressPrefix="10.2.0.0/24"
spokeVMName="nginxServer"
spokeVMUserName="tosokr"
spokeVMPassword="MyP@ssw0rd637!"
spokeVMIPAddress="10.2.0.4"
2. Install virtual-wan and azure-firewall cli extensions
az extension add --name virtual-wan
az extension add --name azure-firewall
3. Create the resource group
az group create --name $resourceGroupName --location $location
4. Create Azure WAN
az network vwan create --name $wanName \
--resource-group $resourceGroupName --type Standard \
--location $location --vnet-to-vnet-traffic --branch-to-branch-traffic
5. Create virtual hub
az network vhub create --name $virtualHubName \
--address-prefix $virtulHubAddressPrefix \
--resource-group $resourceGroupName \
--vwan $wanName --location $location \
--sku Standard
6. Convert the virtual hub into secured virtual hub
az network firewall create --name virtulHubFirewall \
--resource-group $resourceGroupName \
--location $location --sku AZFW_Hub \
--vhub $virtualHubName
7. Create shared services spoke vnet
az network vnet create --name $sharedServicesVnetName \
--resource-group $resourceGroupName \
--address-prefixes $sharedServicesVnetAddressPrefix \
--location $location \
--subnet-name $sharedServicesVnetSubnet1Name \
--subnet-prefixes $sharedServicesVnetSubnet1AddressPrefix
8. Crete a spoke vnet
az network vnet create --name $spokeVnetName \
--resource-group $resourceGroupName \
--address-prefixes $spokeVnetAddressPrefix \
--location $location \
--subnet-name $spokeVnetSubnet1Name \
--subnet-prefixes $spokeVnetSubnet1AddressPrefix
9. Get the ids of the created network resources
sharedServicesVnetId=$(az network vnet show --name $sharedServicesVnetName \
--resource-group $resourceGroupName --query id -o tsv )
spokeVnetId=$(az network vnet show --name $spokeVnetName \
--resource-group $resourceGroupName --query id -o tsv)
spokeSubnet1Id=$(az network vnet subnet show --name $spokeVnetSubnet1Name \
--resource-group $resourceGroupName --vnet-name $spokeVnetName \
--query id -o tsv)
10. Peer the shared services vnet with the secured hub
az network vhub connection create \
--name sharedServicesConnectionPeer \
--remote-vnet $sharedServicesVnetId \
--resource-group $resourceGroupName \
--internet-security true \
--vhub-name $virtualHubName
11. Peer the spoke vnet with the secured hub
az network vhub connection create \
--name spokeConnectionPeer \
--remote-vnet $spokeVnetId \
--resource-group $resourceGroupName \
--internet-security true \
--vhub-name $virtualHubName
12. Send the traffic between vnets and branches through Azure Firewall
az network vhub route-table create \
--connections All_Branches All_Vnets \
--destination-type CIDR \
--destinations $sharedServicesVnetAddressPrefix $spokeVnetAddressPrefix \
--name VirtualNetworkAndBranchRouteTable \
--next-hop-type IPAddress \
--next-hops 10.0.64.4 \
--resource-group $resourceGroupName \
--vhub-name $virtualHubName \
--location $location
13. Create a cloud-init file for the Linux VM to auto install nginx on provisioning
cat <<EOF > cloud-init.yaml
#cloud-config
package_upgrade: true
packages:
- nginx
EOF
14. Deploy Linux VM in spoke vnet
az vm create --name $spokeVMName \
--resource-group $resourceGroupName \
--image UbuntuLTS --authentication-type password \
--admin-username $spokeVMUserName \
--admin-password $spokeVMPassword \
--location $location \
--private-ip-address $spokeVMIPAddress \
--public-ip-address "" \
--size Standard_A1_v2 \
--subnet $spokeSubnet1Id \
--generate-ssh-keys \
--custom-data cloud-init.yaml
15. Create public IP address for the Application Gateway
az network public-ip create \
--resource-group $resourceGroupName \
--name myAGPublicIPAddress \
--allocation-method Static \
--sku Standard
16. Create the ApplicationGateway
az network application-gateway create \
--name aksAppGateway \
--location $location \
--resource-group $resourceGroupName \
--capacity 1 \
--sku Standard_v2 \
--public-ip-address myAGPublicIPAddress \
--vnet-name $sharedServicesVnetName \
--subnet $sharedServicesVnetSubnet1Name \
--http-settings-port 80 \
--http-settings-protocol Http \
--servers $spokeVMIPAddress
17. Create a firewall policy
az network firewall policy create \
--name WanBasePolicy \
--resource-group $resourceGroupName \
--location $location
18. Create a firewall rule collection group
az network firewall policy rule-collection-group create \
--name spokeRules --policy-name WanBasePolicy \
--priority 201 --resource-group $resourceGroupName
19. Add filter collection into the rule collection group
az network firewall policy rule-collection-group collection add-filter-collection \
--collection-priority 201 \
--name spokeCollection \
--policy-name WanBasePolicy \
--resource-group $resourceGroupName \
--rule-collection-group-name spokeRules \
--action Allow \
--rule-type NetworkRule \
--destination-addresses $spokeVMIPAddress \
--destination-ports 80 \
--ip-protocols TCP \
--source-addresses $sharedServicesVnetSubnet1AddressPrefix
20. Assing the policy to the firewall
az network firewall update \
--name virtulHubFirewall \
--resource-group $resourceGroupName \
--firewall-policy WanBasePolicy
21. Access the Application Gateway listener
curl http://$(az network public-ip show \
--name myAGPublicIPAddress --resource-group $resourceGroupName \
--query ipAddress -o tsv)
If you do not see the “Welcome to nginx!” page, wait for 30 seconds for the backend health to refresh in Application Gateway. If still not successful, debug debug debug …