Hosting applications in Azure usually requires some form of connection to the on-premises networks. You could use Point-to-Site dialup or ExpressRoute, but Site-2-Site VPN’s seems the most use technology, and certainly is cheaper than ExpressRoute connection.
But what if you want to use multiple links for failover? What if your local firewall fails or the internet connection itself? Well, that’s why Azure supports MultiSite VPN’s. While it is capable of having two tunnels from on-premises to Azure with preferences, there is no automatic failover support. That means that if tunnel 1 goes down, tunnel 2 is NOT automatically activated. You need to disable tunnel 1 in Azure itself and only THEN tunnel 2 comes up. Which is annoying, but there is another way to fully automate this.. BGP, Border Gateway Protocol.
BGP is widely used in Internet land.. or to be more precise in the routers that make up the internet itself. Routes towards other regions of the wide network are exchanged between the devices and that is how packets are steered from A to B to C to D to E and back again.
Azure supports BGP (link) and on the same link you can read what it is and why you should/could use it within Azure. While my telecom provider only allows me a single external IP address, BGP still could have its advantages. As you might be aware, Virtual Networks in Azure can be extended with new address spaces and new subnets. By using BGP, these new addresses are automatically added to my VPN to my home. I know, it’s not very vital, but it saves me time in configuring the static routes on my router and as soon as my ISP is willing to give me 2 external IP addresses I will be happy to extend this post with multi-vpn connections using BGP. For now, this post is more about how to implement it with a Juniper SRX.
The setup here is as follows:
As you can see the setup is quite simple. On the left the home or “on-premises” network with 172.16.5.0/24 and on Azure inside a VNet two subnets (one for the Gateway, one for the actual VM’s). A VPN tunnel will be connecting both sides.
Azure configuration
So how to configure this in Azure? There is an excellent guide on https://azure.microsoft.com/en-us/documentation/articles/vpn-gateway-bgp-resource-manager-ps/ (note that you only need to create 1 Vnet instead of following the entire guide)
For my purpose (and this article) I had to change a few items, and also used the portal and PowerShell together. I created the VNet in the portal, got the subnet and the GatewaySubnet in there, but created the Gateway through PowerShell.
$RG = "BGP-Test"
$Location = "West US"
$VNetName = "TestVNet1"
$FESubName = "FrontEnd"
$GWSubName = "GatewaySubnet"
$VNetPrefix = "172.16.100.0/22"
$FESubPrefix = "172.16.100.0/24"
$GWSubPrefix = "172.16.102.0/27"
$VNet1ASN = 65010
$GWName = "VNet1GW"
$GWIPName = "VNet1GWIP"
$GWIPconfName = "gwipconf1"
$gwpip = New-AzureRmPublicIpAddress -Name $GWIPName -ResourceGroupName $RG -Location $Location -AllocationMethod Dynamic
$vnet = Get-AzureRmVirtualNetwork -Name $VNetName -ResourceGroupName $RG
$subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -VirtualNetwork $vnet
$gwipconf1 = New-AzureRmVirtualNetworkGatewayIpConfig -Name $GWIPconfName -Subnet $subnet -PublicIpAddress $gwpip
New-AzureRmVirtualNetworkGateway -Name $GWName -ResourceGroupName $RG -Location $Location -IpConfigurations $gwipconf -GatewayType Vpn -VpnType RouteBased -GatewaySku HighPerformance -Asn $VNet1ASN
This basically created the gateway and the return output will give you the BGP peering address:
Note this down, as you will need it in the Juniper configuration.
The next part is to create the connection from Azure side towards the Juniper. In order for the connection to be created, again, use PowerShell where we first create the local network object in Azure that represents my “home” connection:
$LNGName = "Home"
$LNGPrefix = "172.16.5.0/24"
$LNGIP = "94.X.Y.Z"
$LNGASN = 65050
$BGPPeerIP = "172.16.5.1"
$ConnectionStS = "AzureToHome"
New-AzureRmLocalNetworkGateway -Name $LNGName -ResourceGroupName $RG -Location $Location -GatewayIpAddress $LNGIP -AddressPrefix $LNGPrefix -Asn $LNGASN -BgpPeeringAddress $BGPPeerIP
As you can see, within the local network gateway object we already specify the ASN and the BGP peering address that we are going to specify later-on in the Juniper configuration.
Next is the connection itself
$vnet1gw = Get-AzureRmVirtualNetworkGateway -Name $GWName -ResourceGroupName $RG
$lng5gw = Get-AzureRmLocalNetworkGateway -Name $LNGName -ResourceGroupName $RG
New-AzureRmVirtualNetworkGatewayConnection -Name $ConnectionStS -ResourceGroupName $RG -VirtualNetworkGateway1 $vnet1gw -LocalNetworkGateway2 $lng5gw -Location $Location -ConnectionType IPsec -SharedKey 'blabla' -EnableBGP True
Juniper side
Obviously first the tunnel
[security]
ike {
proposal bgp-proposal {
authentication-method pre-shared-keys;
dh-group group2;
authentication-algorithm sha1;
encryption-algorithm aes-256-cbc;
lifetime-seconds 28800;
}
policy bgp-policy {
mode main;
proposals bgp-proposal;
pre-shared-key ascii-text "blabla"; ## SECRET-DATA
}
gateway bgp-gateway {
ike-policy bgp-policy;
address 13.A.B.C;
external-interface pp0.0;
version v2-only;
}
}
ipsec {
proposal bgp-ipsec-proposal {
protocol esp;
authentication-algorithm hmac-sha1-96;
encryption-algorithm aes-256-cbc;
lifetime-seconds 3600;
}
policy bgp-ipsec-policy {
proposals bgp-ipsec-proposal;
}
vpn bgp-ipsec-vpn {
bind-interface st0.0;
ike {
gateway bgp-gateway;
ipsec-policy bgp-ipsec-policy;
}
}
}
flow {
tcp-mss {
ipsec-vpn {
mss 1350;
}
}
}
Secondly the routing
routing-options
static {
route 0.0.0.0/0 {
qualified-next-hop pp0.0 {
metric 1;
}
}
route 172.16.102.30/32 next-hop st0.0;
}
Note that for the routing, we do not include the entire VNET as per regular VPN configuration. We only add the BGP peering address as the target in our static routing entry (with a /32!)
Thirdly the policies to allow traffic
[security policies]
from-zone Internet to-zone Internal {
policy Azure-In {
match {
source-address Azure-Networks-1;
destination-address onprem-networks-1;
application any;
}
then {
permit;
}
}
}
(note; I specified Azure-Networks-1 in this case as 172.16.100.0/22, obviously if more address spaces are added these need to be added to the policy rules too..)
This takes care of the VPN on the Juniper side, but not yet the BGP. In order to setup for BGP the following configuration entries need to be made.
set protocols bgp local-address 172.16.5.1
set protocols bgp group azure type external
set protocols bgp group azure multihop ttl 50
set protocols bgp group azure peer-as 65010
set protocols bgp group azure neighbor 172.16.102.30
Now wait for the configuration to be applied and the BGP to be exchanged. If all is well, outside of the configuration editor, you should be able to issue a show bgp neighbor which should output something like:
Peer: 172.16.102.30+179 AS 65010 Local: 172.16.5.1+54347 AS 65050
Type: External State: Established Flags: <Sync>
Last State: OpenConfirm Last Event: RecvKeepAlive
Last Error: None
Options: <Multihop Preference LocalAddress Ttl PeerAS Refresh>
Local Address: 172.16.5.1 Holdtime: 90 Preference: 170
Number of flaps: 0
Peer ID: 172.16.102.30 Local ID: 172.16.5.1 Active Holdtime: 90
Keepalive Interval: 30 Peer index: 0
BFD: disabled, down
.......
......
RIB State: BGP restart is complete
Send state: in sync
Active prefixes: 1
Received prefixes: 2
Accepted prefixes: 2
Suppressed due to damping: 0
Advertised prefixes: 0
Last traffic (seconds): Received 12 Sent 2 Checked 50
Input messages: Total 153 Updates 1 Refreshes 0 Octets 2940
Output messages: Total 151 Updates 0 Refreshes 0 Octets 2932
Output Queue[0]: 0
When you want to fully validate, type show route and it should list the 172.16.100.0/22 route:
admin@GATEWAY> show route
inet.0: 10 destinations, 11 routes (10 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
……..
172.16.100.0/22 *[BGP/170] 01:08:17, localpref 100, from 172.16.102.30
AS path: 65010 I
> via st0.0
172.16.102.30/32 *[Static/5] 01:34:33
> via st0.0
which concludes the configuration and the validation of the BGP enabled tunnel..