Scenario: Credit Union Hybrid AVD in Canada Central (Toronto HQ)
Youโre rolling out Azure Virtual Desktop (AVD) in Canada Central for 300 staff. Identity and core services still live on-prem in Toronto HQ (AD DS, DNS, file shares, legacy line-of-business apps). You need a Site-to-Site VPN so that:
- AVD session hosts can join the domain
- Users get low-friction access to on-prem resources (file shares, app servers)
- You avoid exposing internal services to the public Internet

Target Design (at a glance)
Azure (Canada Central)
- VNet:
AVD-Prod-vNET - Address space:
10.50.0.0/16 - Workload subnet:
WorkloadSubnet=10.50.10.0/24 - GatewaySubnet:
10.50.255.0/27 - VPN Gateway:
AVD-VNGW-CC - Public IP:
AVD-VNGW-CC-PIP - VPN: Route-based, IKEv2, Gen2, SKU VpnGw2
On-prem (Toronto HQ)
- VPN device public IP:
(your ISP-assigned public IP) - Private address space to route:
10.20.0.0/16(HQ LAN),10.21.0.0/16(Server VLAN)
Lab 1: Build the Site-to-Site VPN using Azure Portal
Prereqs
- Resource group:
RG-AVD-Network-Prod - VNet already created:
AVD-Prod-vNET - You have:
- On-prem firewall/router that supports IPSec/IKEv2
- A chosen PSK (shared key)
Step A: Create the Azure VPN Gateway
- Azure Portal โ Search Virtual network gateways
- Click Create
- Configure:
- Name:
AVD-VNGW-CC - Region:
Canada Central - Gateway type:
VPN - VPN type:
Route-based - SKU:
VpnGw2 - Generation:
Gen2 - Virtual network:
AVD-Prod-vNET - Gateway subnet address range:
10.50.255.0/27
(Azure will create the GatewaySubnet if it doesnโt exist) - Public IP: Create new
- Public IP name:
AVD-VNGW-CC-PIP
- Public IP name:
- Active-active: Disabled
- BGP: Disabled
- Name:
- Review + create โ Create
Reality check: provisioning a VPN Gateway often takes a while. Donโt panic if itโs 20โ45 minutes in some tenants.
Step B: Create the Local Network Gateway (Toronto HQ representation)
- Azure Portal โ Search Local network gateways
- Click Create
- Configure:
- Name:
LNG-TorontoHQ - Endpoint: IP address
- IP address:
() - Address space:
10.20.0.0/1610.21.0.0/16
- BGP: Disabled
- Region:
Canada Central - Resource group:
RG-AVD-Network-Prod
- Name:
- Click Create
Step C: Create the S2S Connection
- Go to Virtual network gateways โ
AVD-VNGW-CC - Left menu โ Connections
- Click + Add
- Configure:
- Name:
Conn-AVD-CC-to-TorontoHQ - Connection type: Site-to-site (IPSec)
- Virtual network gateway:
AVD-VNGW-CC - Local network gateway:
LNG-TorontoHQ - Shared key (PSK):
() - Enable BGP: Unticked
- IKE Protocol:
IKEv2
- Name:
- Click Create
- Verify connection status shows Connected
What you configure on the Toronto firewall/router
Have these ready for the network team (or for your own change window):
- Remote peer IP: Azure gateway public IP (from
AVD-VNGW-CC-PIP) - Remote networks:
10.50.0.0/16(or the exact Azure subnets you want reachable) - Local networks:
10.20.0.0/16,10.21.0.0/16 - PSK: exactly the same as the Azure Connection setting
- IKEv2 + IPSec settings: must match proposals (encryption, integrity, DH group, lifetimes)
- Confirm NAT rules are not unintentionally translating internal subnets in a way that breaks routing
Lab 2: Build the same S2S VPN using PowerShell (Az module)
Replace the placeholder values before running.
# Connect
Connect-AzAccount
# Set-AzContext -Subscription "" # optional
$Location = "Canada Central"
$RgName = "RG-AVD-Network-Prod"
$VnetName = "AVD-Prod-vNET"
# Azure VNet plan
$VnetAddressSpace = "10.50.0.0/16"
$WorkloadSubnetName = "WorkloadSubnet"
$WorkloadSubnetPrefix = "10.50.10.0/24"
$GatewaySubnetName = "GatewaySubnet"
$GatewaySubnetPrefix = "10.50.255.0/27"
# Gateway objects
$VpnGwName = "AVD-VNGW-CC"
$PipName = "AVD-VNGW-CC-PIP"
$LngName = "LNG-TorontoHQ"
$ConnName = "Conn-AVD-CC-to-TorontoHQ"
# On-prem settings (replace)
$OnPremPublicIp = "198.51.100.20" # Toronto firewall/router public IP
$OnPremAddressPrefixes = @("10.20.0.0/16","10.21.0.0/16") # On-prem routed networks
$SharedKey = "REPLACE_WITH_STRONG_PSK"
# 1) Resource group
if (-not (Get-AzResourceGroup -Name $RgName -ErrorAction SilentlyContinue)) {
New-AzResourceGroup -Name $RgName -Location $Location | Out-Null
}
# 2) VNet (create if missing) + ensure GatewaySubnet exists
$vnet = Get-AzVirtualNetwork -Name $VnetName -ResourceGroupName $RgName -ErrorAction SilentlyContinue
if (-not $vnet) {
$subWork = New-AzVirtualNetworkSubnetConfig -Name $WorkloadSubnetName -AddressPrefix $WorkloadSubnetPrefix
$subGw = New-AzVirtualNetworkSubnetConfig -Name $GatewaySubnetName -AddressPrefix $GatewaySubnetPrefix
$vnet = New-AzVirtualNetwork `
-Name $VnetName `
-ResourceGroupName $RgName `
-Location $Location `
-AddressPrefix $VnetAddressSpace `
-Subnet @($subWork, $subGw)
} else {
$gwSubnet = Get-AzVirtualNetworkSubnetConfig -Name $GatewaySubnetName -VirtualNetwork $vnet -ErrorAction SilentlyContinue
if (-not $gwSubnet) {
Add-AzVirtualNetworkSubnetConfig -Name $GatewaySubnetName -AddressPrefix $GatewaySubnetPrefix -VirtualNetwork $vnet | Out-Null
$vnet = Set-AzVirtualNetwork -VirtualNetwork $vnet
}
}
$gwSubnet = Get-AzVirtualNetworkSubnetConfig -Name $GatewaySubnetName -VirtualNetwork $vnet
# 3) Public IP
$pip = New-AzPublicIpAddress `
-Name $PipName `
-ResourceGroupName $RgName `
-Location $Location `
-Sku Standard `
-AllocationMethod Static
# 4) Gateway IP config
$gwIpConfig = New-AzVirtualNetworkGatewayIpConfig `
-Name "gwipconfig1" `
-SubnetId $gwSubnet.Id `
-PublicIpAddressId $pip.Id
# 5) Create VPN Gateway
$vng = New-AzVirtualNetworkGateway `
-Name $VpnGwName `
-ResourceGroupName $RgName `
-Location $Location `
-IpConfigurations $gwIpConfig `
-GatewayType Vpn `
-VpnType RouteBased `
-GatewaySku VpnGw2 `
-VpnGatewayGeneration "Generation2" `
-EnableBgp $false
# 6) Local Network Gateway
$lng = New-AzLocalNetworkGateway `
-Name $LngName `
-ResourceGroupName $RgName `
-Location $Location `
-GatewayIpAddress $OnPremPublicIp `
-AddressPrefix $OnPremAddressPrefixes
# 7) S2S Connection
$conn = New-AzVirtualNetworkGatewayConnection `
-Name $ConnName `
-ResourceGroupName $RgName `
-Location $Location `
-VirtualNetworkGateway1 $vng `
-LocalNetworkGateway2 $lng `
-ConnectionType IPsec `
-SharedKey $SharedKey `
-EnableBgp $false
# 8) Verify
Get-AzVirtualNetworkGatewayConnection -Name $ConnName -ResourceGroupName $RgName |
Select-Object Name, ConnectionStatus, IngressBytesTransferred, EgressBytesTransferred
Verification Checklist (the โdonโt leave until this is greenโ list)
Azure-side checks
- VPN Gateway deployment: Succeeded
- Connection: Connected
- GatewaySubnet exists and is correct:
10.50.255.0/27
Routing checks
- No overlapping CIDRs (Azure and on-prem)
- On-prem device routes include Azure address space (
10.50.0.0/16) - Local Network Gateway includes every on-prem subnet you expect to reach
Functional tests (recommended)
From an Azure VM in WorkloadSubnet:
- Ping is often blocked. Prefer TCP tests:
Test-NetConnection-Port 53 Test-NetConnection(LDAP)-Port 389 Test-NetConnection(SMB)-Port 445 nslookup yourdomain.local
How this ties back to AVD (practical purpose)
Once S2S is up, you can confidently deploy:
- AVD session hosts that domain-join to on-prem AD DS
- FSLogix profile storage on a file share that AVD hosts can reach
- Legacy app dependencies that still run on-prem