Tuesday 9 November 2021

Building a hub between your lab and your internet devices using Azure

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 forwaring 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.


The following are the prerequisites which I will not cover in this post and you should already have 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

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

  1. Install required modules
  2. Connect to Azure
  3. Create a Resource Group
  4. Create VNet and subnets
  5. Create a Local Network Gateway
  6. Create a Virtual Network Gateway
  7. Create a Connection
  8. Set up the on-premises VM as a router
  9. Create a Site-to-Site interface
  10. Set up BGP Router
  11. Configure BGP Peering
  12. Start the VPN connection
  13. Download the P2S VPN configuration from Azure
  14. Create a VM for testing
  15. Demonstrate any-to-any connectivity

Now we will start to take a look on 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 Tenand 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 script. 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
}

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 your 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 break down 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 pretty 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 take a look in 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 create 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 take a look in 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 retrieve 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 similar to the following:


Get-BgpPeer


The output will be similar to the following:


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:


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


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 in 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 download to the current directory.

Next you need to download the Azure VPN client from HERE. Install it in 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:




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.


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.


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 as long as you have RDP enabled.

I hope this was useful for you and that now you have a better understanding on how to use VPN S2S with BGP and P2S with Azure AD authentication.

No comments:

Post a Comment