Azure to AWS VPN: Step-by-step

D Wheatley
Level Up Coding
Published in
7 min readMay 28, 2020

--

I have resources in AWS, I have resources in Azure. How do I get them to communicate with each other securely and privately?

That is the focus of this step-by-step. More specifically, we will run through the creation of a Site-to-Site VPN between an AWS Virtual Private Cloud (VPC) and Azure’s equivalent, the Virtual Network (VNet). We’ll test the success of this by showing that an EC2 instance in AWS can RDP to a Virtual Machine (VM) in Azure via its private IP address, and vice-versa.

In Azure we’ll be using PowerShell in the Cloud Shell to set up the resources, and for AWS I’ll use the console. We’ll cover the following steps:

  1. Create the base infrastructure in Azure from scratch
  2. Creating the VPN components for a default AWS VPC.
  3. Create the VPN components in the Azure

Starting with a fresh environment on Azure. You need the following:

A resource group. Azure forces you to logically group components together. For example, you might have one resource group of components for app A, and another for app B. Coming from AWS, this essentially felt like mandatory tagging, which I quite like as it keeps thinks tidy.

New-AzResourceGroup -Name TestRG1 -Location UKSouth

That creates a resource group called TestRG1 in the location UKSouth. You’ll reference TestRG1 a lot — pretty much everything you build in Azure needs to be assigned to a resource group.

A virtual network. In AWS this is called a VPC. Make sure that it has a different address space to your AWS environment. We must also include parameters for which resource group the VNet will exist in, its location, its name, and its address space.

$virtualNetwork = New-AzVirtualNetwork `
-ResourceGroupName TestRG1 `
-Location UKSouth `
-Name VNet1 `
-AddressPrefix 11.1.0.0/16

In PowerShell you set variables with the $ sign. We’re telling PowerShell that we want to set a variable called $virtualNetwork, and then we’re giving instructions about what that variable is. Usually when you hit enter, PowerShell runs your code — by inputting ` at the end of a line, PowerShell instead allows you to go to the next line. You could do without ` and write everything on one line, but it’s often clearer to separate.

A subnet for your VM to live in.

$subnetConfig = Add-AzVirtualNetworkSubnetConfig `
-Name WebSub `
-AddressPrefix 11.1.0.0/24 `
-VirtualNetwork $virtualNetwork

Most of that should be self-explanatory. Note how we’re calling the variable we set earlier to tell Azure which VNet to place ther subnet in.

Update your VNet with your new subnet configuration!

$virtualNetwork | Set-AzVirtualNetwork

At first I didn’t realise the significance of this — you need to run this after you’ve set any new subnet configuration to update the VNet with these new settings.

Add a GatewaySubnet

$vnet = Get-AzVirtualNetwork -ResourceGroupName TestRG1 -Name VNet1Add-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' -AddressPrefix 11.1.255.0/27 -VirtualNetwork $vnet$vnet | Set-AzVirtualNetwork

In Azure, Local Network Gateways and Virtual Network Gateways must be placed in a subnet called GatewaySubnet in order to work. Notice that we’re using the Set-AzVirtualNetwork command again to apply these changes.

Before we continue, I’d like to pause briefly to explain the crucial next components and what they do. In both AWS and Azure, you’ll need to set up two devices. In Azure we have:
- Local Network Gateway: This is where you tell Azure details about the AWS VPN device you want to connect to.
- Virtual Network Gateway: This is your Azure VPN device.

In AWS we have:
- Customer Gateway: This is where you tell AWS details about the Azure VPN device you want to connect to.
- Virtual Private Gateway: This is your AWS VPN device.

Hopefully you can see how with this setup, each environment has one component which is a VPN device, and one component which knows the details of the other environment so that it can connect. Now we’ll provision a Virtual Network Gateway in Azure, place it in the GatewaySubnet, and give it a public IP address. Note: Provisioning a VNet Gateway can take up to 45 minutes!

Request a public IP address

$gwpip= New-AzPublicIpAddress -Name VNet1GWIP -ResourceGroupName TestRG1 -Location 'UKSouth' -AllocationMethod Dynamic

This is the public IP address that will be associated with your Azure VPN device (the VPN Gateway). When creating your Customer Gateway in AWS, you’ll refer to this IP address.

Create your Gateway IP address configuration

$vnet = Get-AzVirtualNetwork -Name VNet1 -ResourceGroupName TestRG1$subnet = Get-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' -VirtualNetwork $vnet$gwipconfig = New-AzVirtualNetworkGatewayIpConfig -Name gwipconfig1 -SubnetId $subnet.Id -PublicIpAddressId $gwpip.Id

Bit of explanation required here I think. We’re setting variables ready to run our next command, which will create the Virtual Network Gateway. Take a look at the next command, and you’ll see how the variables we just set slot into the parameters of the New-AzVirtualNetworkGateway command.

Create Virtual Network Gateway

New-AzVirtualNetworkGateway -Name VNet1GW -ResourceGroupName TestRG1 `
-Location 'UKSouth' -IpConfigurations $gwipconfig -GatewayType Vpn `
-VpnType RouteBased -GatewaySku VpnGw1

We’ve finally created our Virtual Network Gateway. We’ve made some decisions for this example that you might not necessarily always take. For example, our VpnType is RouteBased. We could have chosen policy based instead — see here for an explanation on the differences. We’ve also chosen a specific GatewaySku. For a list of GatewaySkus and their properties, see here. The important thing for us to note is that we had to choose a SKU that supported our type of VPN tunnel, which will be IKEv2.

This will take up to 45 minutes to provision. Once done, you can view details of it by running:

Get-AzVirtualNetworkGateway -Name Vnet1GW -ResourceGroup TestRG1

While it’s provisioning, let’s hop on over to AWS to set things up over there. We’ll be using a defualt VPC so that it’s easy for you to follow along.

  1. Under Networking and Content Delivery, select VPC. On the left hand panel, select Customer Gateway → Create Customer Gateway. This is where we will fill in details about our Azure Virtual Network Gateway. Name it, choose static routing and enter the IP address you assigned to the Azure Virtual Network Gateway, hit create.
  2. On the left-hand panel, select Virtual Private Gateway → Create Virtual Private Gateway. Name it, hit create. Unlike in Azure, you don’t need to manually assign this an IP address. Once created, right-click it and attach it to your VPC.
  3. Left-hand panel again, choose Site-to-Site VPN Connections → Create VPN connection:
    Name: I called mine AWS-to-Azure
    Target Gateway Type: Virtual Private Gateway (then select the one you just made)
    Customer Gateway: choose existing, then select the one you made previously
    Routing Options: Static, then enter the IP address range of your Azure VNet — the VNet as a whole, not the IP address range of the GatewaySubnet.
  4. Download the configuration for a generic device. In the config file, locate the Pre-Shared Key value and the ‘Outside IP Addresses: Virtual Private Gateway’ value. You’ll enter these into the last resource you’ll create, the Local Network Gateway in Azure.

We’re done in AWS for the moment. A quick trip back to Azure:

  • Create the Local Network Gateway
New-AzLocalNetworkGateway -Name Site1 -ResourceGroupName TestRG1 `
-Location 'UKSouth' -GatewayIpAddress '__________' -AddressPrefix '__________'

The GatewayIpAddress needs to be the value from the AWS configuration document you downloaded ‘Outside IP Address: Virtual Private Gateway’.

The AddressPrefix needs to be the address range of your AWS VPC.

  • Create the VPN connection
$gateway1 = Get-AzVirtualNetworkGateway -Name VNet1GW -ResourceGroupName TestRG1$local = Get-AzLocalNetworkGateway -Name Site1 -ResourceGroupName TestRG1

We’ve set our variables, now to create!

New-AzVirtualNetworkGatewayConnection -Name Azure-to-AWS -ResourceGroupName TestRG1 `
-Location 'UKSouth' -VirtualNetworkGateway1 $gateway1 -LocalNetworkGateway2 $local `
-ConnectionType IPsec -RoutingWeight 10 -SharedKey '_____'`
-ConnectionProtocol IKEv2

Replace the SharedKey with the Pre-Shared Key value in the AWS S2S Connection configuration file you downloaded. Don’t worry that we’ve set up IKEv2 and the AWS document mentions IKEv1 — this seems to just be an oversight on AWS’ part.

Everything’s done in Azure, now we’ll fit the final piece of the puzzle over in AWS:

  • Enable Route Propagation

Go to the route table you intend to use for the connection (if you’re using a default VPC, you only have one). Highlight that route table and click Route Propagation → Edit Route Propagation, and propagate the virtual private gateway route.

Proving it works

Your Site-to-Site VPN Connection should now show as ‘Connected’ in Azure and ‘available’ in AWS! For a quick test, you can create a VM in Azure and an EC2 instance in AWS and try and RDP from one to another. To make this work you must ensure that in AWS you create a rule in the security group assigned to the EC2 instance that allows traffic to the Azure address range

And in Azure you assign a Network Security Group to the subnet your VM sits in which allows traffic to the AWS VPC address range.

The proof that your VPN is working is that you’ll be able to RDP via each server’s private IP address. For production, make sure you provision a second VPN tunnel for high availability. Now have fun with your connected clouds.

--

--