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:
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.
- 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.
- A GNS3 environment with a functional CISCO IOS Router – This router’s IOS needs to be capable of implementing IPSEC VPNs.
- 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.
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.
- Launch GNS3, and if you don’t have an existing project you can use, create a new one.
- 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:
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:
6. Next, connect the Router to the Cloud. Once connected, click the green Play icon, as follows:
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:
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 end
9. If all went well, you should be able to ping 18.104.22.168 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 = "10.1.0.0/16" $VNet1ASN = 65001 $GW1 = "VNet1GW" $FESubnet1 = "FrontEnd" $BESubnet1 = "Backend" $GwSubnet1 = "GatewaySubnet" $FEPrefix1 = "10.1.0.0/24" $BEPrefix1 = "10.1.1.0/24" $GwPrefix1 = "10.1.255.0/27" $DNS1 = "22.214.171.124" $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 = "10.101.0.0/24" $LNGprefix2 = "10.101.1.0/24" $LNGIP1 = "Go to whatsmyip.com and paste your IP here." $LNGASN1 = 65000 $BGPPeerIP1 = "10.101.1.254"
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.
- On the resource list, click on VNet1ToSite1.
- Then click on Download Configuration.
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:
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:
- The reference to the key ring in the IKEv2 profile (they’ve inadvertently left off the full name of the key ring.)
- 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 !-------------- ! WAN / OUTSIDE INTERFACE interface e0/0 description OUTSIDE ip address dhcp mac-address 985F.D3D8.A6C7 no shut ! !-------------- ! IKEv2 PROPOSAL !-------------- crypto ikev2 proposal azure-proposal-VNet1ToSite1 encryption aes-cbc-256 aes-cbc-128 integrity sha1 sha256 group 2 14 24 ! ! ------------- ! IKEv2 POLICY ! ------------- crypto ikev2 policy azure-policy-VNet1ToSite1 proposal azure-proposal-VNet1ToSite1 ! !-------------- ! IKEv2 PRE-SHARED KEY !-------------- crypto ikev2 keyring azure-keyring-VNet1ToSite1 peer 126.96.36.199 address 188.8.131.52 pre-shared-key Azure@!b2C3 ! !-------------- ! IKEv2 PROFILE !-------------- crypto ikev2 profile azure-profile-VNet1ToSite1 match address local interface e0/0 match identity remote address 184.108.40.206 255.255.255.255 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 ! !-------------- ! IPSEC TRANSFORM !-------------- 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 ! !-------------- ! TUNNEL INTERFACE FOR ROUTING TO AZURE !-------------- interface Tunnel100 ip address 10.101.1.254 255.255.255.254 ip tcp adjust-mss 1350 tunnel source e0/0 tunnel mode ipsec ipv4 tunnel destination 220.127.116.11 !Microsoft provided config invalid: The IPSEC profile name is too long. tunnel protection ipsec profile azure-ipsec-profile ! !-------------- ! LAN INTERFACE (OR ANY OTHER INTERFACE) !-------------- interface l0 ip address 18.104.22.168 255.255.255.0 ! !-------------- ! BGP ROUTER CONFIGURATION !-------------- router bgp 65001 bgp log-neighbor-changes neighbor 10.1.255.30 remote-as 65000 neighbor 10.1.255.30 ebgp-multihop 255 neighbor 10.1.255.30 update-source Tunnel100 ! address-family ipv4 network 22.214.171.124 mask 255.255.255.0 neighbor 10.1.255.30 activate exit-address-family ! ip forward-protocol nd ! !-------------- ! STATIC ROUTES !-------------- ip route 10.1.255.30 255.255.255.255 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:
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 126.96.36.199.
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.
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 10.1.0.0/16 route via the 10.1.255.30 neighbor.
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:
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 188.8.131.52 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.
To remove all of the resources associated with this lab (and to stop incurring cost) run the following commands:
-Name $Connection1 -ResourceGroupName $RG1 Remove-AzVirtualNetworkGatewayConnection` -Name $LNG1 -ResourceGroupName $RG1 Remove-AzResourceGroup -Name $RG1
My biggest take aways from this exercise are:
- 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).
- 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.