Skip to main content

Challenge 14: Site-to-site VPN gateway

Estimated time and cost

60-90 minutes | ~$0.19/h (VpnGw1 SKU) | Exam weight: 20-25%

Deployment time

VPN Gateway provisioning takes 30-45 minutes. Use --no-wait and continue with other tasks while the gateway deploys.

Scenario

Contoso has a hub virtual network in Azure (vnet-hub, 10.1.0.0/16) and an on-premises datacenter with the address space 192.168.0.0/16. The on-premises VPN device has a public IP of 203.0.113.50. The networking team must establish a site-to-site IPsec VPN tunnel between the Azure hub VNet and the on-premises datacenter to enable hybrid connectivity for workloads that cannot yet migrate to Azure.

Architecture:

On-premises datacenter192.168.0.0/16VPN Device: 203.0.113.50IPsec/IKEAzure — vnet-hub10.1.0.0/16VPN Gateway: vgw-hubGatewaySubnet (10.1.255.0/27)snet-workloads (10.1.1.0/24)snet-mgmt (10.1.2.0/24)

Learning objectives

After completing this challenge you will be able to:

  • Design and implement a site-to-site VPN connection
  • Create and configure a local network gateway representing on-premises
  • Create and configure a virtual network gateway (VPN type)
  • Identify when to use a policy-based VPN versus a route-based VPN connection
  • Verify VPN connection status and troubleshoot connectivity issues

Prerequisites

  • An Azure subscription with Contributor access
  • Azure CLI installed and authenticated (az login)
  • PowerShell with Az module installed (Install-Module Az -Force)
  • A resource group and VNet already created (or create them in Task 1)

Key concepts for AZ-700

ConceptDetail
GatewaySubnetDedicated subnet for the VPN gateway; must be named exactly GatewaySubnet; recommended size /27 or larger
Virtual Network GatewayAzure-managed VPN endpoint; supports route-based (dynamic) or policy-based (static)
Local Network GatewayLogical representation of the on-premises VPN device (public IP + address prefixes)
VPN ConnectionThe IPsec/IKE tunnel linking the virtual network gateway to the local network gateway
Route-based VPNUses route tables for traffic selection; supports multiple tunnels, P2S, VNet-to-VNet, coexistence with ExpressRoute
Policy-based VPNUses traffic selectors (ACLs); limited to a single S2S tunnel; required for legacy devices
Shared key (PSK)Pre-shared key that must match on both sides of the tunnel

Policy-based vs route-based VPN

FeaturePolicy-basedRoute-based
IKE versionIKEv1 onlyIKEv1 and IKEv2
Max S2S tunnels130 (VpnGw1) to 100 (VpnGw4/5)
Point-to-SiteNot supportedSupported
BGP supportNot supportedSupported
VNet-to-VNetNot supportedSupported
Coexist with ExpressRouteNot supportedSupported
Gateway SKUBasic onlyVpnGw1-5, VpnGw1AZ-5AZ
Use caseLegacy on-prem devices requiring IKEv1 policy matchAll modern deployments
Exam note

The exam frequently tests when policy-based is required versus route-based. The answer is almost always route-based unless the question explicitly states a legacy device that only supports IKEv1 with policy-based traffic selectors. Route-based gateways are the default recommendation.


Task 1: Create the hub VNet and GatewaySubnet

Azure CLI

# Create resource group
az group create \
--name rg-vpn-lab \
--location eastus

# Create hub VNet
az network vnet create \
--resource-group rg-vpn-lab \
--name vnet-hub \
--location eastus \
--address-prefixes 10.1.0.0/16 \
--subnet-name snet-workloads \
--subnet-prefixes 10.1.1.0/24

# Create the GatewaySubnet (must be named exactly "GatewaySubnet")
az network vnet subnet create \
--resource-group rg-vpn-lab \
--vnet-name vnet-hub \
--name GatewaySubnet \
--address-prefixes 10.1.255.0/27

Azure PowerShell

# Create resource group
New-AzResourceGroup -Name "rg-vpn-lab" -Location "eastus"

# Create hub VNet with subnets
$workloadsSubnet = New-AzVirtualNetworkSubnetConfig `
-Name "snet-workloads" `
-AddressPrefix "10.1.1.0/24"

$gatewaySubnet = New-AzVirtualNetworkSubnetConfig `
-Name "GatewaySubnet" `
-AddressPrefix "10.1.255.0/27"

New-AzVirtualNetwork `
-ResourceGroupName "rg-vpn-lab" `
-Name "vnet-hub" `
-Location "eastus" `
-AddressPrefix "10.1.0.0/16" `
-Subnet $workloadsSubnet, $gatewaySubnet
GatewaySubnet requirements
  • The name must be GatewaySubnet (case-sensitive, no other names work)
  • Minimum recommended size is /27 (32 addresses) to allow for future growth and active-active configurations
  • /28 is the absolute minimum but limits future expandability
  • Do not associate an NSG or route table with the GatewaySubnet (it can disrupt gateway operation)

Task 2: Deploy the VPN gateway

Step 1: Create a public IP for the gateway

az network public-ip create \
--resource-group rg-vpn-lab \
--name pip-vgw-hub \
--location eastus \
--allocation-method Static \
--sku Standard

Step 2: Create the virtual network gateway

az network vnet-gateway create \
--resource-group rg-vpn-lab \
--name vgw-hub \
--vnet vnet-hub \
--gateway-type Vpn \
--vpn-type RouteBased \
--sku VpnGw1 \
--vpn-gateway-generation Generation1 \
--public-ip-addresses pip-vgw-hub \
--no-wait

Azure PowerShell

# Create public IP
$pip = New-AzPublicIpAddress `
-ResourceGroupName "rg-vpn-lab" `
-Name "pip-vgw-hub" `
-Location "eastus" `
-AllocationMethod Static `
-Sku Standard

# Get subnet reference
$vnet = Get-AzVirtualNetwork -ResourceGroupName "rg-vpn-lab" -Name "vnet-hub"
$gwSubnet = Get-AzVirtualNetworkSubnetConfig -Name "GatewaySubnet" -VirtualNetwork $vnet

# Create IP configuration
$ipConfig = New-AzVirtualNetworkGatewayIpConfig `
-Name "gwIpConfig" `
-SubnetId $gwSubnet.Id `
-PublicIpAddressId $pip.Id

# Create the VPN gateway (takes 30-45 minutes)
New-AzVirtualNetworkGateway `
-ResourceGroupName "rg-vpn-lab" `
-Name "vgw-hub" `
-Location "eastus" `
-IpConfigurations $ipConfig `
-GatewayType Vpn `
-VpnType RouteBased `
-GatewaySku VpnGw1 `
-AsJob

Step 3: Monitor deployment progress

# Check provisioning state (repeat until "Succeeded")
az network vnet-gateway show \
--resource-group rg-vpn-lab \
--name vgw-hub \
--query "provisioningState" \
--output tsv

Task 3: Create the local network gateway

The local network gateway represents the on-premises VPN device in Azure. It stores the public IP of the on-prem device and the address prefixes of the on-prem network.

Azure CLI

az network local-gateway create \
--resource-group rg-vpn-lab \
--name lgw-onprem-datacenter \
--gateway-ip-address 203.0.113.50 \
--local-address-prefixes 192.168.0.0/16 \
--location eastus

Azure PowerShell

New-AzLocalNetworkGateway `
-ResourceGroupName "rg-vpn-lab" `
-Name "lgw-onprem-datacenter" `
-Location "eastus" `
-GatewayIpAddress "203.0.113.50" `
-AddressPrefix "192.168.0.0/16"

Multiple on-premises subnets

If the on-premises network has multiple non-contiguous subnets, list them all:

az network local-gateway create \
--resource-group rg-vpn-lab \
--name lgw-onprem-datacenter \
--gateway-ip-address 203.0.113.50 \
--local-address-prefixes 192.168.1.0/24 192.168.2.0/24 10.50.0.0/16 \
--location eastus

Task 4: Create the VPN connection

Once the VPN gateway has finished provisioning, create the IPsec connection.

Azure CLI

az network vpn-connection create \
--resource-group rg-vpn-lab \
--name conn-hub-to-onprem \
--vnet-gateway1 vgw-hub \
--local-gateway2 lgw-onprem-datacenter \
--shared-key "Contoso!VPN#2024secure"

Azure PowerShell

$vgw = Get-AzVirtualNetworkGateway -ResourceGroupName "rg-vpn-lab" -Name "vgw-hub"
$lgw = Get-AzLocalNetworkGateway -ResourceGroupName "rg-vpn-lab" -Name "lgw-onprem-datacenter"

New-AzVirtualNetworkGatewayConnection `
-ResourceGroupName "rg-vpn-lab" `
-Name "conn-hub-to-onprem" `
-Location "eastus" `
-VirtualNetworkGateway1 $vgw `
-LocalNetworkGateway2 $lgw `
-ConnectionType IPsec `
-SharedKey "Contoso!VPN#2024secure"
Shared key requirements
  • The shared key must be identical on both sides (Azure and on-premises device)
  • Maximum 128 characters
  • Supports alphanumeric characters and special characters
  • Use a strong, randomly generated key in production

Task 5: Verify connection status

Azure CLI

# Check connection status
az network vpn-connection show \
--resource-group rg-vpn-lab \
--name conn-hub-to-onprem \
--query "{status:connectionStatus, inBytes:ingressBytesTransferred, outBytes:egressBytesTransferred}" \
--output table

Azure PowerShell

Get-AzVirtualNetworkGatewayConnection `
-ResourceGroupName "rg-vpn-lab" `
-Name "conn-hub-to-onprem" | `
Select-Object Name, ConnectionStatus, IngressBytesTransferred, EgressBytesTransferred

Connection status values

StatusMeaning
ConnectedTunnel is established and passing traffic
ConnectingAzure side is ready but waiting for the on-prem device to respond
NotConnectedConnection object exists but the tunnel has not been initiated
UnknownCannot determine state (check gateway health)
Lab simulation

In a lab without a real on-premises device, the connection will remain in Connecting state. This is expected. To simulate a fully connected tunnel, deploy a second VPN gateway in another VNet and create a VNet-to-VNet connection (both sides are under your control).


Task 6: Test connectivity (lab simulation with second VNet)

To verify end-to-end connectivity in a lab, create a second VNet simulating the on-premises network:

# Create simulated on-prem VNet
az network vnet create \
--resource-group rg-vpn-lab \
--name vnet-onprem-sim \
--location eastus \
--address-prefixes 192.168.0.0/16 \
--subnet-name snet-servers \
--subnet-prefixes 192.168.1.0/24

az network vnet subnet create \
--resource-group rg-vpn-lab \
--vnet-name vnet-onprem-sim \
--name GatewaySubnet \
--address-prefixes 192.168.255.0/27

# Create second public IP and gateway
az network public-ip create \
--resource-group rg-vpn-lab \
--name pip-vgw-onprem \
--location eastus \
--allocation-method Static \
--sku Standard

az network vnet-gateway create \
--resource-group rg-vpn-lab \
--name vgw-onprem-sim \
--vnet vnet-onprem-sim \
--gateway-type Vpn \
--vpn-type RouteBased \
--sku VpnGw1 \
--vpn-gateway-generation Generation1 \
--public-ip-addresses pip-vgw-onprem \
--no-wait

After both gateways are provisioned, create connections in both directions:

# Update local gateway with actual public IP of simulated on-prem gateway
ONPREM_GW_IP=$(az network public-ip show \
--resource-group rg-vpn-lab \
--name pip-vgw-onprem \
--query "ipAddress" \
--output tsv)

az network local-gateway update \
--resource-group rg-vpn-lab \
--name lgw-onprem-datacenter \
--gateway-ip-address "$ONPREM_GW_IP"

# Create the reverse local gateway (representing Azure hub from on-prem perspective)
HUB_GW_IP=$(az network public-ip show \
--resource-group rg-vpn-lab \
--name pip-vgw-hub \
--query "ipAddress" \
--output tsv)

az network local-gateway create \
--resource-group rg-vpn-lab \
--name lgw-azure-hub \
--gateway-ip-address "$HUB_GW_IP" \
--local-address-prefixes 10.1.0.0/16 \
--location eastus

# Create reverse connection (on-prem to hub) with same shared key
az network vpn-connection create \
--resource-group rg-vpn-lab \
--name conn-onprem-to-hub \
--vnet-gateway1 vgw-onprem-sim \
--local-gateway2 lgw-azure-hub \
--shared-key "Contoso!VPN#2024secure"

Break & fix

Scenario 1: Shared key mismatch

Symptom: Connection status remains Connecting indefinitely.

Root cause: The shared key on the Azure connection does not match the key configured on the on-premises device.

Diagnostic command:

az network vpn-connection show \
--resource-group rg-vpn-lab \
--name conn-hub-to-onprem \
--query "connectionStatus" \
--output tsv
# Returns: Connecting

Fix: Update the shared key to match both sides:

az network vpn-connection update \
--resource-group rg-vpn-lab \
--name conn-hub-to-onprem \
--shared-key "CorrectMatchingKey2024!"

Scenario 2: Missing GatewaySubnet

Symptom: Gateway creation fails with an error about missing subnet.

Root cause: The VNet does not have a subnet named exactly GatewaySubnet.

Fix: Create the subnet with the exact required name:

az network vnet subnet create \
--resource-group rg-vpn-lab \
--vnet-name vnet-hub \
--name GatewaySubnet \
--address-prefixes 10.1.255.0/27

Scenario 3: Wrong local address prefixes

Symptom: VPN tunnel is Connected but traffic to certain on-premises subnets is not routed through the tunnel.

Root cause: The local network gateway is missing address prefixes for some on-premises subnets.

Diagnostic command:

az network local-gateway show \
--resource-group rg-vpn-lab \
--name lgw-onprem-datacenter \
--query "localNetworkAddressSpace.addressPrefixes" \
--output tsv

Fix: Update the local gateway with all on-premises prefixes:

az network local-gateway update \
--resource-group rg-vpn-lab \
--name lgw-onprem-datacenter \
--local-address-prefixes 192.168.0.0/16 10.50.0.0/16
![Challenge 14 - Network Topology](/img/az-700/challenge-14-topology.svg)


```powershell
Remove-AzResourceGroup -Name "rg-vpn-lab" -Force -AsJob

Additional references