Day 1: Virtual WAN Hub Provisioning¶
File: terraform/03-vwan/main.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
azurerm = { source = "hashicorp/azurerm", version = "~> 3.85.0" }
}
}
provider "azurerm" { features {} }
data "azurerm_resource_group" "networking" { name = "abhavtech-networking" }
data "azurerm_virtual_network" "prod" {
name = "abhavtech-azure-prod"
resource_group_name = data.azurerm_resource_group.networking.name
}
# Virtual WAN Resource
resource "azurerm_virtual_wan" "main" {
name = "abhavtech-vwan"
resource_group_name = data.azurerm_resource_group.networking.name
location = data.azurerm_resource_group.networking.location
disable_vpn_encryption = false
allow_branch_to_branch_traffic = true
office365_local_breakout_category = "OptimizeAndAllow"
type = "Standard"
}
## Virtual WAN Hub: Central India
resource "azurerm_virtual_hub" "india" {
name = "abhavtech-vwan-hub-india"
resource_group_name = data.azurerm_resource_group.networking.name
location = "centralindia"
virtual_wan_id = azurerm_virtual_wan.main.id
address_prefix = "10.200.0.0/23"
}
## VPN Gateway in Hub (for branch IPsec)
resource "azurerm_vpn_gateway" "india" {
name = "abhavtech-vpn-gw-india"
resource_group_name = data.azurerm_resource_group.networking.name
location = "centralindia"
virtual_hub_id = azurerm_virtual_hub.india.id
scale_unit = 3 # VpnGw3: 1.25 Gbps per tunnel, 10 tunnels max
bgp_settings {
asn = 65515 # Azure auto-assigned ASN
peer_weight = 0
instance_0_bgp_peering_address {
custom_ips = ["10.200.0.254"]
}
}
}
## Connect Prod VNet to Virtual WAN Hub
resource "azurerm_virtual_hub_connection" "prod_vnet" {
name = "prod-vnet-connection"
virtual_hub_id = azurerm_virtual_hub.india.id
remote_virtual_network_id = data.azurerm_virtual_network.prod.id
}
## VPN Sites (one per branch)
resource "azurerm_vpn_site" "bangalore" {
name = "branch-bangalore"
resource_group_name = data.azurerm_resource_group.networking.name
location = "centralindia"
virtual_wan_id = azurerm_virtual_wan.main.id
address_cidrs = ["192.168.50.0/24"]
link {
name = "blr-isr4331-primary"
ip_address = var.bangalore_wan_ip
speed_in_mbps = 100
bgp { asn = 65010; peering_address = "10.200.1.10" }
}
}
resource "azurerm_vpn_site" "delhi" {
name = "branch-delhi"
resource_group_name = data.azurerm_resource_group.networking.name
location = "centralindia"
virtual_wan_id = azurerm_virtual_wan.main.id
address_cidrs = ["192.168.51.0/24"]
link {
name = "del-isr4331-primary"
ip_address = var.delhi_wan_ip
speed_in_mbps = 100
bgp { asn = 65011; peering_address = "10.200.1.14" }
}
}
resource "azurerm_vpn_site" "hyderabad" {
name = "branch-hyderabad"
resource_group_name = data.azurerm_resource_group.networking.name
location = "centralindia"
virtual_wan_id = azurerm_virtual_wan.main.id
address_cidrs = ["192.168.52.0/24"]
link {
name = "hyd-isr1100-primary"
ip_address = var.hyderabad_wan_ip
speed_in_mbps = 50
bgp { asn = 65012; peering_address = "10.200.1.18" }
}
}
## VPN Connections (attach each site to gateway)
resource "azurerm_vpn_gateway_connection" "bangalore" {
name = "conn-bangalore"
resource_group_name = data.azurerm_resource_group.networking.name
vpn_gateway_id = azurerm_vpn_gateway.india.id
remote_vpn_site_id = azurerm_vpn_site.bangalore.id
vpn_link {
name = "bangalore-link"
vpn_site_link_id = azurerm_vpn_site.bangalore.link[0].id
bgp_enabled = true
shared_key = var.bangalore_psk
protocol = "IKEv2"
ipsec_policy {
dh_group = "DHGroup14"
ike_encryption_algorithm = "AES256"
ike_integrity_algorithm = "SHA384"
encryption_algorithm = "AES256"
integrity_algorithm = "SHA256"
pfs_group = "PFS14"
sa_lifetime_seconds = 27000
sa_data_size_kilobytes = 102400000
}
}
}
output "vpn_gateway_public_ips" {
description = "Configure these as tunnel destinations on branch ISR routers"
value = azurerm_vpn_gateway.india.bgp_settings[0].instance_0_bgp_peering_address[0].tunnel_ips
}
Deploy Virtual WAN¶
cd ~/azure-deployment/terraform/03-vwan
terraform init
terraform plan -out=tfplan
terraform apply tfplan
## Get VPN Gateway public IPs (needed for ISR tunnel config)
VWAN_GW_IP1=$(terraform output -json vpn_gateway_public_ips | jq -r '.[0]')
VWAN_GW_IP2=$(terraform output -json vpn_gateway_public_ips | jq -r '.[1]')
echo "VWAN GW IP1: $VWAN_GW_IP1"
echo "VWAN GW IP2: $VWAN_GW_IP2"
Day 2-3: Branch IPsec Configuration¶
Bangalore ISR 4331 (BGP ASN 65010)¶
! ============================================================================
! BANGALORE BRANCH - ISR 4331 TO AZURE VIRTUAL WAN
! ============================================================================
hostname BLR-ISR-01
! IKEv2 Proposal (must match Azure Virtual WAN policy)
crypto ikev2 proposal AZURE-VWAN-PROPOSAL
encryption aes-cbc-256
integrity sha384
group 14
crypto ikev2 policy AZURE-VWAN-POLICY
proposal AZURE-VWAN-PROPOSAL
crypto ikev2 keyring AZURE-VWAN-KEYRING
peer azure-gw1
address <AZURE_VWAN_GW_IP_1>
pre-shared-key <PSK_FROM_AZURE_PORTAL>
peer azure-gw2
address <AZURE_VWAN_GW_IP_2>
pre-shared-key <PSK_FROM_AZURE_PORTAL>
crypto ikev2 profile AZURE-VWAN-PRIMARY
match identity remote address <AZURE_VWAN_GW_IP_1>
identity local address <BLR_WAN_PUBLIC_IP>
authentication remote pre-share
authentication local pre-share
keyring local AZURE-VWAN-KEYRING
lifetime 27000
crypto ikev2 profile AZURE-VWAN-SECONDARY
match identity remote address <AZURE_VWAN_GW_IP_2>
identity local address <BLR_WAN_PUBLIC_IP>
authentication remote pre-share
authentication local pre-share
keyring local AZURE-VWAN-KEYRING
lifetime 27000
crypto ipsec transform-set AZURE-VWAN-TS esp-aes 256 esp-sha-hmac
mode tunnel
crypto ipsec profile AZURE-VWAN-IPSEC-PRIMARY
set transform-set AZURE-VWAN-TS
set ikev2-profile AZURE-VWAN-PRIMARY
set security-association lifetime seconds 27000
set pfs group14
crypto ipsec profile AZURE-VWAN-IPSEC-SECONDARY
set transform-set AZURE-VWAN-TS
set ikev2-profile AZURE-VWAN-SECONDARY
set security-association lifetime seconds 27000
set pfs group14
! Tunnel interfaces
interface Tunnel100
description IPSEC-TO-AZURE-VWAN-PRIMARY
ip address 10.200.1.10 255.255.255.252
ip mtu 1400
ip tcp adjust-mss 1360
tunnel source GigabitEthernet0/0/0
tunnel mode ipsec ipv4
tunnel destination <AZURE_VWAN_GW_IP_1>
tunnel protection ipsec profile AZURE-VWAN-IPSEC-PRIMARY
no shutdown
interface Tunnel101
description IPSEC-TO-AZURE-VWAN-SECONDARY
ip address 10.200.1.22 255.255.255.252
ip mtu 1400
ip tcp adjust-mss 1360
tunnel source GigabitEthernet0/0/0
tunnel mode ipsec ipv4
tunnel destination <AZURE_VWAN_GW_IP_2>
tunnel protection ipsec profile AZURE-VWAN-IPSEC-SECONDARY
no shutdown
! BGP
router bgp 65010
bgp router-id 192.168.50.1
neighbor 10.200.0.254 remote-as 65515
neighbor 10.200.0.254 description AZURE-VWAN-HUB-PRIMARY
neighbor 10.200.0.254 ebgp-multihop 3
neighbor 10.200.0.254 update-source Tunnel100
neighbor 10.200.0.253 remote-as 65515
neighbor 10.200.0.253 description AZURE-VWAN-HUB-SECONDARY
neighbor 10.200.0.253 ebgp-multihop 3
neighbor 10.200.0.253 update-source Tunnel101
address-family ipv4
network 192.168.50.0 mask 255.255.255.0
neighbor 10.200.0.254 activate
neighbor 10.200.0.254 route-map AZURE-VNETS-IN in
neighbor 10.200.0.254 route-map BRANCH-LAN-OUT out
neighbor 10.200.0.254 route-map SET-LOCALPREF-200 in
neighbor 10.200.0.253 activate
neighbor 10.200.0.253 route-map AZURE-VNETS-IN in
neighbor 10.200.0.253 route-map BRANCH-LAN-OUT out
neighbor 10.200.0.253 route-map SET-LOCALPREF-100 in
exit-address-family
! Route-maps
ip prefix-list AZURE-VNETS seq 10 permit 10.100.0.0/16 le 32
ip prefix-list AZURE-VNETS seq 20 permit 10.101.0.0/16 le 32
ip prefix-list AZURE-VNETS seq 999 deny 0.0.0.0/0 le 32
ip prefix-list BANGALORE-LAN seq 10 permit 192.168.50.0/24
ip prefix-list BANGALORE-LAN seq 999 deny 0.0.0.0/0 le 32
route-map AZURE-VNETS-IN permit 10
match ip address prefix-list AZURE-VNETS
route-map AZURE-VNETS-IN deny 999
route-map BRANCH-LAN-OUT permit 10
match ip address prefix-list BANGALORE-LAN
route-map BRANCH-LAN-OUT deny 999
route-map SET-LOCALPREF-200 permit 10
set local-preference 200
route-map SET-LOCALPREF-100 permit 10
set local-preference 100
! Static routes for BGP peer reachability
ip route 10.200.0.254 255.255.255.255 Tunnel100
ip route 10.200.0.253 255.255.255.255 Tunnel101
Apply similar config to Delhi (ASN 65011, subnet 192.168.51.0/24) and all other India branches, adjusting ASN, LAN subnet, and tunnel IPs per branch.