Site-to-Site VPN to Microsoft Azure with BGP
Route-based site-to-site VPN between VyOS and a Microsoft Azure Virtual Network Gateway with dynamic routing via BGP over IKEv2/IPsec.
Scenario Overview
Use Case
Connect an on-premises network (or VyOS running in another cloud) to Microsoft Azure over a secure IPsec tunnel with automatic route exchange via BGP.
Applicability:
- Hybrid cloud deployments (Yandex Cloud ↔ Azure, VK Cloud ↔ Azure)
- On-premises datacenter ↔ Azure
- Multi-cloud architectures
- Disaster recovery scenarios
- Cloud migration (phased approach)
Benefits of Route-Based VPN with BGP
- Dynamic routing: Automatic route exchange via BGP
- Scalability: Easily add new subnets without changing the IPsec config
- Failover: Automatic switchover when redundant tunnels are added
- Flexibility: Support for complex topologies (Hub-and-Spoke, mesh)
Network Topology
┌─────────────────────────────────────────────────────────────────┐
│ Internet / Public WAN │
└──────────────────────────┬──────────────────────────────────────┘
│
┌────────────┴────────────┐
│ │
┌───────▼────────┐ ┌──────▼────────────┐
│ VyOS Router │ │ Azure VNet GW │
│ │ │ │
│ Public IP: │ │ Public IP: │
│ 198.51.100.3 │ │ 203.0.113.2 │
│ │ │ │
│ VTI: 10.10.1.5 │◄──────►│ BGP: 10.0.0.4 │
│ AS 64499 │ IPsec │ AS 65540 │
└───────┬────────┘ BGP └──────┬────────────┘
│ │
┌───────▼────────┐ ┌──────▼────────────┐
│ On-Premises │ │ Azure VNet │
│ Network │ │ │
│ 10.10.0.0/16 │ │ 10.0.0.0/16 │
│ │ │ │
│ LAN: eth1 │ │ Subnet: │
│ 10.10.0.5 │ │ 10.0.0.0/24 │
└────────────────┘ └───────────────────┘Configuration Parameters
| Component | VyOS (On-Premises) | Azure |
|---|---|---|
| Public IP | 198.51.100.3 | 203.0.113.2 |
| Private Network | 10.10.0.0/16 | 10.0.0.0/16 |
| VTI/BGP IP | 10.10.1.5/32 | 10.0.0.4/32 |
| BGP ASN | 64499 | 65540 |
| IKE Version | IKEv2 | IKEv2 |
| Pre-Shared Key | ch00s3-4-s3cur3-psk | ch00s3-4-s3cur3-psk |
| IPsec Mode | Route-Based (VTI) | Route-Based |
Azure Configuration
1. Create the Virtual Network Gateway
Using the Azure Portal
Go to Virtual Network Gateways → Create
Basics:
Resource Group: rg-azure-vpn Name: vng-vyos-site Region: East US Gateway type: VPN VPN type: Route-based SKU: VpnGw1 (or higher for production) Virtual network: vnet-azure-main (10.0.0.0/16)Gateway subnet (if not created):
Subnet name: GatewaySubnet (mandatory name) Address range: 10.0.255.0/27Public IP:
Public IP address name: pip-vng-vyos Public IP type: Basic or Standard Assignment: Dynamic or StaticWait for deployment (~30-45 minutes)
Using the Azure CLI
# Create the Resource Group
az group create --name rg-azure-vpn --location eastus
# Create the Virtual Network
az network vnet create \
--resource-group rg-azure-vpn \
--name vnet-azure-main \
--address-prefix 10.0.0.0/16 \
--subnet-name subnet-main \
--subnet-prefix 10.0.0.0/24
# Create the Gateway Subnet
az network vnet subnet create \
--resource-group rg-azure-vpn \
--vnet-name vnet-azure-main \
--name GatewaySubnet \
--address-prefix 10.0.255.0/27
# Create the Public IP
az network public-ip create \
--resource-group rg-azure-vpn \
--name pip-vng-vyos \
--allocation-method Static \
--sku Standard
# Create the Virtual Network Gateway
az network vnet-gateway create \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--public-ip-address pip-vng-vyos \
--vnet vnet-azure-main \
--gateway-type Vpn \
--vpn-type RouteBased \
--sku VpnGw1 \
--bgp-asn 65540 \
--no-wait
# Check the provisioning status
az network vnet-gateway show \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--query "provisioningState"2. Get the Azure BGP IP and Public IP
# Get the Public IP
az network public-ip show \
--resource-group rg-azure-vpn \
--name pip-vng-vyos \
--query "ipAddress" -o tsv
# Output: 203.0.113.2
# Get the BGP Peer IP
az network vnet-gateway show \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--query "bgpSettings.bgpPeeringAddress" -o tsv
# Output: 10.0.0.43. Create the Local Network Gateway (represents VyOS)
Azure Portal
Local Network Gateways → Create
Configuration:
Resource Group: rg-azure-vpn Name: lng-vyos-onprem Endpoint: IP address IP address: 198.51.100.3 (VyOS public IP) Address Space: 10.10.0.0/16 (on-premises network)BGP Settings:
Configure BGP settings: Yes Autonomous system number (ASN): 64499 BGP peer IP address: 10.10.1.5
Azure CLI
az network local-gateway create \
--resource-group rg-azure-vpn \
--name lng-vyos-onprem \
--gateway-ip-address 198.51.100.3 \
--address-prefixes 10.10.0.0/16 \
--bgp-asn 64499 \
--bgp-peering-address 10.10.1.54. Create the VPN Connection
Azure Portal
Virtual Network Gateway → Connections → Add
Configuration:
Name: conn-vyos-azure Connection type: Site-to-site (IPsec) Virtual network gateway: vng-vyos-site Local network gateway: lng-vyos-onprem Shared key (PSK): ch00s3-4-s3cur3-pskBGP:
Enable BGP: YesIKE Protocol:
IKE Protocol: IKEv2
Azure CLI
az network vpn-connection create \
--resource-group rg-azure-vpn \
--name conn-vyos-azure \
--vnet-gateway1 vng-vyos-site \
--local-gateway2 lng-vyos-onprem \
--shared-key "ch00s3-4-s3cur3-psk" \
--enable-bgpVyOS Configuration
Complete Working Configuration
configure
# System settings
set system host-name vyos-azure-vpn
set system time-zone Europe/Moscow
# WAN interface (must have a public IP or NAT)
set interfaces ethernet eth0 address '198.51.100.3/24'
set interfaces ethernet eth0 description 'WAN'
# LAN interface (on-premises network)
set interfaces ethernet eth1 address '10.10.0.5/16'
set interfaces ethernet eth1 description 'LAN'
# ===== IPsec Configuration =====
# IKE Group (Phase 1)
set vpn ipsec ike-group AZURE lifetime '28800'
set vpn ipsec ike-group AZURE proposal 1 encryption 'aes256'
set vpn ipsec ike-group AZURE proposal 1 hash 'sha256'
set vpn ipsec ike-group AZURE proposal 1 dh-group '14'
set vpn ipsec ike-group AZURE key-exchange 'ikev2'
set vpn ipsec ike-group AZURE dead-peer-detection action 'restart'
set vpn ipsec ike-group AZURE dead-peer-detection interval '30'
set vpn ipsec ike-group AZURE dead-peer-detection timeout '120'
# ESP Group (Phase 2)
set vpn ipsec esp-group AZURE lifetime '3600'
set vpn ipsec esp-group AZURE mode 'tunnel'
set vpn ipsec esp-group AZURE proposal 1 encryption 'aes256'
set vpn ipsec esp-group AZURE proposal 1 hash 'sha256'
set vpn ipsec esp-group AZURE pfs 'dh-group14'
# VTI Interface (Virtual Tunnel Interface)
set interfaces vti vti1 address '10.10.1.5/32'
set interfaces vti vti1 description 'Azure VPN Tunnel'
set interfaces vti vti1 ip adjust-mss '1350'
set interfaces vti vti1 ip disable-forwarding
# IPsec Authentication
set vpn ipsec authentication psk azure id '198.51.100.3'
set vpn ipsec authentication psk azure id '203.0.113.2'
set vpn ipsec authentication psk azure secret 'ch00s3-4-s3cur3-psk'
# IPsec Site-to-Site Peer
set vpn ipsec site-to-site peer 203.0.113.2 description 'Azure VNet Gateway'
set vpn ipsec site-to-site peer 203.0.113.2 authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer 203.0.113.2 authentication pre-shared-secret 'ch00s3-4-s3cur3-psk'
set vpn ipsec site-to-site peer 203.0.113.2 connection-type 'respond'
set vpn ipsec site-to-site peer 203.0.113.2 ike-group 'AZURE'
set vpn ipsec site-to-site peer 203.0.113.2 ikev2-reauth 'yes'
set vpn ipsec site-to-site peer 203.0.113.2 local-address '198.51.100.3'
set vpn ipsec site-to-site peer 203.0.113.2 vti bind 'vti1'
set vpn ipsec site-to-site peer 203.0.113.2 vti esp-group 'AZURE'
# ===== BGP Configuration =====
# BGP Router
set protocols bgp system-as '64499'
set protocols bgp parameters router-id '10.10.0.5'
set protocols bgp parameters log-neighbor-changes
# BGP Neighbor (Azure VNet Gateway)
set protocols bgp neighbor 10.0.0.4 description 'Azure VNet Gateway BGP'
set protocols bgp neighbor 10.0.0.4 remote-as '65540'
set protocols bgp neighbor 10.0.0.4 address-family ipv4-unicast
set protocols bgp neighbor 10.0.0.4 address-family ipv4-unicast soft-reconfiguration inbound
set protocols bgp neighbor 10.0.0.4 ebgp-multihop '2'
set protocols bgp neighbor 10.0.0.4 update-source 'vti1'
set protocols bgp neighbor 10.0.0.4 timers holdtime '30'
set protocols bgp neighbor 10.0.0.4 timers keepalive '10'
# Advertise the local network to Azure
set protocols bgp address-family ipv4-unicast network '10.10.0.0/16'
# Static route for the Azure BGP peer (via VTI)
set protocols static route 10.0.0.4/32 interface vti1
# ===== NAT Configuration (if required) =====
# Exclude VPN traffic from NAT
set nat source rule 10 outbound-interface name 'eth0'
set nat source rule 10 source address '10.10.0.0/16'
set nat source rule 10 destination address '10.0.0.0/16'
set nat source rule 10 exclude
# NAT for the rest of the internet traffic
set nat source rule 100 outbound-interface name 'eth0'
set nat source rule 100 source address '10.10.0.0/16'
set nat source rule 100 translation address 'masquerade'
# ===== Firewall (optional, but recommended) =====
# Allow IPsec on the WAN
set firewall name WAN_LOCAL default-action 'drop'
set firewall name WAN_LOCAL rule 10 action 'accept'
set firewall name WAN_LOCAL rule 10 state established
set firewall name WAN_LOCAL rule 10 state related
set firewall name WAN_LOCAL rule 20 action 'accept'
set firewall name WAN_LOCAL rule 20 protocol 'udp'
set firewall name WAN_LOCAL rule 20 destination port '500'
set firewall name WAN_LOCAL rule 20 description 'IKE'
set firewall name WAN_LOCAL rule 21 action 'accept'
set firewall name WAN_LOCAL rule 21 protocol 'udp'
set firewall name WAN_LOCAL rule 21 destination port '4500'
set firewall name WAN_LOCAL rule 21 description 'NAT-T'
set firewall name WAN_LOCAL rule 22 action 'accept'
set firewall name WAN_LOCAL rule 22 protocol 'esp'
set firewall name WAN_LOCAL rule 22 description 'ESP'
set firewall name WAN_LOCAL rule 30 action 'accept'
set firewall name WAN_LOCAL rule 30 protocol 'icmp'
set interfaces ethernet eth0 firewall local name 'WAN_LOCAL'
commit
saveVerifying the Configuration
1. Verify the IPsec Tunnel
# Check the IPsec status
show vpn ipsec sa
# Expected output:
# Connection State Uptime Bytes In/Out
# peer-203.0.113.2 up 00h05m22s 0.0 B/0.0 B
# vti1 up 00h05m22s 0.0 B/0.0 B
# Detailed information
show vpn ipsec sa detail
# Check the IKE SA
show vpn ike sa2. Verify BGP
# Check the BGP neighbors
show bgp summary
# Output should show:
# Neighbor V AS MsgRcvd MsgSent Up/Down State
# 10.0.0.4 4 65540 45 47 00:21:32 Established
# Check the routes received from Azure
show bgp neighbors 10.0.0.4 received-routes
# Check the routes advertised to Azure
show bgp neighbors 10.0.0.4 advertised-routes
# Check the routing table
show ip route
# There should be routes via vti1:
# B>* 10.0.0.0/16 [20/0] via 10.0.0.4, vti1, weight 1, 00:20:153. Verify Connectivity
# Ping the Azure BGP peer via the VTI
ping 10.0.0.4 source-address 10.10.1.5
# Ping an Azure VM (for example, 10.0.0.10)
ping 10.0.0.10 source-address 10.10.0.5
# Traceroute
traceroute 10.0.0.104. Verify on the Azure Side
# Azure CLI - check the connection status
az network vpn-connection show \
--resource-group rg-azure-vpn \
--name conn-vyos-azure \
--query "connectionStatus"
# Output: Connected
# Check the BGP peers
az network vnet-gateway list-bgp-peer-status \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--query "value[].{Peer:neighbor,AS:asn,State:state,RoutesReceived:routesReceived}"
# Check the learned routes
az network vnet-gateway list-learned-routes \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--query "value[].{Network:network,NextHop:nextHop,Origin:origin}" -o tableIntegration with Cloud Platforms
Yandex Cloud as the On-Premises Side
Topology
Azure VNet (10.0.0.0/16)
│
│ IPsec + BGP
│
VyOS in Yandex Cloud (10.128.0.0/24)
│
Yandex Cloud VPC NetworksNotes
VyOS VM in Yandex Cloud:
# Public IP from Yandex Cloud # Elastic IP or NAT Gateway # The WAN interface receives an address from a Yandex Cloud subnet set interfaces ethernet eth0 address '10.128.0.10/24' set interfaces ethernet eth0 description 'Yandex Cloud WAN' # Static route for the default gateway set protocols static route 0.0.0.0/0 next-hop 10.128.0.1Yandex Cloud routing:
# Add a static route to the Yandex Cloud routing table # Destination: 10.0.0.0/16 (Azure) # Next hop: 10.128.0.10 (VyOS internal IP) # Using the yc CLI yc vpc route-table create \ --name azure-routes \ --network-name yc-network \ --route destination=10.0.0.0/16,next-hop=10.128.0.10Security Groups:
# Allow IPsec on the VyOS VM # Inbound rules: # - UDP 500 (IKE) # - UDP 4500 (NAT-T) # - Protocol 50 (ESP)
Yandex Cloud CLI Commands
# Create a VM for VyOS
yc compute instance create \
--name vyos-azure-gw \
--zone ru-central1-a \
--network-interface subnet-name=default-ru-central1-a,nat-ip-version=ipv4 \
--create-boot-disk image-folder-id=standard-images,image-family=vyos \
--ssh-key ~/.ssh/id_rsa.pub
# Get the public IP
yc compute instance get vyos-azure-gw --format json | jq -r '.network_interfaces[0].primary_v4_address.one_to_one_nat.address'
# Create a static route for the Azure network
yc vpc route-table create \
--name route-to-azure \
--network-name default \
--route destination=10.0.0.0/16,next-hop=10.128.0.10
# Apply the route table to the subnet
yc vpc subnet update default-ru-central1-a \
--route-table-name route-to-azureVK Cloud as the On-Premises Side
Topology
Azure VNet (10.0.0.0/16)
│
│ IPsec + BGP
│
VyOS in VK Cloud (10.0.10.0/24)
│
VK Cloud Private NetworksNotes
VyOS VM in VK Cloud:
# Floating IP from VK Cloud # WAN interface set interfaces ethernet eth0 address '10.0.10.10/24' set interfaces ethernet eth0 description 'VK Cloud WAN' # Default route set protocols static route 0.0.0.0/0 next-hop 10.0.10.1VK Cloud routing:
- Add a static route through the VK Cloud portal
- Destination: 10.0.0.0/16
- Next hop: 10.0.10.10 (VyOS IP)
Security Groups:
- Allow UDP 500, 4500 and the ESP protocol
Troubleshooting
Problem: IPsec Tunnel Does Not Come Up
Symptoms:
show vpn ipsec sa
# Connection state: downSolution:
- Check network connectivity:
ping 203.0.113.2
# The Azure gateway should respond- Check the firewall rules:
# Make sure UDP 500, 4500 and ESP are allowed
show firewall name WAN_LOCAL
# Check the Azure NSG (Network Security Group)
az network nsg rule list \
--resource-group rg-azure-vpn \
--nsg-name nsg-vnet-main \
--query "[].{Name:name,Port:destinationPortRange,Protocol:protocol}" -o table- Check the Pre-Shared Key:
# VyOS
show vpn ipsec authentication psk
# Azure - via the portal or CLI
az network vpn-connection shared-key show \
--resource-group rg-azure-vpn \
--connection-name conn-vyos-azure- Check the logs:
# VyOS
show log vpn ipsec
# Enable debug (temporarily)
set vpn ipsec logging log-modes ike
set vpn ipsec logging log-modes esp
set vpn ipsec logging log-level 2
commit
# Disable it after troubleshooting
delete vpn ipsec logging
commitProblem: BGP Session Does Not Establish
Symptoms:
show bgp summary
# Neighbor state: Idle or ActiveSolution:
- Check the IPsec tunnel (it must be UP):
show vpn ipsec sa- Check the static route for the BGP peer:
show ip route 10.0.0.4
# There should be a route via vti1- Check the BGP configuration:
show configuration commands | grep bgp
# Confirm the following are correct:
# - remote-as (Azure = 65540)
# - neighbor IP (10.0.0.4)
# - update-source vti1
# - ebgp-multihop 2- Ping the Azure BGP peer:
ping 10.0.0.4 interface vti1- Check BGP on Azure:
az network vnet-gateway list-bgp-peer-status \
--resource-group rg-azure-vpn \
--name vng-vyos-siteProblem: BGP Established, but No Routes
Symptoms:
show bgp neighbors 10.0.0.4 received-routes
# Empty or few routesSolution:
- Check the advertised routes:
show bgp neighbors 10.0.0.4 advertised-routes- Check the route-map/prefix-list (if configured):
show policy
# Make sure no filters are blocking the routes- Check the Azure routes:
az network vnet-gateway list-learned-routes \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--query "value[].{Network:network,NextHop:nextHop,Origin:origin}" -o table- Check the BGP network statements:
show configuration commands | grep "protocols bgp.*network"
# Make sure the required networks are being advertisedProblem: High Latency or Packet Loss
Solution:
- Check the MTU:
# VyOS - should be 1350 or less on the VTI
show interfaces vti vti1
# If it needs to be changed
set interfaces vti vti1 mtu 1350
set interfaces vti vti1 ip adjust-mss 1310
commit- Check the throughput:
# iperf3 test through the tunnel
# On the Azure VM
iperf3 -s
# On a VyOS LAN client
iperf3 -c 10.0.0.10 -t 60- Check the Azure Gateway SKU:
az network vnet-gateway show \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--query "sku.name"
# Upgrade to higher SKU if needed (VpnGw2, VpnGw3)
az network vnet-gateway update \
--resource-group rg-azure-vpn \
--name vng-vyos-site \
--sku VpnGw2Best Practices
Security
Strong Pre-Shared Key:
# Generate strong PSK openssl rand -base64 32Certificate authentication (alternative to PSK):
# More secure, but harder to set up # Azure supports certificate-based authFirewall rules:
# Minimal access over the VPN set firewall name VPN_IN default-action 'drop' set firewall name VPN_IN rule 10 action 'accept' set firewall name VPN_IN rule 10 state established set firewall name VPN_IN rule 10 state related # Add only the required rules
Performance
MTU optimization:
# The VTI MTU must account for IPsec overhead # Ethernet MTU (1500) - IPsec overhead (~80) = 1420 # Recommended: 1350-1400 set interfaces vti vti1 mtu 1400 set interfaces vti vti1 ip adjust-mss 1360BGP timers:
# Faster failover detection set protocols bgp neighbor 10.0.0.4 timers holdtime '30' set protocols bgp neighbor 10.0.0.4 timers keepalive '10'Azure Gateway SKU:
- VpnGw1: Up to 650 Mbps, 30 tunnels
- VpnGw2: Up to 1 Gbps, 30 tunnels
- VpnGw3: Up to 1.25 Gbps, 30 tunnels
Monitoring
VyOS monitoring:
# Check the status regularly show vpn ipsec sa show bgp summary # Logs show log vpn # Traffic stats show interfaces vti vti1Azure monitoring:
# Azure Monitor metrics # - VPN Gateway bandwidth # - Tunnel ingress/egress bytes # - BGP peer status # Alerts on disconnect az monitor metrics alert create \ --name vpn-disconnect-alert \ --resource-group rg-azure-vpn \ --scopes $(az network vpn-connection show -g rg-azure-vpn -n conn-vyos-azure --query id -o tsv) \ --condition "avg tunnel_connectivity_status < 1" \ --window-size 5m \ --evaluation-frequency 1mAutomated testing:
# Ping test script #!/bin/bash while true; do ping -c 1 10.0.0.10 > /dev/null if [ $? -ne 0 ]; then echo "$(date): VPN connectivity lost!" | mail -s "VPN Alert" admin@example.com fi sleep 60 done
High Availability
For production, a redundant setup is recommended:
- Redundant VPN to Azure - Dual tunnel configuration
Additional Resources
- Azure VPN Gateway Documentation
- VyOS IPsec Documentation
- BGP Configuration Guide
- Redundant Azure VPN Setup
Tested on: VyOS 1.4 (Sagitta LTS), VyOS 1.5 (Circinus), Azure VPN Gateway (VpnGw1, VpnGw2) Last updated: 2025-10-14