*Configuring VPC Peering Between Two VPCs
Summary
In this lab I connected two separate VPCs in different AWS regions so that their EC2 instances could talk to each other privately. I created CA-VPC in Canada (Central) and US-VPC in US East (Ohio), each with a non-overlapping CIDR block, a private subnet, and an EC2 instance with no public IP. At first, a ping from one instance to the other failed, because separate VPCs are isolated from each other by default. I then created a VPC peering connection between the two VPCs, accepted it in the other region, and added a route in each VPC's route table pointing to the other VPC through the peering connection. After that, the instances could reach each other using only their private IP addresses, without an Internet Gateway or any public IPs.
Architecture
| Canada side | US side | |
|---|---|---|
| Region | Canada (Central) ca-central-1 | US East (Ohio) us-east-2 |
| VPC | CA-VPC, 192.168.0.0/24 | US-VPC, 192.168.1.0/24 |
| Subnet | CA-Subnet, 192.168.0.0/24, ca-central-1a | US-Subnet, 192.168.1.0/24, us-east-2a |
| Instance | CA-Server, no public IP | US-Server, no public IP |
| Security group inbound | All traffic, SSH | All traffic, SSH |
| Route added | 192.168.1.0/24 → peering connection | 192.168.0.0/24 → peering connection |
| Resource | Details |
|---|---|
| Peering connection | CA-US |
| Requester | CA-VPC in ca-central-1 |
| Accepter | US-VPC in us-east-2 |
| Access method | EC2 Instance Connect Endpoint in CA-VPC |
Both VPCs were in the same AWS account, but the same process works for VPCs in different accounts.
Part 1: Setting Up the Canada Side
1. Created CA-VPC
I switched the console to Canada (Central), opened the VPC console, and clicked Create VPC. I chose VPC only, named it CA-VPC, and gave it the IPv4 CIDR block 192.168.0.0/24.
2. Created CA-Subnet
Under Subnets, I clicked Create subnet, selected CA-VPC, and entered:
| Setting | Value |
|---|---|
| Subnet name | CA-Subnet |
| Availability Zone | ca-central-1a |
| IPv4 subnet CIDR | 192.168.0.0/24 |
I didn't create an Internet Gateway for this VPC, so CA-Subnet was a private subnet with no path to the internet.
3. Launched CA-Server
In the EC2 console, I launched an instance named CA-Server in CA-VPC and CA-Subnet, with Auto-assign public IP set to Disable. I created a security group with two inbound rules:
| Type | Protocol | Port | Source |
|---|---|---|---|
| All traffic | All | All | 0.0.0.0/0 |
| SSH | TCP | 22 | 0.0.0.0/0 |
Allowing all traffic meant the security group wouldn't get in the way while I tested connectivity between the VPCs, so any failure would come from the network itself. Once the instance was running, its Networking tab showed a private IPv4 address in 192.168.0.0/24 and no public IP.
Part 2: Setting Up the US Side
1. Created US-VPC
I switched the console to US East (Ohio) and created a second VPC named US-VPC with the CIDR block 192.168.1.0/24.
The two VPCs needed different, non-overlapping CIDR blocks. VPC peering doesn't work between VPCs whose address ranges overlap, because a route table couldn't tell which VPC an address like 192.168.0.10 belonged to.
2. Created US-Subnet
I created a subnet in US-VPC:
| Setting | Value |
|---|---|
| Subnet name | US-Subnet |
| Availability Zone | us-east-2a |
| IPv4 subnet CIDR | 192.168.1.0/24 |
3. Launched US-Server
I launched an instance named US-Server in US-VPC and US-Subnet, with Auto-assign public IP disabled and a security group with the same two inbound rules as the Canada side: All traffic and SSH, both from 0.0.0.0/0. I noted its private IPv4 address in 192.168.1.0/24.
Part 3: Confirming the VPCs Were Isolated
1. Connected to CA-Server
Neither instance had a public IP, so I couldn't SSH into them from my computer. Back in Canada (Central), I created an EC2 Instance Connect Endpoint in CA-VPC, using CA-Subnet, and waited for it to become Available. Then I selected CA-Server, clicked Connect, and connected through the endpoint using its private IP.
2. Tried to ping US-Server
From CA-Server, I pinged US-Server's private IP:
ping US_SERVER_PRIVATE_IPThe ping failed with no replies. Even though both VPCs were in the same AWS account, they were completely separate networks. CA-VPC's route table only had its local route for 192.168.0.0/24, so it had no idea where to send traffic for 192.168.1.0/24.
Part 4: Creating the Peering Connection
1. Sent the peering request
- In Canada (Central), I opened the VPC console and went to Peering connections.
- I clicked Create peering connection and named it
CA-US. - Under VPC ID (Requester), I selected
CA-VPC. - Under Select another VPC to peer with, I chose My account and Another Region, then selected US East (Ohio).
- For VPC ID (Accepter), I pasted the VPC ID of
US-VPC, which I'd copied from the Ohio region's VPC console. The console can't list VPCs from another region in a dropdown, so the ID had to be entered by hand. - I clicked Create peering connection.
The connection's status was Pending acceptance. A peering connection is a two-sided agreement, so creating the request wasn't enough on its own.
2. Accepted the request
I switched to US East (Ohio), opened Peering connections, selected the pending CA-US request, and clicked Actions → Accept request.
I waited until the connection's status showed Active in both regions.
Part 5: Updating the Route Tables
An active peering connection is like a bridge between the two VPCs, but traffic won't cross it until each VPC's route table says to use it. Each side needed a route pointing to the other VPC's CIDR block.
1. Canada side
In Canada (Central), I opened the route table associated with CA-Subnet, went to the Routes tab, clicked Edit routes, and added:
| Destination | Target |
|---|---|
192.168.1.0/24 | Peering Connection → CA-US |
2. US side
In US East (Ohio), I opened the route table associated with US-Subnet and added:
| Destination | Target |
|---|---|
192.168.0.0/24 | Peering Connection → CA-US |
Both routes showed Active. Each VPC now knew to send traffic for the other VPC's address range through the peering connection.
Part 6: Verifying Private Communication
Back on CA-Server, I ran the same ping again:
ping US_SERVER_PRIVATE_IPThis time US-Server replied. The two instances were communicating across regions using only their private IP addresses. The traffic traveled over AWS's own network through the peering connection, without any Internet Gateway, NAT Gateway, or public IP.
What I Learned
- VPCs are isolated by default, even when they're in the same AWS account. Resources in one VPC can't reach another VPC unless a connection is set up.
- VPC peering is a private connection between exactly two VPCs. It works between VPCs in the same region, in different regions, and in different AWS accounts.
- The two VPCs must have non-overlapping CIDR blocks. That's why one VPC used
192.168.0.0/24and the other192.168.1.0/24. - Peering is a request and accept process. The requester VPC's owner sends the request, and the accepter VPC's owner has to approve it before the connection becomes active.
- An active peering connection does nothing on its own. Both VPCs need a route to the other VPC's CIDR block with the peering connection as the target, and security groups on both sides still need to allow the traffic.
- Peering is not transitive. If VPC A is peered with B, and B is peered with C, A still can't reach C through B. A would need its own peering connection to C. For many VPCs, a Transit Gateway is easier than peering every pair.
- Traffic between peered VPCs stays on the AWS network and never crosses the public internet, even between regions.
Notes
- Both security groups allowed all traffic from anywhere to keep testing simple. In a real setup, each side would allow only the specific ports it needs, and only from the other VPC's CIDR block, such as
192.168.1.0/24. - The peering connection itself is free, but data transferred between regions over it is billed per GB. Data between peered VPCs in the same Availability Zone is free, and other same-region traffic is billed at a lower rate.
Cleanup
This lab created resources in two regions, so I had to switch regions to clean up each side. Running instances are billed by the hour, and everything else would otherwise clutter my account.
1. Deleted the peering connection
In Canada (Central), I went to Peering connections, selected CA-US, clicked Actions → Delete peering connection, and confirmed. Deleting it from one side removes it from both regions.
2. Removed the peering routes
The routes that pointed to CA-US now showed Blackhole, because their target was gone. In each region, I opened the subnet's route table, clicked Edit routes, removed the peering route, and saved. These would also disappear when the VPCs were deleted, but removing them kept things tidy.
3. Deleted the EC2 Instance Connect Endpoint
In Canada (Central), under Endpoints, I selected the EC2 Instance Connect Endpoint, clicked Actions → Delete VPC endpoints, and confirmed. A VPC can't be deleted while it still has an endpoint.
4. Terminated both instances
In the EC2 console, I terminated CA-Server in Canada (Central), then switched to US East (Ohio) and terminated US-Server. I waited until both showed Terminated.
5. Deleted the security groups
In each region, I went to Security Groups, filtered by the lab's VPC, and deleted the security group created for the instance.
6. Deleted the subnets and VPCs
In Canada (Central), I deleted CA-Subnet and then CA-VPC. In US East (Ohio), I deleted US-Subnet and then US-VPC. Deleting each VPC also removed its main route table, network ACL, and default security group.
7. Confirmed nothing was left
In both regions, I checked that Peering connections, Endpoints, Instances, and Your VPCs didn't show anything from this lab. I made sure not to delete the default VPC in either region, or myfirst-vpc from the earlier labs.