Fun with Azure VPN
Published Sep 06 2022 04:09 PM 7,445 Views
Microsoft

Introduction

 

Hi folks! My name is Felipe Binotto, Cloud Solution Architect, based in Australia.

I decided to make this post for a couple reasons. The first reason is to demonstrate how you can quickly build a hub between your own lab and your internet devices using Azure and how easy it is. No more port forwarding in your router, public IP addresses in your VMs, everything will route through the Azure gateway, and you will get an any-to-any type of connectivity. The second reason is to demonstrate some important concepts such as:

  • Site-to-Site VPN
  • Point-to-Site VPN
  • BGP
  • Azure AD authentication for VPN

Note that everything I will demonstrate here can also be done using Azure vWAN. However, this is cheaper and fit for lab and demonstration purposes.

The following is the architecture overview of what we are trying to achieve.

fbinotto_0-1662504725093.png

Pre-requisites

 

The following are the prerequisites which I will not cover in this post, and you should already have them in place before you start:

  • Azure subscription
  • On-premises Windows Server 2016 or higher VM with 2 network cards and internet access (the 2 network cards are only required if you want to route traffic to different subnets otherwise 1 network card should do)
  • Enable Azure AD authentication on the VPN gateway. Instructions are documented HERE. This will create a new Enterprise Application in your Azure tenant

High-Level Steps

 

The following are the high-level steps on what we will do and the order we will do it:

 

  • Install required modules
  • Connect to Azure
  • Create a Resource Group
  • Create VNet and subnets
  • Create a Local Network Gateway
  • Create a Virtual Network Gateway
  • Create a Connection
  • Set up the on-premises VM as a router
  • Create a Site-to-Site interface
  • Set up BGP Router
  • Configure BGP Peering
  • Start the VPN connection
  • Download the P2S VPN configuration from Azure
  • Create a VM for testing
  • Demonstrate any-to-any connectivity

 

Now we will start to look at how you can fully automate that deployment. The full script can be downloaded from HERE but I will break it down in this post, so you understand what is happening. You must run this script from your on-premises VM if you don't want to make any modifications. However, once you understand it, you should be able to split the commands and play around.

Note: in the scripts I defined the Subscription Name and Tenant Id as parameters. Here I will use them as variables.

Note: disable Internet Enhanced Security Configuration (IEESC) for the administrator or you will have issues when authenticating to Azure. You can do that from Server Manager or using the following function. Restart your PowerShell session after running it.

 

 

 

function Disable-IEESC {
    $AdminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\ `
    Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}"
    Set-ItemProperty -Path $AdminKey -Name "IsInstalled" -Value 0
    Stop-Process -Name Explorer
}

 

 

 

Getting Started

 

OK, let's get started. Let's start with the basics. The following lines of code will:

 

  1. Install the required modules
  2. Set some variables which I will explain when we are looking at the commands which use them. You are welcome to change their values as long as you do what you’re doing. You must provide values for $subName and $tenantId
  3. Prompt you for credentials to connect to your Azure subscription

 

 

 

# Install required modules
Install-PackageProvider -Name NuGet -Force
Install-Module Az.Resources,Az.Compute,Az.Network -Force -Confirm:$false

# Set variables
$subName                = ''
$tenantId               = ''
$rgName                 = 'Connectivity'
$location               = 'AustraliaEast'
$vnetName               = 'Global-Connect'
$subnetName             = 'IaaS'
$subnetPrefix           = '172.16.0.0/24'
$gatewaySubnetPrefix    = '172.16.255.0/27'
$myPIP                  = (Invoke-WebRequest myexternalip.com/raw).content
$vnetAddressRange       = '172.16.0.0/16'
$vpnAddressPool         = '172.17.0.0/24'
$sharedKey              = 'mySuperS3cr3t123'
$vmPassword             = 'myC0mplexP@ssword'
$localASN               = 64512
$remoteASN              = 65515

# Connect to Azure subscription
Connect-AzAccount -Subscription $subName

 

 

 

Next, we will start creating the foundation resources in this order:

 

  1. Create Resource Group
  2. Define Azure subnets
  3. Create VNet

 

 

 

# Create Resource Group
$rg = @{
    Name = $rgName
    Location = $location
}
New-AzResourceGroup @rg

# Define subnets
$subnet1 = New-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' `
-AddressPrefix $gatewaySubnetPrefix
$subnet2 = New-AzVirtualNetworkSubnetConfig -Name $subnetName `
-AddressPrefix $subnetPrefix

# Create Virtual Network
$vnet = New-AzVirtualNetwork -Name $vnetName -ResourceGroupName $rgName `
-Location $location -AddressPrefix $vnetAddressRange -Subnet $subnet1, $subnet2

 

 

 

So far so good, nothing special.

Now we are going to create the Local Network Gateway. This resource represents your on-premises router configuration. Note how we are not specifying our on-premises subnets. This is because they will be known to Azure via BGP peer route exchange.

 

 

 

# Create Local Network Gateway
$localIP = (Get-NetIPAddress | Where-Object {$_.InterfaceAlias -eq 'Ethernet' `
-and $_.AddressFamily -eq 'ipv4'}).IpAddress
$localGW = New-AzLocalNetworkGateway -Name HomeLab -ResourceGroupName $rgName `
-Location $location -GatewayIpAddress $myPIP -Asn $localASN `
-BgpPeeringAddress $localIP

 

 

 

Let's break down the important parameters being used in this command:

 

  • GatewayIpAddress: this is your on-premises public IP address. Notice that when we define the variables in the beginning, we are dynamically retrieving it using a HTTP request
  • Asn: ASN stands for Autonomous System Number. This is key for BGP routing. ASNs are assigned to organisations but if you don't have one like I don't, you can use one from the private range 64512 - 65534
  • BgpPeeringAddress: this is your local IP address used for BGP. BGP peers exchange routing information between them via BGP sessions. We will use the IP address of your first Ethernet device. You can also use APIPA addresses. By the way, BGP stands for Border Gateway Protocol

Next, we create the Virtual Network Gateway. This is the Router representation in the Azure side.

 

 

 

# Create Virtual Network Gateway
$gwpip = New-AzPublicIpAddress -Name "$vnetName-GWIP" -ResourceGroupName $rgName `
-Location $location -AllocationMethod Dynamic
$vnet = Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $rgName
$subnet = Get-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' -VirtualNetwork $vnet
$gwipconfig = New-AzVirtualNetworkGatewayIpConfig -Name gwipconfig1 -SubnetId $subnet.Id `
-PublicIpAddressId $gwpip.Id
$vnetGW = New-AzVirtualNetworkGateway -Name "$vnetName-GW" -ResourceGroupName $rgName `
-Location $location -IpConfigurations $gwipconfig -GatewayType Vpn -EnableBGP $true `
-VpnType RouteBased -GatewaySku VpnGw1 -Asn $remoteASN `
-VpnClientProtocol OpenVPN -VpnClientAddressPool $vpnAddressPool `
-AadTenantUri "https://login.microsoftonline.com/$tenantId" `
-AadIssuerUri "https://sts.windows.net/$tenantId/" `
-AadAudienceId '41b23e61-6c1e-4545-b367-cd054e0ed4b4'

 

 

 

Let's focus on the creation of the Virtual Network Gateway because there is where the important bits are. The following is the breakdown of the important parameters being used in this command:

 

  • GatewayType: here we are specifying this will be a Site-to-Site VPN gateway as opposed to an Express Route gateway
  • EnableBGP: here we specify we will be using BGP
  • VpnType: RouteBased as PolicyBased doesn't support P2S or BGP
  • GatewaySku: you cannot use the Basic SKU as it doesn't support the OpenVPN or IKEv2 protocols for Azure AD authentication as well as BGP
  • Asn: this is the ASN in the Azure side
  • VpnClientProtocol: we are going to use OpenVPN as it uses TLS and can penetrate firewalls, and it is the protocol that supports most Operating Systems such as Windows, Linux, MacOS, iOS and Android
  • VpnClientAddressPool: this is the pool of addresses that will be used by the VPN clients
  • AadTenantUri: this is the URI which contains your tenant details

 

Next, let's create a connection between our on-prem router and the Azure VPN gateway. Note that at this point the connection won't be established as we haven't yet configured the on-prem router.

 

 

 

# Create Virtual Network Gateway Connection
New-AzVirtualNetworkGatewayConnection -Name "$($vnetGW.Name)-$($localGW.Name)" 
-ResourceGroupName $rgName -Location $location -VirtualNetworkGateway1 $vnetGW 
-LocalNetworkGateway2 $localGW -ConnectionType IPsec -RoutingWeight 10 `
-SharedKey $sharedKey -EnableBgp $true

 

 

 

Everything above is self-explanatory, just worth mentioning that we are enabling BGP in the connection.

Now it is time to configure the local server. We first install the required Windows Features and then install site-site VPN and BGP Routing. The script sleeps for 3 seconds to allow the service to start before we run the next command.

 

 

 

# Install the required Windows Features and Install Remote Access
Install-WindowsFeature -Name RemoteAccess, Routing, RSAT, RSAT-Role-Tools, `
RSAT-RemoteAccess, RSAT-RemoteAccess-PowerShell
Install-RemoteAccess -VpnType VpnS2S
Start-Sleep 3

 

 

 

Once we have those prerequisites in place, we can create the S2S connection from the on-premises side. Remember we have already created one in Azure, and it is waiting for a connection from the other side.

 

 

 

# Create S2S Connection
$gwpip = Get-AzPublicIpAddress -Name "$vnetName-GWIP" -ResourceGroupName $rgName
Add-VpnS2SInterface -Name 'Azure' $gwpip.IpAddress -Protocol IKEv2 `
-AuthenticationMethod PSKOnly -SharedSecret $sharedKey `
-IPv4Subnet @("$($vnetAddressRange):100" ,"$($vpnAddressPool):100")

 

 

 

Let's look at the important parameters from the command above:

 

  • $gwpip.IpAddress: this is the public IP address of the Azure VPN Gateway
  • IPv4Subnet: these are the Azure subnets which will be routed through that interface

 

Now it is time for the on-prem BGP configuration. We first created a BPG Router followed by a BGP Peer.

 

 

 

# Create BGP Router and Peer
Add-BgpRouter -BgpIdentifier $localIP -LocalASN $localASN
Add-BgpPeer -Name AzureS2S -LocalIPAddress $localIP `
-PeerIPAddress $($vnetGW.BgpSettings.BgpPeeringAddress) `
-LocalASN $localASN -PeerASN $remoteASN -PeeringMode Automatic

 

 

 

Let's look at the important parameters from the command above:

 

  • BgpIdentifier: this is the local on-prem IP, the same we have configured as the BGP Peer in the Azure Local Network Gateway
  • LocalASN: this is the on-prem ASN, the same we have configured as the BGP Peer in the Azure Local Network Gateway
  • LocalIPAddress: this is the local on-prem IP, the same we have configured as the BGP Peer in the Azure Local Network Gateway
  • PeerIPAddress: this is the Azure BGP Peering address which we retrieved from the Virtual Network Gateway
  • RemoteASN: this is the Azure ASN that we set when creating the Virtual Network Gateway

 

And finally, we can establish the connection.

 

 

 

Connect-VpnS2SInterface -Name 'Azure'

 

 

 

You can run the following commands to check everything is working:

 

 

 

Get-VpnS2SInterface

 

 

 

The output will be like the following:

 

fbinotto_1-1662505126636.png

 

 

 

Get-BgpPeer

 

 

 

The output will be like the following:

 

fbinotto_2-1662505168481.png

 

Now let's deploy an Azure VM so we can test connectivity between your router and the Azure VM.

 

 

 

# Deploy Azure VM
$vmAdminUser = "LocalAdminUser"
$vmSecurePassword = ConvertTo-SecureString $vmPassword -AsPlainText -Force
$nic = New-AzNetworkInterface -Name 'VM01-nic' -ResourceGroupName $rgName `
-Location $location -SubnetId $vnet.Subnets[1].Id
$credential = New-Object System.Management.Automation.PSCredential `
($vmAdminUser, $vmSecurePassword)
$vm = New-AzVMConfig -VMName 'VM01' -VMSize 'Standard_DS1_v2'
$vm = Set-AzVMOperatingSystem -VM $vm -Windows -ComputerName 'VM01' `
-Credential $credential -ProvisionVMAgent -EnableAutoUpdate
$vm = Add-AzVMNetworkInterface -VM $vm -Id $nic.Id
$vm = Set-AzVMSourceImage -VM $vm -PublisherName 'MicrosoftWindowsServer' `
-Offer 'WindowsServer' -Skus '2016-Datacenter' -Version latest

 

 

 

From the router VM you should be able to RDP to the Azure VM and vice-versa.

From the router VM:

 

fbinotto_3-1662505228729.png

 

From the Azure VM (make sure RDP is enabled in your router VM):

 

fbinotto_4-1662505246408.png

 

Cool, S2S is working. Now we need to download and configure the Azure VPN client to test P2S using Azure Authentication. First let's download the configuration file using our current authenticated session on the server.

 

 

 

# Downloads VPN Client Config
$vpnClient = New-AzVpnClientConfiguration -ResourceGroupName Connectivity `
-ResourceName $vnetGW.Name
Invoke-WebRequest -Uri $vpnClient.VpnProfileSASUrl -OutFile .\vpnclientconfig.zip

 

 

 

Note that a ZIP file has been downloaded to the current directory.

Next you need to download the Azure VPN client from HERE. Install it on a desktop, laptop or any device which is not connected to the router you have just configured. Copy and extract the ZIP file to this device.

We can now configure the VPN Client as follows:

 

fbinotto_5-1662505282257.png

fbinotto_0-1662505766164.png

 

fbinotto_9-1662505313503.png

 

And finally, you should be able to connect using your Azure AD credentials (Conditional Access and MFA will apply if applicable).

You can also see you got an IP from the pool we have configured before and you got the default routes.

 

fbinotto_10-1662505331491.png

 

Now from your internet VPN client device you should be able to RDP to both the Router and the Azure VM. But what if you want to route to other devices on-premises which are in different subnets?

No problem. We just need to advertise the new routes and the BGP Router will let Azure know about them. In this example, I have a second network card (Ethernet 2) which routes traffic to the 10.0.2.0/24 subnet. So, we can advertise the route with the following command.

 

 

 

# Add custom route
Add-BgpCustomRoute -Interface "Ethernet 2" -Network 10.0.2.0/24

 

 

 

Once you reconnect the VPN, you will notice you have new routes as per below.

 

fbinotto_11-1662505363267.png

 

You have the 10.0.2.0/24 route, and you also get the gateway (10.0.2.45/32) and broadcast (10.0.2.255/32) addresses.

From this point you can RDP from any-to-any if you have RDP enabled.

Conclusion

 

How cool is that? I just love to be able to connect to any of my lab resources as well as my Azure resources from a single place and completely secure! Not only that, but as a bonus you get connectivity from your lab to Azure too. And it is a fully automated setup.

I hope this was informative to you and thanks for reading!

 

 

Disclaimer

The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.

11 Comments
Co-Authors
Version history
Last update:
‎Sep 06 2022 05:39 PM
Updated by: