In this exercise we will build a single VPN connection between a VPC and a ‘datacenter’, which we will also host in AWS.
This is exercise 3.1 for the AWS Advanced Networking Specialty training. For an explanation and overview of all exercises, see the overview post.
The exercises are built on the assumption that you’re already familiar with the AWS basics and have achieved at least one associate level AWS certification.
AWS Site-to-Site VPNs are used to create a secure, private connection between AWS and an office location or customer datacenter. The basic setup of a VPN connection into AWS looks like this:
The Customer Gateway is typically a hardware appliance, for example a Cisco ASA, Fortinet Fortigate or Juniper SRX. However, it can also be a software firewall or VPN endpoint like PFSense or Windows 2012 R2.
In this exercise, we will simulate a datacenter in a separate VPC in a different AWS region. Normally you would use VPC Peering for this use case (see ANS Exercise 1.2: VPC Peering), but for the purposes of this exercise we will use Windows 2012 R2 running on EC2 as a customer gateway.
This exercise will focus on static routing only. Dynamic routing with BGP will be covered in another exercise.
Datacenter VPC setup
Let’s start by creating the Datacenter VPC. Navigate to the VPC console and choose a region near you. On the VPC Dashboard, click the Launch VPC Wizard button.
Then select the first option (VPC with a Single Public Subnet) and click Select.
Keep all the default settings (including the IP range), but give the VPC a recognizable name like ‘ans-exercise-3-1-datacenter’. Then click Create.
AWS VPC setup
Next we’ll build the AWS VPC. This VPC will not connect to the internet at all, the instances in it will only be accessible through VPN.
We will not use the VPC Wizard to create this VPC. Navigate to the VPC console and select another region than used for the Datacenter VPC. Then select Your VPCs on the left, and click the Create VPC button.
Give the VPC a recognizable name, for example ‘ans-exercise-3-1-aws-vpc’, and a CIDR block that is different from the one above, like 10.1.0.0/16. Then click Create.
Then select the Subnets tab on the left and click Create Subnet:
In the next screen, give the subnet a name, select your AWS VPC and define a CIDR block (eg. 10.1.0.0/24). Click the Create button.
Next, select the Virtual Private Gateways section on the left of the VPC console and click the Create Virtual Private Gateway button.
Name the VGW ‘ans-exercise-3-1-aws-vpg’, keep the default ASN and click the Create Virtual Private Gateway button.
Back in the VPC console, select the VGW and attach it to the VPC created in the previous step.
When this is done, we have deployed the components in the following diagram:
Deploying the application EC2 instance
We’ll deploy an EC2 instance into the ‘AWS VPC’. This instance will have no internet connectivity whatsoever, but should, at the end of our exercise, be accessible over VPN.
Select the AWS region containing the AWS VPC (the one with the VGW) and navigate to the AWS EC2 console. Then click the Launch Instance button.
In the next screen, select the Amazon Linux 2 AMI and click the Select button. Select a very small instance (t2.nano or t2.micro) and click the Next: Configure Instance Details button.
In the Configure Instance Details screen, select the AWS VPC and subnet created above.
Click through the Storage and Tags tabs without making changes. In Step 6: Configure Security Group, make sure SSH (port 22) and ‘All ICMP - IPv4’ are allowed from the datacenter’s VPC CIDR block (10.0.0.0/16). This will allow any instance in the datacenter to SSH and Ping this instance.
Click the Review and Launch button, and click the Launch button on the next screen. Make sure you specify a SSH key pair.
Deploying the customer gateway
Navigate to the EC2 console and select the region in which your datacenter VPC resides. Then launch a new instance. In the AMI selection step, search for “Windows 2012” and select the AMI displayed.
Select an instance type for the Windows server. We advice to use at least a t2.medium. Anything less and you’ll be looking at a very slow server.
In Step 3: Configure Instance Details, select your datacenter VPC and subnet, and make sure to enable Auto-assign Public IP.
Again, skip through the Storage and Tags pages. In Step 6: Configure Security Group, make sure your IP is allowed to reach port 3389 (RDP). Also allow all traffic from the local VPC. This will make sure any instance in the datacenter is allowed to send its traffic to the customer gateway.
Click Review and Launch. In the next screen, select Launch and select a valid keypair.
When the instance is launching, it will be assigned a public IP address. You can find this by selecting the instance and looking at its description in the EC2 Console. Copy this address for use in the next step.
With the two instances deployed, our infrastructure looks like this:
Configure the Customer Gateway in AWS
Open the VPC console and navigate back to the region with your AWS VPC. Then select the Customer Gateways tab and click the Create Customer Gateway button.
Give the customer gateway a name, select static routing, and paste the IP address from the previous step. Leave the certificate field empty, and optionally fill in a device name.
Create the Customer Gateway and navigate back to the VPC console. Then select the ‘Site-to-Site VPN Connections’ tab and click the Create VPN Connection button.
In the next step, give the connection a name and select the Virtual Private Gateway created earlier and the Customer Gateway created in the previous step.
Then select Static under Routing Options, and add the datacenter VPC CIDR (10.0.0.0/16).
Leave all the other options on their defaults and create the VPN connection. Back in the VPC console, select the VPN connection and click the Download Configuration button. Select Microsoft Windows 2012 and download the file.
The final step to configure the AWS side is updating the route table for the subnet with our EC2 instance. To do this, navigate to the Route Tables section of the VPC console and select your route table. It should look like this:
Click the Edit Route Propagation button and check the box for your Virtual Gateway. This tells the route table to add any CIDRs known by the VGW. Because we use static routing, this will add the route we defined when we created the VPN connection. Click Save, and navigate to the Routes tab. It should show that traffic for 10.0.0.0/16 is now routed to the VGW.
Configure the Windows Server
Navigate back to the EC2 console and select your Datacenter region. Then select your Windows Server and disable source / destination checking. This allows the instance to receive traffic that is not destined for this server (so it can forward that over VPN).
When that is done, open an RDP session to the server and follow the procedures described under step 3, 4 and 5 of the Configuring Windows Server 2012 R2 as a Customer Gateway Device article. See below for some additional information regarding step 4.
Step 4 - configuration file
Follow Option 1: Run netsh Script. Most of the netsh script can be found in the configuration file downloaded earlier. Adjusted to this exercise, it should look like this:
! Script for Tunnel 1: netsh advfirewall consec add rule Name="vgw-010c99b9c089ac407 Tunnel 1" ^ Enable=Yes Profile=any Type=Static Mode=Tunnel ^ LocalTunnelEndpoint=10.0.0.173 ^ RemoteTunnelEndpoint=18.104.22.168 Endpoint1=10.0.0.0/16 ^ Endpoint2=10.1.0.0/16 Protocol=Any Action=RequireInClearOut ^ Auth1=ComputerPSK Auth1PSK=VXIRDc2aktMMc9NPKEXTCbvACUT7i6Xf ^ QMSecMethods=ESP:SHA1-AES128+60min+100000kb ^ ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2 ! Script for Tunnel 2: netsh advfirewall consec add rule Name="vgw-010c99b9c089ac407 Tunnel 2" ^ Enable=Yes Profile=any Type=Static Mode=Tunnel ^ LocalTunnelEndpoint=10.0.0.173 ^ RemoteTunnelEndpoint=22.214.171.124 Endpoint1=10.0.0.0/16 ^ Endpoint2=10.1.0.0/16 Protocol=Any Action=RequireInClearOut ^ Auth1=ComputerPSK Auth1PSK=Z4oxa_mKADV5E5ksLB4O.1Ei2Dt4mbBC ^ QMSecMethods=ESP:SHA1-AES128+60min+100000kb ^ ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2
Of course, the Name, LocalTunnelEndpoint and RemoteTunnelEndpoint will be different in your situation.
Reboot the server when you have completed step 5.
Verify the tunnel
Navigate to the VPC console and select the region with the AWS VPC. Click the Site-to-Site VPN Connections tab on the left and select your VPN connection. It should show one tunnel UP. If not, wait a few minutes. If the tunnel doesn’t come up, continue with the next step; the tunnel might only come up when traffic is sent. From the AWS Windows 2012 R2 CGW article:
The VPN tunnel comes up when traffic is generated from the customer gateway device, therefore the ping command also initiates the VPN connection.
When the tunnel is up, or when it takes too long to come up, switch back to the RDP session with the Windows server and run
ping 10.1.0.131 from a command prompt (replace this with the IP of your Linux instance). If all went well, you can now connect to the instance on the other side!
As we saw in the previous section, one tunnel is UP, while the other one is down. This is an inherent effect of static routing: there can only be one simultaneous path to a specific address or CIDR. If we want both tunnels to be UP at the same time we would need BGP, but that’s for another exercise. To quote the AWS article:
In the Amazon VPC console, on the VPN Connections page, select your VPN connection. The first tunnel is in the UP state. The second tunnel should be configured, but it isn’t used unless the first tunnel goes down. It may take a few moments to establish the encrypted tunnels.
Add an instance to the datacenter
In the previous sections we have tested connectivity from the Windows Server. However, to create a more realistic representation of a datacenter we should add an additional instance in a separate subnet.
Navigate back to the VPC console for the region in which you created the Datacenter VPC. Then click the Create Route Table button.
In the next screen, give the route table a name and select the Datacenter VPC.
Back in the VPC console, select the route table and click the Edit routes button.
Add a route for
0.0.0.0/0 to the Internet Gateway and a route to
10.1.0.0/16 to the Customer Gateway instance. Because the route table will route traffic to the most specific route, any traffic to 10.1.x.x will be routed to the CGW, all traffic for 10.0.x.x will be routed locally, and all other traffic will be routed to the internet gateway.
Next, create a new subnet in the datacenter VPC. This will host our ‘datacenter application’. Fill in the following details:
When the subnet has been created, select it in the VPC console and click the Edit route table association button.
Then select the route table we just created. This will make sure that any instance in this subnet will use the routes we defined.
The last step is to deploy a new Linux instance in this subnet. Navigate back to the EC2 console and follow the same steps as before to launch a new instance. Use Amazon Linux 2, a small instance type, and make sure you select the right VPC, subnet, and enable Auto-assign Public IP.
In Step 6: Configure Security Group, make sure your IP is allowed to access port 22.
In the review step, make sure you select a valid key pair and launch the instance.
Test connection between Linux instances
SSH into the new Datacenter Linux instance and try to Ping and SSH to the instance in the other VPC and region.
If all went well, the instance in the ‘Datacenter’ can now reach the instance in the AWS VPC, routing its traffic through the Customer Gateway, VPN Tunnel and Virtual Private Gateway.
The full setup we’ve built in this exercise looks like this:
Compare this with the generic VPN diagram at the top of this post, and you’ll see it matches pretty well.
The instances we used (the application servers) in the AWS VPC and the Datacenter are empty shells; they don’t do anything. But it shouldn’t be a stretch of imagination to see how one could host a private REST API and the other one a database, or how instead of a single server the AWS side might actually be a load balancer with an autoscaling group.
We have seen that to successfully route traffic between two instances in separate environments connected by VPN, on the AWS side you need:
- A Virtual Private Gateway
- A definition of the Customer Gateway
- A VPN connection between the VGW and CGW, which consists of two tunnels with a public IP address each
- Route propagation enabled for the subnets that need to send and receive traffic from the VGW
On the datacenter side, you need:
- A routing device, often a physical applicance; the Customer Gateway
- If this is hosted on AWS:
- Source / Destination checking needs to be off
- The firewall needs to allow inbound traffic from instances in the datacenter
- If this is hosted on AWS:
- Routing tables that direct traffic for AWS to the CGW
We have also seen that using static routing, only one tunnel is UP at the same time. This can be resolved with BGP, but this is not easy to achieve with a Windows CGW (or a Linux CGW, for that matter). We will cover this in another exercise.