In this exercise we will set up VPC peering within the same region. We will experiment with routes, referencing security groups in different VPCs, overlapping CIDRs, and transitive routing.
In this exercise we will not complicate matters with private subnets and NAT. Instead, we will use public subnets only.
This is exercise 1.2 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.
Creating three VPCs in one region
We will get started by creating three VPCs, called
ans-exercise-1.2-vpc-c. We will use the CIDR ranges
The easiest way to launch VPCs is to use the Launch VPC Wizard. To start the wizard, open the VPC console, navigate to the VPC Dashboard and click the “Launch VPC Wizard” button.
Select the “VPC with a Single Public Subnet” option and fill in the details as follows.
Click “Create VPC” and repeat for the other two VPCs. The end result should look like this:
Adding EC2 instances
Launch an EC2 instance in every VPC. They can be small instances (eg. t2.micro). Make sure that you:
- assign a public IP address to every instance
- assign a descriptive Name tag to the instances
- open port 22 to your IP address
- configure the key pair so you can SSH to the instance
You will find that you have to create three separate security groups, because each security group is bound to a specific VPC.
When you’re done, you should have an overview like this:
Start SSH sessions and test connectivity between the instances
Log in to every instance and try to ping the other instances. Of course this won’t work, because the VPCs are in no way linked, and the instances live in completely separate subnets.
[[email protected]10-0-0-82 ~]$ ping -c 1 192.168.0.223 PING 192.168.0.223 (192.168.0.223) 56(84) bytes of data. --- 192.168.0.223 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms [[email protected]10-0-0-82 ~]$ ping -c 1 172.16.0.8 PING 172.16.0.8 (172.16.0.8) 56(84) bytes of data. --- 172.16.0.8 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms
Set up VPC Peering
We will set up VPC Peering so that VPC B is connected to A and C, but C and A are not connected.
Open the VPC Console and click Peering Connections. Then click the “Create Peering Connection” button.
Fill in the fields to connect VPC A to VPC B.
After you’ve filled in the details and clicked the “Create Peering Connection” button, you will find a peering connection pending acceptance. Click the Actions button and accept the request.
Repeat the same steps to set up a connection between VPC B and C.
Setting up routing
When you accept the peering connections, you will see a popup like this:
The message says “To send and receive traffic across this VPC peering connection, you must add a route to the peered VPC in one or more of your VPC route tables.”, so let’s do that now.
We will need to set up the following routes:
- VPC A needs to know how to reach VPC B
- VPC B needs to know how to reach VPC A
- VPC B needs to know how to reach VPC C
- VPC C needs to know how to reach VPC B
The Route Table tab contains an overview of all route tables in all VPCs. This is a bit hard to parse, so we’ll navigate to the Subnets tab instead. Select the VPC A subnet and click the Route Table tab in the bottom.
From here, click the route table link (
rtb-01adcee467c0bd700 in my screenshot). This will filter the correct route table in the Route Table tab. Click the Routes tab in the bottom, then click the “Edit Routes” button.
Click the “Add route” button and fill in the CIDR for VPC B (
192.168.0.0/16). Then select the peering connection between A and B. This will tell the AWS implicit router that any traffic for the
192.168.0.0/16 CIDR should be routed over this peering connection.
Go back to the Subnets tab and select the VPC B subnet. Like before, click the Route Table tab in the bottom and click the link to the correct route table.
Because VPC B is connected to both VPC A and C, we will need to add two routes to this route table. Make sure that you forward traffic for a CIDR to the correct peering connection.
When you’ve set up the peering connections for VPC B, finish up by adding the last route to VPC C’s route table.
Note: you could theoretically select a smaller range for a peering connection. For example, we could route
192.168.0.0/24from VPC A to B, instead of
192.168.0.0/16. However, VPC Peering is limited to exactly one peering connection between two VPCs. So in this example, we would not be able to also route
192.168.1.0/24from VPC A to VPC B.
Accepting traffic in the security groups
After setting up the routes in the previous step, the routers ‘know’ how to send traffic between the VPCs. However, we have not allowed any traffic between the instances yet. Let’s do that now.
Navigate to the instance in VPC B in the EC2 console and select its security group.
Then click the Inbound tab and press the Edit button.
Click the Add Rule button twice and fill in the following rules, allowing ping traffic from VPCs A and C.
Now SSH back into the instance in VPC A, and try to ping the instance in VPC B again.
[[email protected] ~]$ ping -c 1 192.168.0.223 PING 192.168.0.223 (192.168.0.223) 56(84) bytes of data. 64 bytes from 192.168.0.223: icmp_seq=1 ttl=255 time=0.452 ms --- 192.168.0.223 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.452/0.452/0.452/0.000 ms
As you can see, this works perfectly!
Allowing access by security group
In the previous step we’ve allowed the instance in VPC A to ping the instance in VPC B. We’ve done this by whitelisting VPC A’s entire CIDR on the instance in VPC B.
Now let’s allow the instance in VPC B to ping the instance in VPC A as well, but do it by whitelisting the instance’s security group.
First, look up and copy the security group ID for the instance in VPC B:
Then select VPC A’s instance security group:
Navigate to the Inbound tab and click Edit again:
Fill in the the security group ID for the instance in VPC B that you just copied:
Click Save and open an SSH connection to the instance in VPC B. From there, try to ping the instance in VPC A. If all was configured well, this should succeed!
__| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ 5 package(s) needed for security, out of 13 available Run "sudo yum update" to apply all updates. [ec2-user@ip-192-168-0-223 ~]$ ping -c 1 10.0.0.82 PING 10.0.0.82 (10.0.0.82) 56(84) bytes of data. 64 bytes from 10.0.0.82: icmp_seq=1 ttl=255 time=0.394 ms --- 10.0.0.82 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.394/0.394/0.394/0.000 ms
A quick overview of what we’ve built so far:
Note: Referencing security groups by ID like we’ve done above only works within the same region. See the last chapter in this post for an example.
Since our VPCs are connected like this:
A <-> B <-> C, you might expect that it would be possible to connect from an instance in VPC A to an instance in VPC C too. However, this is not the case. The implicit router for each VPC will only allow traffic when either the source or the destination IP address resides in the VPC.
A few examples:
- VPC B will accept an inbound connection from
192.168.0.223, because the
192.168.0.223address resides in the
- VPC A will accept an outbound connection from
192.168.0.223, because the
10.0.0.82address resides in the
- VPC B will reject an inbound connection from
172.16.0.8, because neither address resides in the
There are three solutions for this problem:
- Create a VPC peering between VPC A and C.
- Create a VPN overlay network.
- Use Transit Gateway, a technology built for transitive traffic.
VPC star pattern peering
When you have only three VPCs, a link between VPC A and VPC C makes sense and is perfectly manageable. However, as the number of VPCs grow, the number of VPC peerings grow exponentially. See the diagram with five VPCs below; it requires 10 peering connections. Six VPCs would require 15 connections. Seven VPCs require 21 connections, and so on. This is a lot to maintain.
Because managing this architecture is difficult, network architects have opted for a simpler solution; the VPN overlay network.
VPN overlay network
In a VPN overlay network, all VPCs or EC2 instances connect to a central VPN server in a Transit VPC. All inter-VPC traffic is routed over the VPN server, which in turn routes the traffic to the correct VPC.
Because the VPNs are set up using the VPN server’s IP address, the VPC sees inbound traffic is targeted at an IP address in its own CIDR, and will allow it.
The VPN Server does not have the same source-destination-check restrictions the VPC does (although you have to disable the check on the EC2 instance), so it can route traffic between CIDRs that are not its own.
The downside of this solution is that you need to manage and scale an EC2 based VPN server. To solve this issue, Amazon has released Transit Gateway.
Transit Gateway is a technology that allows multiple VPCs, VPNs and Direct Connect to connect to a single gateway. This gateway does not have any source-destination restrictions, and can be configured to route entire CIDRs, partial CIDRs or no traffic between it associated networks. It is fully managed by Amazon and has a very high bandwidth capacity.
Create a new VPC (called
ans-exercise-1.2-vpc-d) and assign the
10.0.0.0/16 CIDR to it. This is the same CIDR as VPC A.
Next, try to create a VPC peering between VPC A and D:
This will result in an error
A peering connection cannot be created between 2 VPCs that have overlapping CIDRs. Please select 2 VPCs which have distinct CIDRs.:
Because AWS does not allow you to override the local route, or to create a route more specific than the local route, it would be impossible to create a route to the peered VPC. As such, creating this peering connection will always be useless and is therefore blocked.