<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BGP &#8211; Blog of Kliment Andreev &#8211; A place so I won&#039;t forget things</title>
	<atom:link href="https://blog.andreev.it/tag/bgp/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.andreev.it</link>
	<description></description>
	<lastBuildDate>Mon, 28 Oct 2024 14:36:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>AWS, Azure: Site-to-site (S2S) VPN tunnel between AWS and Azure</title>
		<link>https://blog.andreev.it/2024/10/aws-azure-site-to-site-s2s-vpn-tunnel-between-aws-and-azure/</link>
					<comments>https://blog.andreev.it/2024/10/aws-azure-site-to-site-s2s-vpn-tunnel-between-aws-and-azure/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Mon, 28 Oct 2024 14:36:49 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[BGP]]></category>
		<category><![CDATA[IKE]]></category>
		<category><![CDATA[S2S]]></category>
		<category><![CDATA[Site-to-Site]]></category>
		<category><![CDATA[VPN]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=10004</guid>

					<description><![CDATA[In this post I&#8217;ll create a site-to-site (S2S) tunnel between AWS and Azure. It&#8217;s&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this post I&#8217;ll create a site-to-site (S2S) tunnel between AWS and Azure. It&#8217;s an HA tunnel so it&#8217;s regionally resilient. I&#8217;ll use Terraform for the deployment using a set of modules (download <a href="https://blog.andreev.it/wp-content/uploads/2024/10/modules.tgz">here</a>). The Terraform files will be separated in two different folders. One for Azure and one for AWS.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2024/10/P175-01.png"><img fetchpriority="high" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2024/10/P175-01.png" alt="" width="643" height="581" class="aligncenter size-full wp-image-10006" srcset="https://blog.andreev.it/wp-content/uploads/2024/10/P175-01.png 643w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-01-300x271.png 300w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-01-585x529.png 585w" sizes="(max-width: 643px) 100vw, 643px" /></a><br />
The architectural diagram looks like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2024/10/P175-02.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2024/10/P175-02.png" alt="" width="816" height="831" class="aligncenter size-full wp-image-10007" srcset="https://blog.andreev.it/wp-content/uploads/2024/10/P175-02.png 816w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-02-295x300.png 295w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-02-768x782.png 768w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-02-585x596.png 585w" sizes="(max-width: 816px) 100vw, 816px" /></a></p>
<h1>Azure</h1>
<p>For Azure, we will provision a public subnet (10.1.0.0/24) and a Gateway subnet (10.1.1.0/24). Then, we&#8217;ll provision one VNET Gateway with active-active BGP tunnel. The Azure setup requires that we provision 4 local network gateways and S2S connections, but the output will return only 2 public IPs. These are the files.<br />
<strong>provider.tf</strong></p>
<pre class="brush: bash; title: ; notranslate">
terraform {
  required_version = &quot;~&gt;1.9.5&quot;
  required_providers {
    azurerm = {
      source  = &quot;hashicorp/azurerm&quot;
      version = &quot;~&gt;3.110.0&quot;
    }
  }
}

provider &quot;azurerm&quot; {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
}
</pre>
<p><strong>azure.tf</strong></p>
<pre class="brush: bash; collapse: true; highlight: [155,196,237,278]; light: false; title: ; toolbar: true; notranslate">
# Create a resource group
module &quot;rg&quot; {
  source = &quot;../../modules/azure/rg-0.0.4&quot;

  az_rg_name     = var.rg_ResourceGroupName
  az_rg_location = var.rgn_RegionLocation
}

# Create a VNET
module &quot;vnet&quot; {
  source = &quot;../../modules/azure/vnet-4.0.0&quot;

  vnet_name           = var.vnet_Name
  resource_group_name = var.rg_ResourceGroupName
  vnet_location       = var.rgn_RegionLocation
  use_for_each        = false
  address_space       = &#x5B;var.vnet_CIDR]
  subnet_prefixes     = &#x5B;var.sub_PublicCIDR, var.sub_GatewayCIDR]
  subnet_names        = &#x5B;var.sub_PublicName, var.sub_GatewayName]

  depends_on = &#x5B;module.rg]
}

# Create a virtual network gateway
module &quot;vnetgw&quot; {
  source = &quot;../../modules/azure/vnetgw-0.5.1&quot;

  location                  = var.rgn_RegionLocation
  name                      = var.vgw_Name
  subnet_address_prefix     = var.sub_GatewayCIDR
  sku                       = var.vgw_SKU
  type                      = var.vgw_Type
  virtual_network_id        = module.vnet.vnet_id
  vpn_generation            = var.vgw_Generation
  vpn_type                  = var.vpn_Type
  subnet_creation_enabled   = false
  vpn_active_active_enabled = true
  vpn_bgp_enabled           = true
  vpn_bgp_settings = {
    asn = var.asn_Azure
  }
  # Create virtual network gateway configurations
  ip_configurations = {
    &quot;ip_config_01&quot; = {
      name            = var.gwc_BGPName1
      apipa_addresses = var.ip_APIPAAddresses1
      public_ip = {
        allocation_method = var.ip_allocation_method
      }
    },
    &quot;ip_config_02&quot; = {
      name            = var.gwc_BGPName2
      apipa_addresses = var.ip_APIPAAddresses2
      public_ip = {
        allocation_method = var.ip_allocation_method
      }
    }
  }
  # Create local network gateways and connections
  local_network_gateways = {
    # AWS Tunnel 1 to Azure Instance 0
    &quot;lngw_01&quot; = {
      name            = var.lng_AWST1A0
      gateway_address = var.ip_AWST1A0
      bgp_settings = {
        asn                 = var.asn_AWS
        bgp_peering_address = var.ip_peering_AWST1A0
      }
      connection = {
        name       = var.conn_AWST1A0
        type       = var.conn_Type
        enable_bgp = true
        shared_key = var.key_SharedKey
        custom_bgp_addresses = {
          primary   = var.ip_primary_AWST1A0
          secondary = var.ip_secondary_AWST1A0
        }
      }
    },
    # AWS Tunnel 2 to Azure Instance 0
    &quot;lngw_02&quot; = {
      name            = var.lng_AWST2A0
      gateway_address = var.ip_AWST2A0
      bgp_settings = {
        asn                 = var.asn_AWS
        bgp_peering_address = var.ip_peering_AWST2A0
      }
      connection = {
        name       = var.conn_AWST2A0
        type       = var.conn_Type
        enable_bgp = true
        shared_key = var.key_SharedKey
        custom_bgp_addresses = {
          primary = var.ip_primary_AWST2A0
        secondary = var.ip_secondary_AWST2A0 }
      }
    },
    # AWS Tunnel 1 to Azure Instance 1
    &quot;lngw_03&quot; = {
      name            = var.lng_AWST1A1
      gateway_address = var.ip_AWST1A1
      bgp_settings = {
        asn                 = var.asn_AWS
        bgp_peering_address = var.ip_peering_AWST1A1
      }
      connection = {
        name       = var.conn_AWST1A1
        type       = var.conn_Type
        enable_bgp = true
        shared_key = var.key_SharedKey
        custom_bgp_addresses = {
          primary = var.ip_primary_AWST1A1
        secondary = var.ip_secondary_AWST1A1 }
      }
    },
    # AWS Tunnel 2 to Azure Instance 1
    &quot;lngw_04&quot; = {
      name            = var.lng_AWST2A1
      gateway_address = var.ip_AWST2A1
      bgp_settings = {
        asn                 = var.asn_AWS
        bgp_peering_address = var.ip_peering_AWST2A1
      }
      connection = {
        name       = var.conn_AWST2A1
        type       = var.conn_Type
        enable_bgp = true
        shared_key = var.key_SharedKey
        custom_bgp_addresses = {
          primary = var.ip_primary_AWST2A1
        secondary = var.ip_secondary_AWST2A1 }
      }
    }
  }

  depends_on = &#x5B;module.vnet]
}
</pre>
<p><strong>variables.tf</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
# Resource group
variable &quot;rg_ResourceGroupName&quot; {
  type        = string
  default     = &quot;rgVPN&quot;
  description = &quot;Resource group name&quot;
}

variable &quot;rgn_RegionLocation&quot; {
  type        = string
  default     = &quot;eastus2&quot;
  description = &quot;Azure region&quot;
}

# VNET
variable &quot;vnet_Name&quot; {
  type        = string
  default     = &quot;vnetVPN&quot;
  description = &quot;VNET name&quot;
}

variable &quot;vnet_CIDR&quot; {
  type        = string
  default     = &quot;10.1.0.0/16&quot;
  description = &quot;VNET CIDR&quot;
}

variable &quot;sub_PublicCIDR&quot; {
  type        = string
  default     = &quot;10.1.0.0/24&quot;
  description = &quot;CIDR of the public subnet&quot;
}

variable &quot;sub_GatewayCIDR&quot; {
  type        = string
  default     = &quot;10.1.1.0/24&quot;
  description = &quot;CIDR of the Gateway subnet&quot;
}

variable &quot;sub_PublicName&quot; {
  type        = string
  default     = &quot;subPublic&quot;
  description = &quot;Name of the public subnet&quot;
}

variable &quot;sub_GatewayName&quot; {
  type        = string
  default     = &quot;GatewaySubnet&quot;
  description = &quot;Name of the Gateway subnet - DO NOT CHANGE. It has to stay as GatewaySubnet&quot;
}

# Virtual network gateway
variable &quot;vgw_Name&quot; {
  type        = string
  default     = &quot;vgwVPN&quot;
  description = &quot;Name of the virtual gateway&quot;
}

variable &quot;vgw_SKU&quot; {
  type        = string
  default     = &quot;VpnGw2AZ&quot;
  description = &quot;Virtual Gateway SKU&quot;
}

variable &quot;vgw_Type&quot; {
  type        = string
  default     = &quot;Vpn&quot;
  description = &quot;Virtual Gateway Type (VPN or ExpressRoute)&quot;
}

variable &quot;vgw_Generation&quot; {
  type        = string
  default     = &quot;Generation2&quot;
  description = &quot;Virtual Gateway Generation&quot;
}

variable &quot;vpn_Type&quot; {
  type        = string
  default     = &quot;RouteBased&quot;
  description = &quot;VPN type - RouteBased or PolicyBased&quot;
}

variable &quot;asn_Azure&quot; {
  type        = string
  default     = &quot;65000&quot;
  description = &quot;Azure ASN&quot;
}

variable &quot;asn_AWS&quot; {
  type        = string
  default     = &quot;64512&quot;
  description = &quot;AWS ASN&quot;
}

# Virtual network gateway config 1
variable &quot;gwc_BGPName1&quot; {
  type        = string
  default     = &quot;vnetGatewayConfig01&quot;
  description = &quot;Name of the virtual network gateway configuration for the first tunnel&quot;
}

variable &quot;ip_APIPAAddresses1&quot; {
  type        = list(string)
  default     = &#x5B;&quot;169.254.21.2&quot;, &quot;169.254.22.2&quot;]
  description = &quot;APIPA address for the first tunnel&quot;
}

# Virtual network gateway config 2
variable &quot;gwc_BGPName2&quot; {
  type        = string
  default     = &quot;vnetGatewayConfig02&quot;
  description = &quot;Name of the virtual network gateway configuration for the second tunnel&quot;
}

variable &quot;ip_APIPAAddresses2&quot; {
  type        = list(string)
  default     = &#x5B;&quot;169.254.21.6&quot;, &quot;169.254.22.6&quot;]
  description = &quot;APIPA address for the second tunnel&quot;
}

variable &quot;ip_allocation_method&quot; {
  type        = string
  default     = &quot;Static&quot;
  description = &quot;Static or Dynamic public IP&quot;
}

# Local network gateway common settings
variable &quot;conn_Type&quot; {
  type        = string
  default     = &quot;IPsec&quot;
  description = &quot;Connection type: IPsec or Vnet2Vnet&quot;
}

variable &quot;key_SharedKey&quot; {
  type        = string
  default     = &quot;KlimentAndreev1970_&quot;
  description = &quot;Make sure it&#039;s the same as &#039;key_SharedKey&#039; variable in variables.tf under the AWS folder&quot;
  # Don&#039;t go crazy with complexity. AWS side can support only 
  # between 8 and 64 characters in length and cannot start with zero (0). 
  # Allowed characters are alphanumeric characters, periods (.), and underscores (_).
}

# Local network gateway AWS Tunnel 1 to Azure Instance 0
# lngw_01
variable &quot;lng_AWST1A0&quot; {
  type        = string
  default     = &quot;lng_AWSTunnel1ToAzureInstance0&quot;
  description = &quot;From AWS Tunnel 1 to Azure Instance 0&quot;
}

###
### REPLACE FROM THE OUTPUT OF AWS IN STEP 2
###
variable &quot;ip_AWST1A0&quot; {
  type        = string
  default     = &quot;13.58.80.164&quot;
  description = &quot;Enter the output of ip_AWST1IP1 from the AWS output.tf script&quot;
}

variable &quot;ip_peering_AWST1A0&quot; {
  type        = string
  default     = &quot;169.254.21.1&quot;
  description = &quot;BGP Peering IP for AWS Tunnel1 to Azure Instance 0&quot;
}

variable &quot;ip_primary_AWST1A0&quot; {
  type        = string
  default     = &quot;169.254.21.2&quot;
  description = &quot;Primary Custom BGP Address for AWS Tunnel1 to Azure Instance 0&quot;
}

variable &quot;ip_secondary_AWST1A0&quot; {
  type        = string
  default     = &quot;169.254.21.6&quot;
  description = &quot;Secondary Custom BGP Address for AWS Tunnel1 to Azure Instance 0&quot;
}

variable &quot;conn_AWST1A0&quot; {
  type        = string
  default     = &quot;connAWSTunnel1toAzureInstance0&quot;
  description = &quot;Connection name for AWS Tunnel1 to Azure Instance 0&quot;
}

# Local network gateway AWS Tunnel 2 to Azure Instance 0
# lngw_02
variable &quot;lng_AWST2A0&quot; {
  type        = string
  default     = &quot;lng_AWSTunnel2ToAzureInstance0&quot;
  description = &quot;From AWS Tunnel 2 to Azure Instance 0&quot;
}

###
### REPLACE FROM THE OUTPUT OF AWS IN STEP 2
###
variable &quot;ip_AWST2A0&quot; {
  type        = string
  default     = &quot;18.119.84.239&quot;
  description = &quot;Enter the output of ip_AWST2A0 from the AWS output.tf script&quot;
}

variable &quot;ip_peering_AWST2A0&quot; {
  type        = string
  default     = &quot;169.254.22.1&quot;
  description = &quot;BGP Peering IP for AWS Tunnel2 to Azure Instance 0&quot;
}

variable &quot;ip_primary_AWST2A0&quot; {
  type        = string
  default     = &quot;169.254.22.2&quot;
  description = &quot;Primary Custom BGP Address for AWS Tunnel2 to Azure Instance 0&quot;
}

variable &quot;ip_secondary_AWST2A0&quot; {
  type        = string
  default     = &quot;169.254.21.6&quot;
  description = &quot;Secondary Custom BGP Address for AWS Tunnel1 to Azure Instance 1&quot;
}

variable &quot;conn_AWST2A0&quot; {
  type        = string
  default     = &quot;connAWSTunnel2toAzureInstance0&quot;
  description = &quot;Connection name for AWS Tunnel2 to Azure Instance 0&quot;
}

# Local network gateway AWS Tunnel 1 to Azure Instance 1
# lngw_03
variable &quot;lng_AWST1A1&quot; {
  type        = string
  default     = &quot;lng_AWSTunnel1ToAzureInstance1&quot;
  description = &quot;From AWS Tunnel 1 to Azure Instance 1&quot;
}

###
### REPLACE FROM THE OUTPUT OF AWS IN STEP 2
###
variable &quot;ip_AWST1A1&quot; {
  type        = string
  default     = &quot;18.119.2.80&quot;
  description = &quot;Enter the output of ip_AWST1A1 from the AWS output.tf script&quot;
}

variable &quot;ip_peering_AWST1A1&quot; {
  type        = string
  default     = &quot;169.254.21.5&quot;
  description = &quot;BGP Peering IP for AWS Tunnel1 to Azure Instance 1&quot;
}

variable &quot;ip_primary_AWST1A1&quot; {
  type        = string
  default     = &quot;169.254.21.2&quot;
  description = &quot;Primary Custom BGP Address for AWS Tunnel1 to Azure Instance 1&quot;
}

variable &quot;ip_secondary_AWST1A1&quot; {
  type        = string
  default     = &quot;169.254.21.6&quot;
  description = &quot;Secondary Custom BGP Address for AWS Tunnel1 to Azure Instance 1&quot;
}

variable &quot;conn_AWST1A1&quot; {
  type        = string
  default     = &quot;connAWSTunnel1toAzureInstance1&quot;
  description = &quot;Connection name for AWS Tunnel1 to Azure Instance 1&quot;
}

# Local network gateway AWS Tunnel 2 to Azure Instance 1
# lngw_04
variable &quot;lng_AWST2A1&quot; {
  type        = string
  default     = &quot;lng_AWSTunnel2ToAzureInstance1&quot;
  description = &quot;From AWS Tunnel 2 to Azure Instance 1&quot;
}

###
### REPLACE FROM THE OUTPUT OF AWS IN STEP 2
###
variable &quot;ip_AWST2A1&quot; {
  type        = string
  default     = &quot;18.220.73.188&quot;
  description = &quot;Enter the output of ip_AWST2A1 from the AWS ouput.tf script&quot;
}

variable &quot;ip_peering_AWST2A1&quot; {
  type        = string
  default     = &quot;169.254.22.5&quot;
  description = &quot;BGP Peering IP for AWS Tunnel2 to Azure Instance 1&quot;
}

variable &quot;ip_primary_AWST2A1&quot; {
  type        = string
  default     = &quot;169.254.21.2&quot;
  description = &quot;Primary Custom BGP Address for AWS Tunnel2 to Azure Instance 1&quot;
}

variable &quot;ip_secondary_AWST2A1&quot; {
  type        = string
  default     = &quot;169.254.22.6&quot;
  description = &quot;Secondary Custom BGP Address for AWS Tunnel2 to Azure Instance 1&quot;
}

variable &quot;conn_AWST2A1&quot; {
  type        = string
  default     = &quot;connAWSTunnel2toAzureInstance1&quot;
  description = &quot;Connection name for AWS Tunnel2 to Azure Instance 1&quot;
}
</pre>
<p><strong>outputs.tf</strong></p>
<pre class="brush: bash; title: ; notranslate">
output &quot;vgw_publicip_1&quot; {
  value       = module.vnetgw.public_ip_addresses.ip_config_01.ip_address
  description = &quot;Use this output to populate the same variable in AWS variables.tf file.&quot;
}

output &quot;vgw_publicip_2&quot; {
  value       = module.vnetgw.public_ip_addresses.ip_config_02.ip_address
  description = &quot;Use this output to populate the same variable in AWS variables.tf file.&quot;
}
</pre>
<p>Once you run the initial <em>terraform apply</em> it will take about 35-40 mins and you&#8217;ll get two IPs as output. You&#8217;ll need these momentarily in the file <strong>variables.tf</strong> under <strong>02.AWS</strong> folder.</p>
<pre class="brush: bash; title: ; notranslate">
vgw_publicip_1 = &quot;48.211.240.129&quot;
vgw_publicip_2 = &quot;48.211.240.186&quot;
</pre>
<h1>AWS</h1>
<p>In AWS we&#8217;ll provision a private and a public subnet as well as two VPN tunnels. This is the Terraform code for that.<br />
<strong>provider.tf</strong></p>
<pre class="brush: bash; title: ; notranslate">
terraform {
  required_version = &quot;~&gt;1.9.5&quot;
  required_providers {
    aws = {
      source  = &quot;hashicorp/aws&quot;
      version = &quot;~&gt;5.57.0&quot;
    }
  }
}

provider &quot;aws&quot; {
  region = var.rgn_RegionLocation
}
</pre>
<p><strong>aws.tf</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
# Create VPC
module &quot;vpc&quot; {

  source = &quot;../../modules/aws/vpc-5.5.1&quot;

  name = var.vpc_Name
  cidr = var.vpc_CIDR

  azs             = var.vpc_AZs
  private_subnets = var.sub_pvtCIDR
  public_subnets  = var.sub_pubCIDR

  enable_nat_gateway = true
  enable_vpn_gateway = true
  amazon_side_asn    = var.asn_AWS
}

# Change the route to enable propagation to public route table
# resource &quot;aws_vpn_gateway_route_propagation&quot; &quot;rtPropg&quot; {
#   vpn_gateway_id = module.vpc.vgw_id
#   route_table_id = module.vpc.public_route_table_ids&#x5B;0]
# }

# Change the route to enable propagation to private route table
resource &quot;aws_vpn_gateway_route_propagation&quot; &quot;rtPvtPropg&quot; {
  vpn_gateway_id = module.vpc.vgw_id
  route_table_id = module.vpc.private_route_table_ids&#x5B;0]
}

# Add the NAT gateway as a route to Internet to the private route table
# resource &quot;aws_route&quot; &quot;r&quot; {
#   route_table_id         = module.vpc.private_route_table_ids&#x5B;0]
#   destination_cidr_block = &quot;0.0.0.0/0&quot;
#   nat_gateway_id         = module.vpc.natgw_ids&#x5B;0]
# }

# Create 2 customer gateways
module &quot;cgw&quot; {
  source = &quot;../../modules/aws/cgw-2.0.1/&quot;

  name = var.cgw_Name

  customer_gateways = {
    IP1 = {
      bgp_asn    = var.asn_Azure
      ip_address = var.vgw_publicip_1
    },
    IP2 = {
      bgp_asn    = var.asn_Azure
      ip_address = var.vgw_publicip_2
    }
  }
}

module &quot;vpngw1&quot; {
  source = &quot;../../modules/aws/vpngw-3.7.2/&quot;

  customer_gateway_id               = module.cgw.ids&#x5B;0]
  vpc_id                            = module.vpc.vpc_id
  vpn_gateway_id                    = module.vpc.vgw_id
  vpn_connection_static_routes_only = false
  local_ipv4_network_cidr           = &quot;0.0.0.0/0&quot;

  tunnel1_inside_cidr   = var.ip_AWST1A0
  tunnel2_inside_cidr   = var.ip_AWST2A0
  tunnel1_preshared_key = var.key_SharedKey
  tunnel2_preshared_key = var.key_SharedKey

  tags = {
    Name = var.vpn_AWSA0Name
  }

  depends_on = &#x5B;module.cgw]

}

module &quot;vpngw2&quot; {
  source = &quot;../../modules/aws/vpngw-3.7.2/&quot;

  customer_gateway_id               = module.cgw.ids&#x5B;1]
  vpc_id                            = module.vpc.vpc_id
  vpn_gateway_id                    = module.vpc.vgw_id
  vpn_connection_static_routes_only = false
  local_ipv4_network_cidr           = &quot;0.0.0.0/0&quot;

  tunnel1_inside_cidr   = var.ip_AWST1A1
  tunnel2_inside_cidr   = var.ip_AWST2A1
  tunnel1_preshared_key = var.key_SharedKey
  tunnel2_preshared_key = var.key_SharedKey

  tags = {
    Name = var.vpn_AWSA1Name
  }

  depends_on = &#x5B;module.cgw]

}
</pre>
<p><strong>variables.tf &#8211; replace the IPs in line 50 and 59 from the previous Azure output</strong></p>
<pre class="brush: bash; collapse: true; highlight: [50,59]; light: false; title: ; toolbar: true; notranslate">
# VPC
variable &quot;rgn_RegionLocation&quot; {
  type        = string
  default     = &quot;us-east-2&quot;
  description = &quot;AWS region&quot;
}

variable &quot;vpc_Name&quot; {
  type        = string
  default     = &quot;vpcVPN&quot;
  description = &quot;Name of the VPC in AWS&quot;
}

variable &quot;vpc_CIDR&quot; {
  type        = string
  default     = &quot;10.2.0.0/16&quot;
  description = &quot;CIDR of the VPC in AWS&quot;
}

variable &quot;vpc_AZs&quot; {
  type        = list(string)
  default     = &#x5B;&quot;us-east-2a&quot;]
  description = &quot;Location of available zones&quot;
}

variable &quot;sub_pubCIDR&quot; {
  type        = list(string)
  default     = &#x5B;&quot;10.2.0.0/24&quot;]
  description = &quot;Public subnet CIDR&quot;
}

variable &quot;sub_pvtCIDR&quot; {
  type        = list(string)
  default     = &#x5B;&quot;10.2.1.0/24&quot;]
  description = &quot;Private subnet CIDR&quot;
}

# Customer gateways
variable &quot;cgw_Name&quot; {
  type        = string
  default     = &quot;cgwVPN&quot;
  description = &quot;Name of the Customer Gateway&quot;
}

####
#### REPLACE WITH OUTPUT FROM AZURE
####
variable &quot;vgw_publicip_1&quot; {
  type        = string
  default     = &quot;20.10.220.96&quot;
  description = &quot;Use the output from previous Azure script. First public IP of the Virtual Network Gateway in Azure&quot;
}

####
#### REPLACE WITH OUTPUT FROM AZURE
####
variable &quot;vgw_publicip_2&quot; {
  type        = string
  default     = &quot;4.152.124.252&quot;
  description = &quot;Use the output from previous Azure script. Second public IP of the Virtual Network Gateway in Azure&quot;
}

variable &quot;asn_AWS&quot; {
  type        = string
  default     = &quot;64512&quot;
  description = &quot;AWS ASN&quot;
}

variable &quot;asn_Azure&quot; {
  type        = string
  default     = &quot;65000&quot;
  description = &quot;Azure ASN&quot;
}

# VPN site to site 1
variable &quot;key_SharedKey&quot; {
  type        = string
  default     = &quot;KlimentAndreev1970_&quot;
  description = &quot;Make sure it&#039;s the same as vartiables.tf in  Azure folder&quot;
  # Don&#039;t go crazy with complexity. AWS side can support only 
  # between 8 and 64 characters in length and cannot start with zero (0). 
  # Allowed characters are alphanumeric characters, periods (.), and underscores (_).

}

variable &quot;vpn_AWSA0Name&quot; {
  type        = string
  default     = &quot;vpnToAzureInstance0&quot;
  description = &quot;AWS Tunnel to Azure Instance 0 name&quot;
}

variable &quot;ip_AWST1A0&quot; {
  type    = string
  default = &quot;169.254.21.0/30&quot;
}

variable &quot;ip_AWST2A0&quot; {
  type    = string
  default = &quot;169.254.22.0/30&quot;
}

# VPN site to site 2
variable &quot;vpn_AWSA1Name&quot; {
  type        = string
  default     = &quot;vpnToAzureInstance1&quot;
  description = &quot;AWS Tunnel to Azure Instance 1 name&quot;
}

variable &quot;ip_AWST1A1&quot; {
  type    = string
  default = &quot;169.254.21.4/30&quot;
}

variable &quot;ip_AWST2A1&quot; {
  type    = string
  default = &quot;169.254.22.4/30&quot;
}
</pre>
<p><strong>outputs.tf</strong></p>
<pre class="brush: bash; title: ; notranslate">
output &quot;ip_AWST1A0&quot; {
  value = module.vpngw1.vpn_connection_tunnel1_address
}

output &quot;ip_AWST2A0&quot; {
  value = module.vpngw1.vpn_connection_tunnel2_address
}

output &quot;ip_AWST1A1&quot; {
  value = module.vpngw2.vpn_connection_tunnel1_address
}

output &quot;ip_AWST2A1&quot; {
  value = module.vpngw2.vpn_connection_tunnel2_address
}
</pre>
<p>Once you run <em>terraform apply</em> you&#8217;ll get 4 IPs as an output.</p>
<pre class="brush: bash; title: ; notranslate">
ip_AWST1A0 = &quot;3.137.10.4&quot;
ip_AWST1A1 = &quot;3.20.47.74&quot;
ip_AWST2A0 = &quot;18.220.233.198&quot;
ip_AWST2A1 = &quot;18.190.37.23&quot;
</pre>
<p>You have to go back and replace these 4 IPs in <strong>variables.tf</strong> in the previous Azure folder. So, you run <em>terraform apply</em> in <strong>01.Azure</strong> folder first, then <strong>02.AWS</strong> second and then again <em>terraform apply</em> in <strong>01.Azure</strong>.</p>
<h1>Azure</h1>
<p>Edit<strong> variables.tf</strong> file and add the 4 IPs. Make sure that the variables match, do not just assign IPs randomly. Replace the IPs in the lines 155, 196, 237 and 278. The second time you run <em>terraform apply</em> it will take about a minute or two.</p>
<h1>Verification</h1>
<p>Now, go to AWS and go to <strong>VPC | VPN | Site-to-Site VPN connections</strong>. You&#8217;ll see two tunnels there. For each one select the tunnel and then click on the <strong>Tunnel details</strong> tab. Both should be up for each tunnel.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2024/10/P175-03.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2024/10/P175-03-1024x241.png" alt="" width="1024" height="241" class="aligncenter size-large wp-image-10018" srcset="https://blog.andreev.it/wp-content/uploads/2024/10/P175-03-1024x241.png 1024w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-03-300x71.png 300w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-03-768x181.png 768w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-03-1170x275.png 1170w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-03-585x138.png 585w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-03.png 1236w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><br />
In Azure, go to <strong>Virtual Network Gateways</strong>, click on the vgw, then <strong>Monitoring </strong>and <strong>BGP peers</strong>.<br />
You should see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2024/10/P175-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2024/10/P175-04-1024x538.png" alt="" width="1024" height="538" class="aligncenter size-large wp-image-10020" srcset="https://blog.andreev.it/wp-content/uploads/2024/10/P175-04-1024x538.png 1024w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-04-300x158.png 300w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-04-768x404.png 768w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-04-1536x808.png 1536w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-04-1170x615.png 1170w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-04-585x308.png 585w, https://blog.andreev.it/wp-content/uploads/2024/10/P175-04.png 1571w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2024/10/aws-azure-site-to-site-s2s-vpn-tunnel-between-aws-and-azure/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
