Introduction
This guide walks through setting up an active-active site-to-site VPN between an Azure Virtual Network Gateway and an on-premises Firewall (Unifi in this example) using BGP for dynamic route advertisement.
BGP is used over static routes to provide a resilient tunnel pair where both Azure gateway instances are active simultaneously — giving you automatic failover without manual intervention, or traffic loss if one tunnel goes down.- Azure subscription with Contributor access
- On-premises firewall supporting BGP
- Understanding of network routing
- Azure Virtual Network (VNet) with a GatewaySubnet configured
Overview
An Azure VPN Gateway operates in either active-standby or active-active mode.
In Active-Standby Mode, one instance handles traffic while the other acts as a Standby Unit ready to take over operations if the Primary Instance fails.If the Primary instance fails in an Active-Standby Configuration, the Secondary takes over, but there is a brief outage during failover. In an Active-Active Mode, both instances handle traffic simultaneously, each with its own public IP and BGP peer address. Your on-premises device establishes two tunnels and BGP sessions, one to each Azure instance. We are following the following design toplogy in this scenario https://learn.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-highlyavailable#active-active-vpn-gateways
Requirements:
- Azure Virtual Network Gateway — active-active, VpnGw1 SKU or higher
- Local Network Gateway — represents your Unifi device in Azure
- Connection — links the VNet Gateway to the Local Network Gateway
- Unifi Network — BGP and IPsec configuration on your gateway
Step 1 — Create the Virtual Network Gateway
In the Azure portal, navigate to Virtual Network Gateways and create a new gateway with the following settings:
| Setting | Value |
|---|---|
| Gateway type | VPN |
| VPN type | Route-based |
| SKU | VpnGw1 (minimum for active-active) |
| Active-active mode | Enabled |
| Configure BGP | Enabled |
| ASN | 65515 (Azure default, change if needed) |
Azure will provision two public IPs automatically — one per gateway instance. Note both IPs once deployment completes; you'll need them for the Unifi config.
Step 2 — Create the Local Network Gateway
The Local Network Gateway tells Azure about your on-premises side. Because you're using BGP, you don't need to list specific address prefixes — BGP will handle route advertisement dynamically.
- IP address — your Unifi gateway's public IP
- BGP settings → ASN — your chosen on-premises ASN (e.g.
65001) - BGP peer IP address — a link-local address, e.g.
169.254.0.1
The BGP peer IP is a link-local address that runs inside the tunnel — it doesn't need to exist on a real interface. Azure uses169.254.21.xand169.254.22.xfor its own peer IPs by default.
Step 3 — Create the VPN Connection
Link the Virtual Network Gateway to the Local Network Gateway with a Connection. Enable BGP on the connection.
- Connection type — Site-to-site (IPsec)
- Shared key (PSK) — generate a strong random string (min 32 chars)
- Enable BGP — Yes
- IKE protocol — IKEv2
Azure creates two tunnel endpoints automatically in active-active mode. You'll need to configure both on the Unifi side.
Step 4 — Configure Unifi (config.gateway.json)
On Unifi, IPsec site-to-site and BGP config is done via config.gateway.json on the controller (or
directly via the CLI on UDM devices). Replace the placeholder values with your own.
{
"vpn": {
"ipsec": {
"site-to-site": {
"peer": {
/* Tunnel 1 — Azure instance 0 */
"<AZURE_IP_1>": {
"authentication": {
"mode": "pre-shared-secret",
"pre-shared-secret": "<YOUR_PSK>"
},
"connection-type": "initiate",
"ike-group": "AzureIKEv2",
"default-esp-group": "AzureESP",
"local-address": "<UNIFI_PUBLIC_IP>",
"tunnel": {
"1": {
"allow-nat-networks": "disable",
"allow-public-networks": "disable",
"local": { "prefix": "0.0.0.0/0" },
"remote": { "prefix": "0.0.0.0/0" },
"protocol": "all"
}
}
},
/* Tunnel 2 — Azure instance 1 */
"<AZURE_IP_2>": {
"authentication": {
"mode": "pre-shared-secret",
"pre-shared-secret": "<YOUR_PSK>"
},
"connection-type": "initiate",
"ike-group": "AzureIKEv2",
"default-esp-group": "AzureESP",
"local-address": "<UNIFI_PUBLIC_IP>",
"tunnel": {
"1": {
"allow-nat-networks": "disable",
"allow-public-networks": "disable",
"local": { "prefix": "0.0.0.0/0" },
"remote": { "prefix": "0.0.0.0/0" },
"protocol": "all"
}
}
}
}
}
}
},
"protocols": {
"ike-group": {
"AzureIKEv2": {
"key-exchange": "ikev2",
"proposal": {
"1": {
"dh-group": "14",
"encryption": "aes256",
"hash": "sha256"
}
},
"lifetime": "28800",
"dead-peer-detection": {
"action": "restart",
"interval": "10",
"timeout": "30"
}
}
},
"esp-group": {
"AzureESP": {
"pfs": "dh-group14",
"proposal": {
"1": {
"encryption": "aes256",
"hash": "sha256"
}
},
"lifetime": "27000"
}
},
"bgp": {
"65001": {
"neighbor": {
"169.254.21.1": {
"remote-as": "65515",
"address-family": {
"ipv4-unicast": { "soft-reconfiguration": "inbound" }
}
},
"169.254.22.1": {
"remote-as": "65515",
"address-family": {
"ipv4-unicast": { "soft-reconfiguration": "inbound" }
}
}
},
"address-family": {
"ipv4-unicast": {
"network": {
"<YOUR_LOCAL_SUBNET>": {}
}
}
}
}
}
}
}
169.254.21.1 and 169.254.22.1 are the
Azure-side defaults. Confirm the exact values in the Azure portal under Virtual Network Gateway → BGP
peers after deployment.
Step 5 — Verify the tunnels
After pushing the config, check tunnel and BGP state from the Unifi CLI:
# Check IPsec tunnel status
show vpn ipsec sa
# Check BGP neighbor state
show ip bgp neighbors
# Verify advertised and received routes
show ip bgp summary
show ip route bgp
You should see two IPsec SAs established (one per Azure instance) and two BGP sessions in
Established state. Azure will advertise the VNet address space; your Unifi will advertise your
local subnet.
Common issues
- Tunnels stuck in connecting — check IKE proposal mismatch. Azure requires AES-256 / SHA-256 / DH-14 minimum.
- BGP stays in Active — confirm the link-local peer IPs match exactly what Azure shows, and that the VTI interfaces are up.
- Routes not propagating — ensure
soft-reconfiguration inboundis set and the local subnet is explicitly advertised underbgp network.
Wrapping up
Once both tunnels and BGP sessions are established, Azure will load-balance outbound traffic across the two instances. If one instance fails, BGP reconverges automatically and all traffic shifts to the remaining tunnel — typically within 10–30 seconds depending on your dead-peer-detection timings.
From here you can extend this setup with route filters to control exactly which prefixes are exchanged, or add a second local gateway for full redundancy on both sides.