Site-to-Site VPN to Microsoft Azure with BGP

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

ComponentVyOS (On-Premises)Azure
Public IP198.51.100.3203.0.113.2
Private Network10.10.0.0/1610.0.0.0/16
VTI/BGP IP10.10.1.5/3210.0.0.4/32
BGP ASN6449965540
IKE VersionIKEv2IKEv2
Pre-Shared Keych00s3-4-s3cur3-pskch00s3-4-s3cur3-psk
IPsec ModeRoute-Based (VTI)Route-Based

Azure Configuration

1. Create the Virtual Network Gateway

Using the Azure Portal

  1. Go to Virtual Network GatewaysCreate

  2. 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)
  3. Gateway subnet (if not created):

    Subnet name: GatewaySubnet (mandatory name)
    Address range: 10.0.255.0/27
  4. Public IP:

    Public IP address name: pip-vng-vyos
    Public IP type: Basic or Standard
    Assignment: Dynamic or Static
  5. Wait 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.4

3. Create the Local Network Gateway (represents VyOS)

Azure Portal

  1. Local Network GatewaysCreate

  2. 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)
  3. 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.5

4. Create the VPN Connection

Azure Portal

  1. Virtual Network GatewayConnectionsAdd

  2. 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-psk
  3. BGP:

    Enable BGP: Yes
  4. IKE 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-bgp

VyOS 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
save

Verifying 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 sa

2. 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:15

3. 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.10

4. 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 table

Integration 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 Networks

Notes

  1. 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.1
  2. Yandex 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.10
  3. Security 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-azure

VK 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 Networks

Notes

  1. 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.1
  2. VK 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)
  3. 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: down

Solution:

  1. Check network connectivity:
ping 203.0.113.2
# The Azure gateway should respond
  1. 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
  1. 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
  1. 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
commit

Problem: BGP Session Does Not Establish

Symptoms:

show bgp summary
# Neighbor state: Idle or Active

Solution:

  1. Check the IPsec tunnel (it must be UP):
show vpn ipsec sa
  1. Check the static route for the BGP peer:
show ip route 10.0.0.4
# There should be a route via vti1
  1. 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
  1. Ping the Azure BGP peer:
ping 10.0.0.4 interface vti1
  1. Check BGP on Azure:
az network vnet-gateway list-bgp-peer-status \
  --resource-group rg-azure-vpn \
  --name vng-vyos-site

Problem: BGP Established, but No Routes

Symptoms:

show bgp neighbors 10.0.0.4 received-routes
# Empty or few routes

Solution:

  1. Check the advertised routes:
show bgp neighbors 10.0.0.4 advertised-routes
  1. Check the route-map/prefix-list (if configured):
show policy

# Make sure no filters are blocking the routes
  1. 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
  1. Check the BGP network statements:
show configuration commands | grep "protocols bgp.*network"

# Make sure the required networks are being advertised

Problem: High Latency or Packet Loss

Solution:

  1. 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
  1. 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
  1. 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 VpnGw2

Best Practices

Security

  1. Strong Pre-Shared Key:

    # Generate strong PSK
    openssl rand -base64 32
  2. Certificate authentication (alternative to PSK):

    # More secure, but harder to set up
    # Azure supports certificate-based auth
  3. Firewall 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

  1. 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 1360
  2. BGP 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'
  3. 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

  1. VyOS monitoring:

    # Check the status regularly
    show vpn ipsec sa
    show bgp summary
    
    # Logs
    show log vpn
    
    # Traffic stats
    show interfaces vti vti1
  2. Azure 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 1m
  3. Automated 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:

Additional Resources


Tested on: VyOS 1.4 (Sagitta LTS), VyOS 1.5 (Circinus), Azure VPN Gateway (VpnGw1, VpnGw2) Last updated: 2025-10-14

Reviewed by OpenNix LLC · Last updated on