Azure Advanced Networking

Previously, I wrote about setting up hybrid networks utilizing AWS and GNS3 as a way to lab out and get familiar with hybrid network concepts and technology. Recently, I’ve been digging into Azure and decided to perform a bake-off, of sorts, between setting up the exact same type of topology discussed in my blog post on AWS Advanced Networking – Part 2 but with Microsoft Azure.

To recap: The general idea is to connect a cloud virtual network back to a GNS3 network hosted on your local workstation/laptop. The GNS3 network simulates an on-premises environment from where you would normally host your local services, such as active directory or perhaps a web server. The configuration notes and scripts for this lab can be found on my corresponding GitHub repository.

In this tutorial, I’ll perform a walk through, and a general comparison to performing the same task in AWS for how to connect your GNS3 lab topology to Microsoft Azure. To start, let’s take a look at the reference architecture for what we are about to build:

Figure 1. The Reference Architecture

First and foremost, the obligatory warning:

This lab MAY cost you money!

Microsoft Azure comes with a $200 credit in the U.S for new account sign-ups. Building out this topology will bite a little bit into that amount. Should you not have free credit remaining, or if you leave a VPN Gateway running, it could get expensive. So, items in this lab which will cost you money are: 

VPN Gateway – $0.04 per connection-hour.


  1. Basic familiarity with PowerShell. This time around, we won’t be using a portal based configuration and everything will be done from the command line. If you have Windows 10, you’ll already have PowerShell available, but some basic knowledge with it will help you troubleshoot when things go wrong.
  2. A GNS3 environment with a functional CISCO IOS Router – This router’s IOS needs to be capable of implementing IPSEC VPNs.
  3. A home internet router which supports NAT-T: This is NAT Traversal, which allows NAT’d IPs to traverse between IPSEC endpoints (encapsulated in UDP) and allow IKE and IPSEC to successfully negotiate. Since normally NAT modifies the IP header, this breaks IKE and IPSEC; NAT-T is designed to overcome this problem. Consult your home internet router’s documentation to ensure it supports this feature. Note: I previously had a Google Wi-Fi router which did not.

With these prereqs out of the way, let’s get started.

GNS3 Configuration

This is the exact same setup for GNS3 as in my previous post concerning AWS Advance Networking – Part 2. If you already have this as a template, you can skip to the next section. If starting from scratch, we’ll take a router within GNS3 and link it to the physical Network Interface Card of your workstation (whether that be a wired or wireless interface), and bridge it to your home/office LAN network. What this accomplishes is an interface within your GNS3 topology which can reach the Internet; more importantly, it’s an interface which can reach the Azure Vnet in order to successfully setup a site-to-site VPN.

  1. Launch GNS3, and if you don’t have an existing project you can use, create a new one.
  2. Within the topology, ensure you have at least one router and one “cloud” device. Specifically, make sure this is “Cloud” and not “Internet 0.1”, as follows:
Figure 2. The Minimum GNS3 Topology

3. Next, right click on the Cloud icon and click Configure.
4. Under the “Ethernet Interfaces” tab, ensure the “Show special Ethernet interface” check box is selected.
5. This next step will depend upon which physical network interface on your GNS3 workstation is connected to the Internet. In my case, my Internet facing NIC is labeled “Wi-Fi” within Windows. Select the drop down menu and select the appropriate NIC for your workstation which provides internet connectivity, and click Add, as follows:

Figure 3. Adding the Local Workstation’s Network Adapter to the GNS3 Topology

6. Next, connect the Router to the Cloud. Once connected, click the green Play icon, as follows:

Figure 3. The GNS3 Router connected to a local NIC

7. Before we make the required configuration changes on the router to get this working, there’s one piece of information we’ll need: The MAC address of your internet facing NIC card. Open a command prompt, and type ipconfig / all. Locate the internet facing NIC in the commands output, and copy its MAC address, as follows:

Figure 4. The MAC address of the Internet providing NIC (also a wrestling move.)

8. Next, we need to configure two items to get the router talking with the Internet: First is DHCP, for automatic assignment of an IP address on your local home network, and second the MAC address (which allows the DHCP process to negotiate an IP address.) Use the snippet below as a guide for configuring your own router, noting that a couple of items need to be updated. The MAC address needs to be the same as your workstations MAC (as noted above) and converted to dotted format, and the interface your configuring needs to be the one connected to the Cloud icon within GNS3. Here’s the example:

config t
 interface Ethernet0/0
  mac-address 985f.d3d8.a6c7
  ip address dhcp
  no shut
Figure 5. Router configuration on the upstream interface.

9. If all went well, you should be able to ping from your GNS3 router. If not, do not proceed to the next steps. First, ensure your router’s interface successfully receives an IP via DHCP, and the default gateway installs in the routing table as part of the DHCP parameters.

Setting Up PowerShell

Here we’ll need to make sure that the Azure PowerShell module is installed. Open a PowerShell window and run the following:

Install-Module -Name Az -AllowClobber -Scope CurrentUser 

Once that is successful, we’ll need to connect the session to your Azure account. Type:


A browser window should open which walks you through the login process for Azure.

After connecting to your Azure account, we’ll need to declare and initialize all of the variables we’ll be using to build out our cloud environment from the command line. Let’s start with the Virtual Network variables. These will be used for the name, location, subnets, gateway, and IP address which comprise your “virtual data center.” This is all the stuff which creates the boundary for where your cloud servers/VMs will sit. Note, this creates a brand new Vnet with new, test parameters. Copy this to the PowerShell prompt:

    $RG1         = "TestRG1"
    $VNet1       = "VNet1"
    $Location1   = "East US"
    $VNet1Prefix = ""
    $VNet1ASN    = 65001
    $GW1         = "VNet1GW"
    $FESubnet1   = "FrontEnd"
    $BESubnet1   = "Backend"
    $GwSubnet1   = "GatewaySubnet"
    $FEPrefix1   = ""
    $BEPrefix1   = ""
    $GwPrefix1   = ""
    $DNS1        = ""
    $GwIP1       = "VNet1GWIP"
    $GwIPConf1   = "gwipconf1" 

Next, we’ll define some parameters concerning your GNS3 “on-premises” environment. This is the information used to let Azure know what IP your inbound connection will be coming from, what IP subnets it will use, what BGP ASN you own, and what IP address you’ll peer from. Modify these as you see fit (definitely modify the value for LNGIP1):

    $LNG1        = "VPNsite1"
    $LNGprefix1  = ""
    $LNGprefix2  = ""
    $LNGIP1      = "Go to and paste your IP here."
    $LNGASN1     = 65000
    $BGPPeerIP1  = "" 

Now, we’ll create a resource group. This will bind all of the things we created together under a single noun name. This makes it very easy to see all what’s associated with this connection and, most of all, allows us to quickly and easily blow away this entire configuration when we are done labbing.

 New-AzResourceGroup -ResourceGroupName $RG1 -Location $Location1 

Next, we’ll create the virtual network from the parameters we defined above:

$fesub1 = New-AzVirtualNetworkSubnetConfig -Name $FESubnet1 -AddressPrefix $FEPrefix1
$besub1 = New-AzVirtualNetworkSubnetConfig -Name $BESubnet1 -AddressPrefix $BEPrefix1
$gwsub1 = New-AzVirtualNetworkSubnetConfig -Name $GWSubnet1 -AddressPrefix $GwPrefix1
$vnet   = New-AzVirtualNetwork `
                -Name $VNet1 `
                -ResourceGroupName $RG1 `
                -Location $Location1 `
                -AddressPrefix $VNet1Prefix `
                -Subnet $fesub1,$besub1,$gwsub1 

This may take a few seconds to complete. Yellow warning text as a response is okay; if you see red text as a response something’s gone wrong. If that’s the case, I’d recommend taking a look at the source code for these commands on my GitHub repository to ensure they are copying/pasting correctly.

Once that’s completed successfully, we’ll request a public IP for the VPN gateway, before creating the gateway itself:

$gwpip = New-AzPublicIpAddress -Name $GwIP1 -ResourceGroupName $RG1 `
                -Location $Location1 -AllocationMethod Dynamic
$subnet = Get-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' `
                -VirtualNetwork $vnet
$gwipconf = New-AzVirtualNetworkGatewayIpConfig -Name $GwIPConf1 `
                -Subnet $subnet -PublicIpAddress $gwpip 

Then, we’ll create the VPN gateway with BGP enabled. This will take a lot of time. Once you enter this command, go to the bathroom, take a break, get some coffee–really…this could take up to 45 minutes:

New-AzVirtualNetworkGateway -Name $Gw1 -ResourceGroupName $RG1 `
    -Location $Location1 -IpConfigurations $gwipconf -GatewayType Vpn `
    -VpnType RouteBased -GatewaySku VpnGw1 -EnableBgp $True -Asn $VNet1ASN 

Next, we’ll create the local network gateway, which represents your GNS3’s side of connection:

New-AzLocalNetworkGateway -Name $LNG1 -ResourceGroupName $RG1 `
    -Location 'East US' -GatewayIpAddress $LNGIP1 `
    -AddressPrefix $LNGprefix1,$LNGprefix2 -Asn $LNGASN1 `
    -BgpPeeringAddress $BGPPeerIP1 

Last, we’ll create the connection to form the Site-to-Site VPN:

$vng1 = Get-AzVirtualNetworkGateway -Name $GW1  -ResourceGroupName $RG1
$lng1 = Get-AzLocalNetworkGateway   -Name $LNG1 -ResourceGroupName $RG1

New-AzVirtualNetworkGatewayConnection -Name $Connection1 `
    -ResourceGroupName $RG1 -Location $Location1 `
    -VirtualNetworkGateway1 $vng1 -LocalNetworkGateway2 $lng1 `
    -ConnectionType IPsec -SharedKey "Azure@!b2C3" -EnableBGP $True  

Final GNS3 Router Configurations

Like AWS, Azure provides customized on-premises device configuration templates to get your side of the connection going. You can download these from PowerShell if you know the syntax for the on-premise platform you’ll use, as follows. This particular PowerShell snippet will work for this lab, but if you have a Juniper device (for example) you’ll need to change out the vendor name, device family, and firmware version:

$RG = "TestRG1"
$GWName = "VNet1GW"
$Connection = "VNet1toSite1"

Get-AzVirtualNetworkGatewayConnectionVpnDeviceConfigScript `
    -Name $Connection -ResourceGroupName $RG -DeviceVendor Cisco `
    -DeviceFamily "Cisco-ISR(IOS)" `
    -FirmwareVersion "Cisco-ISR-15.x--IKEv2+BGP" 

If you don’t want to be bothered by figuring out the exact syntax, you can head to the Azure portal and select from a convenient list. To do that, head to the Azure portal and click on All Resources.

  1. On the resource list, click on VNet1ToSite1.
  2. Then click on Download Configuration.
Figure 6. Azure portal device configuration download screen

A sub-menu will slide out from where you can then select the vendor, device family, and firmware version, as such. Select the appropriate configuration template for your device:

Figure 7. The Azure portal download configuration selection screen

For this lab, I recommend modifying the Cisco configurations a bit. In fact, there are at least two items in the Microsoft provided configuration that must be modified:

  1. The reference to the key ring in the IKEv2 profile (they’ve inadvertently left off the full name of the key ring.)
  2. The IPSEC profile name (the original name is greater than 30 characters which, in my IOS version, is not allowed.)

The modifications required for the configuration in this example are noted as red comments below. Additionally, items which you may be required to change, depending on the IOS image your using in GNS3, are also highlighted in red.

! Example Router Config
interface e0/0
 description OUTSIDE
 ip address dhcp
 mac-address 985F.D3D8.A6C7
 no shut
crypto ikev2 proposal azure-proposal-VNet1ToSite1
 encryption aes-cbc-256 aes-cbc-128
 integrity sha1 sha256
 group 2 14 24
! -------------
! ------------- 
crypto ikev2 policy azure-policy-VNet1ToSite1
 proposal azure-proposal-VNet1ToSite1
crypto ikev2 keyring azure-keyring-VNet1ToSite1
  pre-shared-key Azure@!b2C3
crypto ikev2 profile azure-profile-VNet1ToSite1
 match address local interface e0/0
 match identity remote address
 authentication local pre-share
 authentication remote pre-share
 !Microsoft provided config invalid: "VNet1ToSite1" was left off.
 keyring local azure-keyring-VNet1ToSite1
 lifetime 28800
 dpd 10 5 on-demand
crypto ipsec transform-set azure-ipsec-proposal-set esp-aes 256 esp-sha256-hmac
!Micrsoft provide config invalid: Chopped off "-VNet1ToSite1"
crypto ipsec profile azure-ipsec-profile
 set security-association lifetime kilobytes 102400000
 set transform-set azure-ipsec-proposal-set
 set ikev2-profile azure-profile-VNet1ToSite1
interface Tunnel100
 ip address
 ip tcp adjust-mss 1350
 tunnel source e0/0
 tunnel mode ipsec ipv4
 tunnel destination
!Microsoft provided config invalid: The IPSEC profile name is too long.
 tunnel protection ipsec profile azure-ipsec-profile
interface l0
 ip address   
router bgp 65001
 bgp log-neighbor-changes
 neighbor remote-as 65000
 neighbor ebgp-multihop 255
 neighbor update-source Tunnel100
 address-family ipv4
  network mask
  neighbor activate
ip forward-protocol nd
ip route Tunnel100


Once you’ve made the required modification to the router snippet above and entered those into your router, the site-to-site VPN should come up. The first thing we can verify is IKEv2 session. At the router terminal prompt, type show crypto ikev2 session detailed. It should show something similar:

Figure 8. The show crypto ikve2 session detailed output

Should you see nothing at all as a response to this command or anything other than READY under status, the IKev2 is failing, and you likely have a layer 3 path problem. Make sure the VPN gateway IP is correct within your router configuration and also from the router you can ping

Once IKv2 is established, you want to make sure routing is working between your GNS3 environment and Azure. Type show ip bgp sum to list the BGP neighbors the router has established. In the output below, we can see that we currently have 1 neighbor, it’s been up for 11 minutes and 7 seconds, and 1 prefix (or route) has been received. If the state remains at idle or active, something is likely wrong with the tunnel interface or the BGP configuration.

Figure 9. The output of show ip bgp sum

If we are BGP peers with the Azure Vnet, we should also see some routes being learned from that peer in the route table, and according to the output above, we are. To verify this, type show ip route bgp at the router’s CLI. In the output below, we are learning the route via the neighbor.

Figure 10. The output of show ip route bgp

From the Azure side, you can verify that the connection is established, and routes are being received with the following command:

Get-AzureRmVirtualNetworkGatewayBgpPeerStatus -ResourceGroupName TestRG1 -VirtualNetworkGatewayName VNet1GW

You should see an output such as this:

Figure 11. The output of the Get-AzureRmVirtualNetworkGatewayBgpPeerStatus command

From this, we can see that the VGW has a peer with ASN 65000, what the neighbor IP is (your GNS3 router) and the number of routes received (1; the network being advertised from your GNS3 router.)

From this point, if you deploy a new VM to VNet1 you should be able to pass traffic back and forth from your GNS3 environment.

Tear Down

To remove all of the resources associated with this lab (and to stop incurring cost) run the following commands:

Remove-AzVirtualNetworkGatewayConnection `
-Name $Connection1 -ResourceGroupName $RG1

Remove-AzVirtualNetworkGatewayConnection ` 
-Name $LNG1 -ResourceGroupName $RG1

Remove-AzResourceGroup -Name $RG1 

Final Notes

My biggest take aways from this exercise are:

  1. The Azure documentation is pretty good. What I’ve detailed here is basically a recreation of what Microsoft has on their Docs site. However, I did run into a few wrinkles along the way (for example, the template configs provided for my router had some issues and their PowerShell script had some areas where I could consolidate things onto a single page).
  2. The Azure PowerShell module is great. In my previous tutorial on this topic with AWS, I did everything from the web portal. This all could have been done from AWS’s own PowerShell integration module, so both Cloud providers have comparable ways to do things quickly and efficiently with scripts straight from the command line. But what wins me over with Azure PowerShell is its simplicity and integration with Windows. For example:

Here’s the authentication string for AWS PowerShell CLI:

 Set-AWSCredential -AccessKey AKIAIOSFODNN7EXAMPLE -SecretKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY -StoreAs MyProfileName 

And here’s the authentication string for Azure PowerShell CLI:


4. Another big item I like about Azure in general is resource groups. With these, I can clearly see all of my assets within Azure which are burning cycles and thus holes in my wallet. With AWS, I’ve yet to find a place where I can go to see everything that is up and running other than looking at my bill after the fact.

One final thing to note: The Azure configuration above uses IKEv2 and my previous AWS demo uses IKEv1. As of February 2019, AWS now supports IKEv2, so don’t let that be a detractor.