A
Arun's Blog
All Posts

AWS Site-to-Site VPN with Azure

|4 min read|
Multi-CloudVPNTerraformNetworking
TL;DR

Connect AWS and Azure using Site-to-Site VPN with Terraform. Create a Virtual Private Gateway in AWS and a Virtual Network Gateway in Azure, then establish an IPsec tunnel between them. Use non-overlapping CIDRs (e.g., AWS 172.31.0.0/16, Azure 192.168.0.0/16) and configure route propagation for smooth connectivity.

Introduction

Silos cannot function in the modern world. Interoperability is key for successful businesses and as much as one may want, a truly homogenous environment is hard to come by. In our everyday demands, all of us experience the urgent necessity to quickly establish communication across various technological environments from various companies.

With that, I've attempted to demonstrate how easily we can set up a Site-to-Site VPN connection between AWS and Azure, and even further ease the need of a rinse-and-repeat option with Terraform.

AWS to Azure VPN Architecture

Prerequisites

As this is an Infrastructure as Code demonstration, you should have:

  1. Understanding of Terraform
  2. An AWS Account with privileges to administer VPC, EC2, and Site-to-Site VPN
  3. An Azure Subscription with privileges to administer Resource Groups, VNets, and VPN Connections
Important

Ensure your AWS and Azure network CIDRs do not overlap. In this example, AWS uses 172.31.0.0/16 and Azure uses 192.168.0.0/16. Overlapping CIDRs will cause routing conflicts.

Final Architecture

AWS Azure VPN Logical Diagram

Terraform Configuration

Note

Because each vendor's Terraform file has dependencies on the other, you must run one first and use its output as input for the other. The Azure VNG public IP is needed for AWS Customer Gateway, and the AWS tunnel IP is needed for Azure Local Network Gateway.

AWS Side

On the AWS side, the module creates a customer gateway (pointing at the Azure VNG public IP), a virtual private gateway attached to the default VPC, route propagation into the main route table, a VPN connection with static_routes_only = true, and a static route advertising the Azure CIDR (192.168.0.0/16). A test EC2 in the default VPC with a permissive security group lets you validate connectivity once both sides come up.

Outputs to capture: aws_vpn_connection.vpn.tunnel1_address (you'll need this for the Azure Local Network Gateway) and the EC2 private IP.

Pro Tip

Use a strong, randomly generated pre-shared key in production. Store it securely in AWS Secrets Manager or Azure Key Vault. Never commit secrets to version control.

Azure Side

On the Azure side, you need a resource group, a VNet with the 192.168.0.0/16 address space, a private subnet for VMs, and critically, a subnet literally named GatewaySubnet (Azure rejects any other name for the gateway). A dynamic public IP feeds the Virtual Network Gateway, which I configured as vpn_type = "RouteBased", SKU VpnGw1, BGP off. A test Windows VM with an NSG allowing inbound from the AWS CIDR closes the loop.

Output the public IP of the VNG, that's what feeds back into the AWS Customer Gateway:

output "toEnterInAWScgw" {
  value = azurerm_public_ip.ipVNG.ip_address
}

Two gotchas. First, the gateway subnet name is non-negotiable, it has to be GatewaySubnet exactly. Second, VNG provisioning is slow, expect 30 to 45 minutes for the resource to come up before you can attach anything to it.

Deployment Order

  1. Run Azure Terraform first to create VNG and get its public IP
  2. Update AWS Terraform with Azure VNG public IP in Customer Gateway
  3. Run AWS Terraform to create VPN connection
  4. Note the AWS tunnel1 IP from output
  5. Create Azure Local Network Gateway and Connection (add to Azure Terraform)

Cleanup

When resources are no longer needed, run terraform destroy (optionally with -auto-approve) to remove all created resources and avoid ongoing charges.

Troubleshooting

  • VPN tunnel shows DOWN - Verify pre-shared keys match exactly on both sides. Check that the Customer Gateway IP matches the Azure VNG public IP.
  • Azure VNG public IP shows empty - Dynamic allocation means the IP is assigned after VNG creation. Apply Terraform, then run terraform refresh to see the IP.
  • Can't ping between AWS and Azure VMs - Check security groups on both sides allow ICMP. Verify route tables have correct routes to the peer network.
  • VNG creation takes too long - Azure VNG creation typically takes 30-45 minutes. This is normal behavior.
  • Routing issues - Ensure AWS route propagation is enabled. On Azure, verify the VNG is RouteBased type.
  • Overlapping CIDRs error - Change one side's CIDR range. VPN cannot route between overlapping address spaces.

Want Help With This?

If you're working on something similar and want a second set of eyes, or you'd like to talk through how this applies to your environment, reach out via the contact form. Happy to help.

Related Articles