AWS Site-to-Site VPN (IV)

So far in the AWS Networking series, we have covered VPCs, subnets, route tables, Internet Gateways, NAT Gateways, EC2 instances, Security Groups, Network ACLs, and Elastic Network Interfaces. In this post, we will look at using a Site-to-Site VPN in AWS so you can securely connect your on-premise workloads to and from your AWS environment. This is a very important aspect of AWS networking, and this is a service you will use almost always.

If you have been following the series, you can easily follow along with this post. If you just stumbled upon this post, you can still continue, assuming you are already familiar with AWS networking basics. However, if you are completely new to AWS, I highly recommend checking out the previous posts linked below.

AWS Networking Fundamentals
If you’re brand new to AWS, don’t worry. This post focuses on the basics of AWS networking. General networking knowledge is helpful but not required - I’ll try to explain things clearly so everyone can follow along.

Why Do We Need a VPN to AWS?

When we launch an instance in a public subnet with a public IP address, we have seen that we can connect to it directly from the Internet. But what about instances in private subnets that do not have a public IP? How do we access them for management? Even for the instances in public subnets, accessing them through the Internet is not always desirable. Ideally, we want to securely connect to all of our instances using their private IP addresses, just as if they were in our own data centre. This is where the AWS Site-to-Site VPN comes in.

AWS NAT Gateway and Private/Public Subnets
When working with AWS networking, you will often hear the terms ‘public subnet’ and ‘private subnet’. However, if you go into the AWS console to create a subnet, you won’t find any option to explicitly make it one or the other.

An AWS Site-to-Site VPN creates a secure and encrypted connection, often called a 'tunnel', between your on-premise network (like your office or data centre) and your AWS VPC over the public Internet. This connection extends your private network into the cloud.

Once the tunnel is established, it allows you to communicate with your EC2 instances or any other resources using their private IP addresses directly from your on-premise workloads. For your on-premise network, the VPC effectively appears as just another part of your internal network.

AWS Site-to-Site VPN Concepts

To create a VPN connection, you first need a compatible IPsec VPN device, like a firewall or router, at your on-premise location. In AWS, the resource you create to represent this device is called a Customer Gateway. The Customer Gateway is essentially a placeholder object in your AWS account where you store information about your on-premise device, most importantly, its public IP address.

On the AWS side of the connection, we need a different type of gateway. You will remember that we routed Internet traffic to an Internet Gateway or NAT Gateway. To send traffic from your VPC to your on-premise network, you route it to a Virtual Private Gateway (VGW). The VGW is a logical, redundant resource on the AWS side of the connection that you attach to your VPC. It serves as the target in your route tables for any traffic destined for your on-premise network.

If you create an AWS Site-to-Site VPN connection, you are charged for each 'VPN connection-hour' for which your connection is provisioned and available. The rate is approximately $0.05 per Site-to-Site VPN connection per hour. In addition to this, any data transferred out from AWS over the VPN connection also incurs standard data transfer charges.

💡
It is worth noting that a Site-to-Site VPN is not the only way to connect your on-premise network to AWS. For use cases that require higher bandwidth and a more consistent network experience, AWS also offers a dedicated service called Direct Connect, which we will cover later in this series.

AWS Provides Two Tunnels

When you create a single VPN connection, AWS automatically provisions two distinct VPN tunnels for you. This is done to ensure high availability for the connection between your on-premise network and your VPC.

Each of these two tunnels terminates on a separate, redundant endpoint within the AWS network. These endpoints are located in different Availability Zones to protect against an issue affecting a single data centre. Your on-premise device should be configured to connect to both of these tunnel endpoints to take full advantage of this fault-tolerant design.

Static Routing vs BGP

When you set up a Site-to-Site VPN, you have to choose between static and BGP routing. The choice between static and dynamic (BGP) routing primarily affects how your VPN connection handles failover and maintenance.

With static routing, you must manually configure a route on your on-premise device (the Customer Gateway). This route specifies that to reach the AWS VPC's CIDR block, the next-hop is the VPN tunnel interface. Because this route is static, your device won't automatically know if the tunnel is down. You have to rely on a separate feature on your device, like 'tunnel monitoring', to detect a failure and switch traffic over to the second, redundant tunnel provided by AWS.

With dynamic (BGP) routing, you do not configure static routes for the VPC prefixes. Instead, BGP automatically exchanges routing information and offers robust liveness detection checks. These checks can detect if the tunnel goes down or degrades.

Creating a VPN Tunnel

Now that the theory is out of the way, let's go and create the VPN connection. We will first create a tunnel using static routes to see how that works, and then later in the post, we will also look at using BGP.

Creating the Customer Gateway

The first step is to create the Customer Gateway. To do this, navigate to the VPC service console and select 'Customer Gateways' from the menu under 'Virtual Private Network (VPN)'.

Here, you will create a resource that represents your on-premise device. You need to give it a descriptive name, like my-site-01, and provide its BGP ASN. For most setups, you will use a private ASN, and you can choose any number from the private range of 64512 to 65534; in this example, I'm using the default 65000. Finally, you must input the public IP address of your on-premise firewall or router, which I have masked in the screenshot 🙂

Creating the Virtual Private Gateway (VGW)

Similar to the Customer Gateway, the next step is to create the Virtual Private Gateway (VGW) on the AWS side. From the VPC console, navigate to 'Virtual Private Gateways' under the 'Virtual Private Network (VPN)' section and choose to create a new one.

You only need to give it a name, like lab-vgw-01, and you can leave the 'Autonomous System Number (ASN)' set to the 'Amazon default ASN', which will assign a private ASN for you.

When a VGW is first created, it exists as a standalone resource, and its state will show as 'detached'.

You must then perform a second action to attach it to the VPC that you want to connect with your on-premise network. To do this, select the VGW, choose 'Attach to VPC' from the Actions menu, and then select your VPC from the list. Once the attachment is complete, the VGW is ready to be used as a routing target for your VPC.

Creating a VPN Connection (Static)

To begin creating the VPN, navigate to the 'Site-to-Site VPN connections' section within the VPC console and click 'Create VPN connection'. This will open a configuration wizard. You'll give the connection a descriptive name, like lab-vpn, and then select the Virtual Private Gateway (VGW) and the Customer Gateway (CGW) that we created in the previous steps.

For this example, we will select 'Static' for the routing options and manually enter the IP prefixes for our on-premise network, which we want the VPC to be able to communicate with.

Further down the page, you can configure the specific options for each of the two tunnels. A key requirement for the VPN to work is that each tunnel has its own internal IP addresses for routing.

These IPs must come from the 169.254.0.0/16 address range, with each tunnel needing a /30 CIDR block for its point-to-point connection. You can either enter these manually or leave them blank for AWS to generate them for you.

💡
When choosing the inside IP addresses for the VPN tunnels, be aware that AWS reserves some specific ranges. You cannot use the following CIDR blocks - 169.254.0.0/30, 169.254.1.0/30, 169.254.2.0/30, 169.254.3.0/30, 169.254.4.0/30, 169.254.5.0/30, and 169.254.169.252/30.

You will also see that AWS generates a unique Pre-Shared Key (PSK) for each tunnel, which is used for authentication.

After you create the connection, the state will change to 'Available', but if you look at the 'Tunnel details' tab, you will notice the status for both tunnels is 'Down'. This is normal and expected because we have only configured the AWS side of the connection. Here you will also see the two public IP addresses to which we will establish the VPN.

To complete the setup, you can select the VPN connection and click the 'Download configuration' button. This allows you to choose your on-premise device vendor and download a configuration file that contains the settings needed to be applied.

If you have dedicated network personnel, they can use this file to provision the VPN on your on-premise device. Please don't expect that you can just download the config and apply it directly, as it's a template and there are a few things you or your team may need to change to fit your specific environment.

Site-to-site VPN between AWS and Palo Alto (Static & BGP)
In this blog post, we’ll look at how to create a site-to-site VPN between AWS and a Palo Alto firewall. We’ll go through both static routing and BGP options.

Update VPC Route Table

Next, you must update your VPC route table to direct traffic destined for your on-premise network through the new VPN connection. You need to add a new route where the destination is your on-premise network's IP prefix (in our case, 10.10.0.0/24) and the target is the Virtual Private Gateway (VGW).

For testing, I have launched an EC2 instance in the private subnet with the IP 10.200.10.187. Also keep an eye on the 'Propagated' column, which says 'No' for our static route; we will look at what this means next.

Route Propagation

When you attach a Virtual Private Gateway to your VPC, you can enable a feature called 'Route Propagation' on your route tables. If you enable this, AWS will automatically add the routes for your VPN connection to your route table. This means that you do not need to manually add or remove the static routes for your on-premise network.

To show you how this works, I have removed the static route (10.10.0.0/24) that we just added to the lab-private-rt-a route table.

Then, as shown in the image, I navigated to the 'Route Propagation' tab for that same route table and enabled propagation from our Virtual Private Gateway. As soon as this was enabled, the exact same route to 10.10.0.0/24 pointing to the VGW popped up again automatically. The only difference is that the 'Propagated' column now says 'Yes'.

You might wonder how AWS knew which route to add. It's because when we configured the static VPN connection, we specified 10.10.0.0/24 as our on-premise IP prefix. Therefore, you can either keep propagation disabled and add the static route manually or enable propagation and let AWS manage the route for you.

Verification and Testing

I have now configured the other side of the connection on my on-premise Palo Alto firewall, and after a few moments, the tunnel status in the AWS console changed to 'Up'.

Since we are using a static route, it is normal for only one of the two tunnels to be in the 'Up' state. To test the connection, I initiated a ping and an SSH connection from my on-premise network to an EC2 instance in our private subnet, and both were successful.

ping 10.200.10.187
PING 10.200.10.187 (10.200.10.187): 56 data bytes
64 bytes from 10.200.10.187: icmp_seq=0 ttl=126 time=19.457 ms
64 bytes from 10.200.10.187: icmp_seq=1 ttl=126 time=15.326 ms
64 bytes from 10.200.10.187: icmp_seq=2 ttl=126 time=16.355 ms
^C
--- 10.200.10.187 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 15.326/17.046/19.457/1.756 ms
ssh -i lab-key-1.pem ec2-user@10.200.10.187 
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
Last login: Tue Jul  1 11:15:17 2025 from 10.10.0.140
[ec2-user@ip-10-200-10-187 ~]$

Creating a VPN Connection (BGP)

Now that we have looked at a VPN connection with a static route, let's see how to create one using BGP. For this lab, I am going to delete the static VPN we created and then create a new one. The process is almost identical, but with one key difference in the routing configuration.

When creating the new VPN connection, I give it a name vpn-bgp and select the same Virtual Private Gateway and Customer Gateway as before. This time, however, for the 'Routing options', I select 'Dynamic (requires BGP)'. You will notice that you no longer need to enter any static IP prefixes. For the tunnel IP addresses, I am manually specifying 169.254.0.12/30 and 169.254.0.16/30 for the two tunnels, but everything else stays the same.

Once the AWS side is configured, you can similarly download the configuration file and apply it to your on-premise firewall. The specifics of the firewall configuration are out of the scope of this post, but I have written a dedicated post on how to configure the Palo Alto side, so feel free to check that out.

Site-to-site VPN between AWS and Palo Alto (Static & BGP)
In this blog post, we’ll look at how to create a site-to-site VPN between AWS and a Palo Alto firewall. We’ll go through both static routing and BGP options.

After configuring the BGP settings on the on-premise firewall, you will need to wait a few minutes for the BGP peering to establish. Once it is successful, you will see the status of both tunnels change to 'Up' in the AWS console. If you look at the details for each tunnel, you will also see an indicator for the BGP routes. In this case, it shows that AWS is receiving '1 BGP ROUTES' because I am only advertising one network prefix from my on-premise device.

BGP Attributes and Path Selection

If you look at the received routes from AWS on the customer gateway (Palo Alto in this example), you’ll notice that the second tunnel has a MED value of 100 and the first tunnel has 200. So, for outbound traffic, the firewall prefers the second tunnel (tunnel.22) with the lowest metric.

Inbound traffic is decided on the AWS side. For inbound traffic (traffic leaving AWS), AWS determines which tunnel to use based on BGP path attributes. If everything is equal, like local preference, AS path, MED, etc, which is the case here since we didn’t customize any of these, AWS will most likely prefer the tunnel with the oldest active route.

If you want full control over both inbound and outbound paths, you can use local preference to control outbound traffic and AS_PATH prepending to influence inbound traffic. However, AWS strongly recommends using customer gateway devices that support asymmetric routing.

For devices that support asymmetric routing, AWS does not recommend using AS_PATH prepending. This ensures both tunnels have equal AS_PATH, and the MED value set by AWS can be used to decide tunnel preference. Since both tunnel interfaces are part of the same zone in the Palo Alto firewall, the firewall allows traffic to go out through one tunnel and return through another. So we don’t need to make any additional changes to handle asymmetric routing in this case.

For devices that do not support asymmetric routing, you can use AS_PATH prepending and local preference to influence paths.

💡
Each AWS Site-to-Site VPN connection has two tunnels and each tunnel supports a maximum throughput of up to 1.25 Gbps.

Closing Thoughts

I hope you now have a good understanding of the concepts behind setting up an AWS Site-to-Site VPN. I have to say that it may be difficult for you to lab this particular topic at home, as it requires having a compatible firewall or router that you can configure.

But don't worry if you don't have the firewall to test this yourself. As long as you understand the components and the process we covered, that is the most important takeaway.