Step-by-Step: Connect your AWS and Azure environments with a VPN tunnel

****** Note that an updated version of this post is available on *******

Hello Folks,

I’ve been working with a customer that is planning their migration from AWS to Azure.  As we all know, migrating complex environment is seldom a one click operation.  In their case they want to be able to move each part of their solutions hosted on AWS to azure one at a time.  That way they can test each move, validate that the move have been successful and keep the solution online.

To achieve the desired results we create a POC (proof of concept environment) that is composed of the following pieces.


In this post I will show how created that site to site IPsec tunnel to connect to a Virtual Private Cloud (VPC) hosted in Amazon Web Services (AWS) to a Virtual Network in Azure. Using this setup you can have workloads in one or both clouds with full VM to VM connectivity over a secure IPsec tunnel. This easily can provide connectivity for high availability operations, backup or (like in our case) migration between clouds.

In our case we selected a Windows 2012 R2 server as the end point of the tunnel on the AWS side mostly because it is a supported platform as a Azure VPN device for route-based VPN that did not add costs to our POC unlike other supported virtual appliances from the AWS marketplace that are supported as validated VPN devices on Azure.

If you’re

let’s get started…

Create an Elastic IP in AWS

First we need to an allocate address in AWS.  It will be assigned in later steps to the AWS VPN gateway. However we will need that address before we start to configuring the Azure infrastructure.

1. In the VPC dashboard, click Elastic IPs , allocate New Address and click Yes, Allocate clip_image002

This will create the address but it will not assign it anywhere. We're doing this now since we need the IP address to setup the Azure side of the VPN

Prepare the Azure side of the VPN

1. We used the Resource Group deployment model.  So first, we need to create a Resource group for our POC.  We created AZURE2AWS

2. In the AZURE2AWS Resource Group Add a virtual Network clip_image004

3. In the Next blade ensure to select Resource Manager as the deployment model and click Create clip_image006

4. Fill in creation details and click Create.

We used one Virtual Network called Azure2Aws with an address space of  In it we created a subnet called FrontEnd with the address range clip_image008

5. In the Virtual Network I created a GTW subnet that will be used when we create the Gateway. clip_image010 SNAGHTML1be7c79

When providing the subnet name ensure that you use “GatewaySubnet” (This name is mandatory for Gateway Subnets).   We used the subnet address space -

6. Once our virtual network was created. We deployed a Windows 2012 R2 server in the virtual network.  It will act as a DC and DNS server for the lab. ( we deployed it at this point so it will be ready by the time we need it).  We ensured that the NIC for the server was set to static since we will use it as a DC and as a DNS server. clip_image014

7. We navigated back to the Azure2Aws resource group and added a Virtual Network Gateway. clip_image016

Clicked Create in the Virtual network Gateway blade, provided the info needed for the creation (Gateway name, IP address Name, route-based) and click create. (Be patient it will take some time to generate the gateway). image

After the gateway has been created you will need to note the IP Address of the Virtual network Gateway you will need it later.

8. Then, navigate back to the Resource Group and Add a Local Network Gateway. clip_image020

I once you selected Local Network Gateway above, click create in the next blade, fill the information of the AWS VPC (IP address is the Elastic IP assigned to the GTW – We created that in the first step - in the AWS VPC, and address space is the VPC CIDR in AWS) ensure that you are always selecting the right Resource Group in our case Azure2Aws and click create clip_image022

9. Wait for the Local network Gateway to be created. Once it is created, in the settings of the local network gateway, in the connections setting, add a new connection. clip_image024

In the connection settings give it a name select the Azure Virtual network gateway we created earlier and supply a shared key note the shared key , you will need it later.  I recommend you DO NOT use a1b2c3d4e5 has we did.  This is a test environment.  please generate a strong shared key. clip_image026

10. I set the Virtual Network DNS to be the DNS on my DC1 machine (the one we created earlier). Navigate to the Resource Group, select the Virtual Network, all settings, set the DNS to custom and provide the address of the DC1 NIC. clip_image028

Prepare AWS side

1. Now that the Azure side of the equation is ready Let’s move to the AWS side of things.  First we created a new VPC.

  • Name Aws2Azure
  • Address block of
  • I used the following name: awssubnet
  • CIDR:

clip_image030 clip_image032 clip_image034 clip_image035

2. Insure your VPC is connected to and internet Gateway. clip_image037

3. At this point having a VPC up and running we created an EC2 instance in the VPC that will act as our edge VPN device.

  • A Windows Server 2012 R2 instance
  • I used a t2.small instance but this could change depending on network performance needed.
  • Ensure that Auto-assign Public IP is enabled.


Please ensure you pick the right VPC and Subnet then click review and launch

4. Once the instance is running associate the Elastic IP we created earlier to the Network interface of the instance. By clicking Elastic IPs in the VPC dashboard, selecting Associate Address in the actions menu, selecting the Network interface used by the Windows Server 2012 R2 instance we created earlier and click associate clip_image041

5. Next, disable source/destination checking on the server. clip_image043 clip_image045

6. Once the Elastic IP is associated connect to your instance over RDP. We are now ready to configure the instance to connect to Azure.

Configure The Windows 2012 R2 Server RRAS server

1. Copy the content of the script located here we will use that PowerShell script to install RRAS on our server and configure it.

On your AWS windows 2012 R2 instance RDP session. Login as administrator, Open the PowerShell ISE and paste the content of the script you copied above in the script pane of the ISE.

Modify as shown below. (red = delete, Green = add\modify) and execute the script.

  <?xml version="1.0" encoding="utf-16"?><br><xsl:stylesheet version="1.0" xmlns:xsl=""><br>  <xsl:output method="text"/><br>  <xsl:template match="/"># Microsoft Corporation
# Windows Azure Virtual Network

# This configuration template applies to Microsoft RRAS running on Windows Server 2012 R2.
# It configures an IPSec VPN tunnel connecting your on-premise VPN device with the Azure gateway.

# !!! Please notice that we have the following restrictions in our support for RRAS:
# !!! 1. Only IKEv2 is currently supported
# !!! 2. Only route-based VPN configuration is supported.
# !!! 3. Admin priveleges are required in order to run this script

Function Invoke-WindowsApi( 
    [string] $dllName,  
    [Type] $returnType,  
    [string] $methodName, 
    [Type[]] $parameterTypes, 
    [Object[]] $parameters 
  ## Begin to build the dynamic assembly 
  $domain = [AppDomain]::CurrentDomain 
  $name = New-Object Reflection.AssemblyName 'PInvokeAssembly' 
  $assembly = $domain.DefineDynamicAssembly($name, 'Run') 
  $module = $assembly.DefineDynamicModule('PInvokeModule') 
  $type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit") 

  $inputParameters = @() 

  for($counter = 1; $counter -le $parameterTypes.Length; $counter++) 
     $inputParameters += $parameters[$counter - 1] 

  $method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',$returnType, $parameterTypes) 

  ## Apply the P/Invoke constructor 
  $ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]) 
  $attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName 

  ## Create the temporary type, and invoke the method. 
  $realType = $type.CreateType() 

  $ret = $realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null, $inputParameters) 

  return $ret

Function Set-PrivateProfileString( 
  ## Prepare the parameter types and parameter values for the Invoke-WindowsApi script 
  $parameterTypes = [string], [string], [string], [string] 
  $parameters = [string] $category, [string] $key, [string] $value, [string] $file 

  ## Invoke the API 
  [void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "WritePrivateProfileString" $parameterTypes $parameters)

# Install RRAS role
Import-Module ServerManager
Install-WindowsFeature RemoteAccess -IncludeManagementTools
Add-WindowsFeature -name Routing -IncludeManagementTools

# !!! NOTE: A reboot of the machine might be required here after which the script can be executed again.

# Install S2S VPN
Import-Module RemoteAccess
if ((Get-RemoteAccess).VpnS2SStatus -ne "Installed")
  Install-RemoteAccess -VpnType VpnS2S

# Add and configure S2S VPN interface

Add-VpnS2SInterface -Protocol IKEv2 -AuthenticationMethod PSKOnly -NumberOfTries 3 -ResponderAuthenticationMethod PSKOnly
 -Name <IP address of your Azure gateway> -Destination  <IP address of your Azure gateway> 
 -IPv4Subnet @(" <IP range of your subnet in Azure> :100")
 -SharedSecret  <shared key> 
 Set-VpnServerIPsecConfiguration -EncryptionType MaximumEncryption

Set-VpnS2Sinterface -Name  <IP address of your Azure gateway>  -InitiateConfigPayload $false -Force

# Set S2S VPN connection to be persistent by editing the router.pbk file (required admin priveleges)
Set-PrivateProfileString $env:windir\System32\ras\router.pbk “ <IP address of your Azure gateway>”  "IdleDisconnectSeconds" "0"
Set-PrivateProfileString $env:windir\System32\ras\router.pbk " <IP address of your Azure gateway> " "RedialOnLinkFailure" "1"

# Restart the RRAS service
Restart-Service RemoteAccess

# Dial-in to Azure gateway
Connect-VpnS2SInterface -Name  <IP address of your Azure gateway> 


2. Once the script finishes. You may have to run the following command in the powershell console

Restart-Service RemoteAccess

3. And then this one

Connect-VpnS2SInterface -Name <IP address of your Azure gateway>

4. Close PowerShell and open the Routing and Remote Access console and verify that the connection is complete clip_image049

5. Go back to your AWS Management Console to Configure Routing.

In the Amazon management console switch to the VPC view and select Route tables. Select the route table associated with your VPC and add a new route to the (Windows Azure Network) and that routes traffic through the instance ID of the Server. clip_image051

6. And finally, create a DHCP Option set that will point the machines in the AWS network to the DNS on the Azure network. That way you will be able to resolve he machines. clip_image053

now that the network and the VPN are complete, we created some other VMs on each side (Ubuntu servers in this case) to validate routing, and connectivity.

That’s it, we now have a site to site VPN between our AWS and Azure environment.  and we’re ready to start moving our workloads over.

Cheers! Signature

Pierre Roman