These terrafrom scripts deploy full mesh Site to Site IPSEC VPN with BGP between Azure and AWS Cloud.
For detailed information refer to Azure Documentation.
In addition terraform scripts deploy also Virtual Machines (one on Azure Site and one on AWS site) which could be used for connectivity testing over VPN connections.
Note that this example creates resources in Azure and AWS cloud which can cost money. Run terraform destroy when you don't need these resources.
Below table represents resources which terraform creates in Azure Cloud
Type | Name | Description | TF file |
---|---|---|---|
Resource Group | TestRG1 | Azure Resource Group where all deployed Azure resources will be placed | s2s-vpn-azure.tf |
Virtual Network | VNet1 | Azure Virtual Network | main.tf |
Azure Subnet | GatewaySubnet | Subnet where Azure Network Gateway will be placed | s2s-vpn-azure.tf |
Azure Public IP | VNet1GWpip | Azure Public IP which will be associated to VPN Network Gateway Instance0 | s2s-vpn-azure.tf |
Azure Public IP | VNet1GWpip2 | Azure Public IP which will be associated to VPN Network Gateway Instance1 | s2s-vpn-azure.tf |
Azure Virtual Network Gateway | VNet1GW | Azure Virtual Network Gateway | s2s-vpn-azure.tf |
Azure Local Network Gateway | AWSTunnel1ToInstance0 | Azure Local Network Gateway - AWS Connection1 Tunnel1 | s2s-vpn-azure.tf |
Azure Local Network Gateway | AWSTunnel2ToInstance0 | Azure Local Network Gateway - AWS Connection1 Tunnel2 | s2s-vpn-azure.tf |
Azure Local Network Gateway | AWSTunnel1ToInstance1 | Azure Local Network Gateway - AWS Connection2 Tunnel1 | s2s-vpn-azure.tf |
Azure Local Network Gateway | AWSTunnel2ToInstance1 | Azure Local Network Gateway - AWS Connection2 Tunnel2 | s2s-vpn-azure.tf |
Connection | AWSTunnel1ToInstance0 | Azure VPN connection between Azure VPN Instance0 and AWS Connection1 Tunnel1 | s2s-vpn-azure.tf |
Connection | AWSTunnel2ToInstance0 | Azure VPN connection between Azure VPN Instance0 and AWS Connection1 Tunnel2 | s2s-vpn-azure.tf |
Connection | AWSTunnel1ToInstance1 | Azure VPN connection between Azure VPN Instance1 and AWS Connection2 Tunnel1 | s2s-vpn-azure.tf |
Connection | AWSTunnel2ToInstance1 | Azure VPN connection between Azure VPN Instance0 and AWS Connection2 Tunnel2 | s2s-vpn-azure.tf |
Azure Subnet | vm-subnet | Subnet where Azure Testing VM will be placed | vm-test-azure.tf |
Azure Security Group | nsg-test-azure-vm | Security group which will be assigned to Azure Test VM nic. SG allows SSH and ICMP trafic | vm-test-azure.tf |
Azure Public IP | pip-test-azure-vm | Azure Public IP which will be associated to Azure Test VM | vm-test-azure.tf |
Azure Network Interface | nic-test-azure-vm | Azure Network Interface will be associated to Azure Test VM | vm-test-azure.tf |
Azure Virtual Machine | vpn-test-azure-vm | Azure VM for VPN connectivity testing | vm-test-azure.tf |
Below table represents resources which terraform creates in AWS Cloud.
Type | Name | Description | TF file |
---|---|---|---|
AWS VPC | VPC1 | AWS VPC | s2s-vpn-aws.tf |
AWS Internet Gateway | ig-test-aws-vm | AWS Internet Gateway in VPC1 - Needed by AWS testing VM | s2s-vpn-aws.tf |
AWS Route Table | vpn-route-table | Route Table in VPC1 | s2s-vpn-aws.tf |
AWS VPC Subnet | vpn-subnet | Subnet in VPC1 for placing AWS testing VM | s2s-vpn-aws.tf |
AWS VPN Gateway | vpn-gw | AWS VPN Gateway | s2s-vpn-aws.tf |
AWS Customer Gateway | ToAzureInstance0 | AWS Customer Gateway representing Azure VPN Instance0 | s2s-vpn-aws.tf |
AWS Customer Gateway | ToAzureInstance1 | AWS Customer Gateway representing Azure VPN Instance1 | s2s-vpn-aws.tf |
AWS VPN Connection | ToAzureInstance0 | AWS VPN Connection to Azure VPN Instance0 | s2s-vpn-aws.tf |
AWS VPN Connection | ToAzureInstance1 | AWS VPN Connection to Azure VPN Instance1 | s2s-vpn-aws.tf |
AWS Network Interface | nic-test-aws-vm | Network Interface for AWS Test VM | s2s-vpn-aws.tf |
AWS Security Group | vpn-test-sg | Network Security Group for AWS Test VM | s2s-vpn-aws.tf |
AWS SSH Key Pair | vpn-test-key-pair | SSH Key Pair for AWS Test VM | s2s-vpn-aws.tf |
AWS EC2 Instance | vpn-test-aws-vm | AWS Test VM Instance | s2s-vpn-aws.tf |
Below table represents terraform input variables
Name | Description | Type | Default | Required |
---|---|---|---|---|
azure_tenant | ID of Azure Tenant. | string |
none | yes |
azure_subscription | ID of Azure Subscription. | string |
none | yes |
azure_location | ID of Azure Location | string |
eastus |
yes |
azure_vnet_prefix | IP Prefix for Azure VNET1 | list(string) |
10.1.0.0/16 |
yes |
azure_gateway_subnet_prefix | Azure Subnet GatewaySubnet IP Prefix | list(string) |
10.1.0.0/24 |
yes |
azure_vm_subnet_prefix | Azure Test VM Subnet IP Prefix | list(string) |
10.1.100.0/24 |
yes |
azure_vpn_gateway_sku | Azure Network Gateway SKU | string |
VpnGw1 |
yes |
azure_vpn_gateway_asn | Azure Network Gateway BGP ASN | string |
65515 |
yes |
aws_region | AWS Region where AWS resources will be deployed | string |
eu-west-1 |
yes |
azure_vnet_prefix | AWS VPC1 prefix | list(string) |
10.2.0.0/16 |
yes |
aws_vm_subnet_prefix | AWS Test VM Subnet IP Prefix | list(string) |
10.2.100.0/24 |
yes |
aws_vpn_gateway_asn | AWS Gateway BGP ASN | string |
64512 |
yes |
bgp_apipa_cidr_1 | BGP APIPA CIDR 1 - AWS Tunnel 1 to Azure Instance 0 | string |
169.254.21.0/30 |
yes |
bgp_apipa_cidr_2 | BGP APIPA CIDR 2 - AWS Tunnel 2 to Azure Instance 0 | string |
169.254.22.0/30 |
yes |
bgp_apipa_cidr_3 | BGP APIPA CIDR 3 - AWS Tunnel 1 to Azure Instance 1 | string |
169.254.21.4/30 |
yes |
bgp_apipa_cidr_4 | BGP APIPA CIDR 4 - AWS Tunnel 2 to Azure Instance 1 | string |
169.254.22.4/30 |
yes |
ipsec_policy | IPSEC Protocols | object ({ dh_group = string ike_encryption = string ike_integrity = string ipsec_encryption = string ipsec_integrity = string pfs_group = string sa_datasize = string sa_lifetime = string } ) |
dh_group = "ECP384" ike_encryption = "GCMAES256" ike_integrity = "SHA384" ipsec_encryption = "GCMAES256" ipsec_integrity = "GCMAES256" pfs_group = "SHA384" sa_datasize = "102400000" sa_lifetime = "27000" |
yes |
ssh_public_key | SSH Public Key for Testing VMs | string |
none | yes |
Below table represents terraform output variables.
Name | Description |
---|---|
AzureInstance0_IP | Azure Network Gateway Instance0 Public IP |
AzureInstance1_IP | Azure Network Gateway Instance1 Public IP |
ToAzureInstance0_Tunnel1_IP | AWS To AzureInstance0 Tunnel 1 Outside IP address |
ToAzureInstance0_Tunnel2_IP | AWS To AzureInstance0 Tunnel 2 Outside IP address |
ToAzureInstance1_Tunnel1_IP | AWS To AzureInstance1 Tunnel 1 Outside IP address |
ToAzureInstance1_Tunnel2_IP | AWS To AzureInstance1 Tunnel 2 Outside IP address |
Azure_Test_VM_Public_IP | Azure Test VM Public IP |
Azure_Test_VM_Private_IP | Azure Test VM Private IP |
AWS_Test_VM_Public_IP | AWS Test VM Public IP |
AWS_Test_VM_Private_IP | AWS Test VM Private IP |
My_Public_IP | Terraform deployment Public IP |
AWS will use the first IP address of /30 inside APIPA CIDR and Azure will use the second IP Address.
Terraform cidrhost is used to calculate azure APIPA addresses from bgp_apipa_cidr
variables.
Example:
bgp_settings {
asn = var.azure_vpn_gateway_asn
peering_addresses {
ip_configuration_name = "vnetGatewayConfig-1"
apipa_addresses = [cidrhost(var.bgp_apipa_cidr_1, 2), cidrhost(var.bgp_apipa_cidr_2, 2)]
}
peering_addresses {
ip_configuration_name = "vnetGatewayConfig-2"
apipa_addresses = [cidrhost(var.bgp_apipa_cidr_3, 2), cidrhost(var.bgp_apipa_cidr_4, 2)]
}
}
Terraform generates VPN connections pre-shared keys on the fly by using terraform random_password resources.
resource "random_password" "AWSTunnel1ToInstance0-PSK" {
length = 16
special = false
}
resource "random_password" "AWSTunnel2ToInstance0-PSK" {
length = 16
special = false
}
resource "random_password" "AWSTunnel1ToInstance1-PSK" {
length = 16
special = false
}
resource "random_password" "AWSTunnel2ToInstance1-PSK" {
length = 16
special = false
}
Terraform scripts deploy Virtual Machines (one on Azure Site and one on AWS site) which could be used for connectivity testing over VPN connections.
Each of testing Virtual Machine requires to use ssh keys for SSH connection. Before deploying terrform scripts include your public ssh key into terraform variable "ssh_public_key".
The following usernames are used for VM SSH login.
VM instance | username |
---|---|
Azure Testing VM | ubuntu |
AWS Testing VM | ec2-user |
Communication to testing VM is restricted by Security Groups.
SSH connection to Virtual Machines is allowed only from IP address where tf scrips are executed. Public deployment IP address is automatically obtained by terraform http data-source.
data "http" "source_ip" {
url = "https://ifconfig.me"
}
For VPN testing purposes IMCP traffic is allowed between Azure VNET and AWS VPC CIDR.
Security Group Rules for Azure Testing VM
resource "azurerm_network_security_rule" "nsg-test-azure-vm-rule-1" {
name = "ssh"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "${data.http.source_ip.body}/32"
destination_address_prefix = "*"
description = "Test-SSH."
resource_group_name = azurerm_resource_group.vpn-rg.name
network_security_group_name = azurerm_network_security_group.nsg-test-azure-vm.name
}
resource "azurerm_network_security_rule" "nsg-test-azure-vm-rule-2" {
name = "icmp"
priority = 101
direction = "Inbound"
access = "Allow"
protocol = "Icmp"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = var.aws_vnet_prefix
destination_address_prefix = "*"
description = "Test-ICMP"
resource_group_name = azurerm_resource_group.vpn-rg.name
network_security_group_name = azurerm_network_security_group.nsg-test-azure-vm.name
}
Security Group Rules for AWS Testing VM
resource "aws_security_group" "vpn-test-sg" {
name = "vpn-test-sg"
description = "Security Group For testing vpn connectivity"
vpc_id = aws_vpc.aws-vpc.id
ingress {
description = "SSH into VPC"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["${data.http.source_ip.body}/32"]
}
ingress {
description = "ICMP into VPC"
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = var.azure_vnet_prefix
}
egress {
description = "Outbound Allowed"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "vpn-test-sg"
}
}
To run this example you need to execute:
$ terraform init
$ terraform plan
$ terraform apply
Name | Version |
---|---|
terraform | >= 0.14.9 |
aws | >= 3.63 |
azurerm | >= 3.0.2 |
Name | Version |
---|---|
aws | >= 3.63 |
azurerm | >= 3.0.2 |
No modules.
Terraform azurerm does not yet support enabling Custom BGP Addresses for Azure connections. Please refer to hashicorp/terraform-provider-azurerm#15854
Without changing Custom BGP Addresses for Azure connections BGP routes are properly advertised through AWSTunnel1ToInstance0 and AWSTunnel1ToInstance1 but tunnels AWSTunnel2ToInstance0 and AWSTunnel2ToInstance1 advertise wrong APIPA address.
To have all tunnels properly advertise routes there need to be changed Custom BGP Addresses for AWSTunnel2ToInstance0 and AWSTunnel2ToInstance1.
AWSTunnel2ToInstance0
-> Primary Custom BGP Address change to169.254.22.2
AWSTunnel2ToInstance1
-> Secondary Custom BGP Address change to169.254.22.6