End Peering Chaos: Build a Simple, Secure Multi-VPC Network with AWS Transit Gateway
Modern AWS environments rarely use just one VPC. As teams grow, more applications and more VPCs appear. If you connect them only with VPC peering, the network becomes complex and hard to manage.
AWS Transit Gateway (TGW) solves this problem. It is like a central router that connects many VPCs together in a hub-and-spoke design. This makes routing simple, scalable, and more secure.
Transit Gateway vs. VPC Peering
VPC Peering: A direct link between two VPCs. It is not transitive. That means if A ↔ B and A ↔ C exist, B and C cannot talk through A. You must build separate peering for every pair. This becomes a mess when you have many VPCs.
Transit Gateway (TGW): A Regional virtual router. You attach VPCs, VPNs, or Direct Connect to it. TGW allows transitive routing. All VPCs connected to the TGW can communicate (if allowed by routes and security rules).
Why TGW?
- Simpler design: one central hub instead of many pair links.
- Scalable: thousands of attachments and routes.
- Secure: traffic flows over AWS backbone, not the public internet.
- Flexible: you can allow or block traffic between selected VPCs.
🧪 Hands-on Lab — 3 VPCs via a Single Transit Gateway
Our Scenario — Three VPCs and One TGW
We want to connect three VPCs with different roles:
- VPC-A (Public/Web) → has Internet access and a web server.
- VPC-B (Private/App) → runs an application server.
- VPC-C (Private/DB) → runs a database server.
Goal:
- We use VPC-A as the entry point (like a bastion).
- From A, we can SSH into B and C using private IPs.
- B and C do not have public IPs.
- Optionally, we can block B↔C traffic to make the design more secure.
Step 1 — Create VPC-A (Public/Web)
VPC → Your VPCs → Create VPC
- VPC only
- Name:
VPC-A - IPv4 CIDR:
10.0.0.0/24
Click on Create VPC button.
Select VPC-A →Actions →Edit Seetings →DNS settings
- Enable DNS hostnames
- Enable DNS resolution
Click on Save button.
Step 2 — Create Public Subnet ( VPC-A)
Subnets → Create subnet
- VPC ID:
VPC-A - Subnet name:
Public_subnet_A - IPv4 subnet CIDR block:
10.0.0.0/25
Click on Create subnet button.
Step 3— Create Internet Gateway and attach to VPC-A
Internet gateways → Create IGW-A
Click on Create internet gateway button.
Actions → Attach to VPC → Select VPC-A
Click on Attach internet gateway button.
Step 4 — Create Route tables ( VPC-A)
Route tables → Create route table
- Name:
PublicRT-A - VPC: Select VPC-A
- Select (VPC-A) → Subnet associations →Edit subnet associations
- Select
Public_subnet_Aand Click on Save associations button.
- Select PublicRT-A → Routes → — Edit Routes
- Add route:
0.0.0.0/0 → IGW-Aand Click on Save chnages button.
Step 5 — Create EC2 Server in VPC-A
Launch a public EC2 in VPC-A
Services →EC2 → Instances →Launch instances
- Name:
A-web - Amazon Linux 2023
- Instance type:
t2.micro
Key Pair (login):
- Create new key pair → Key pair name: ec2_ssh_key
- Type: RSA, File format: .pem
- Click on create key pair button and save to file your PC.
Network settings → Edit:
- VPC: VPC-A
- Subnet: Select Public_subnet_A
- Auto-assign public IP: Enable
- Firewall (SG): Create a new security group
- Security group name: Public_EC2_SG
- Description: Security group for public EC2
Rules:
- SSH → Source: Anywhere (0.0.0.0/0)
- HTTP → Source: Anywhere (0.0.0.0/0)
Select Advanced details →User data (optional):
Copy below the command to the user data box.
#!/bin/bash
dnf -y update
dnf -y install httpd
systemctl enable --now httpd
echo "<h1>VPC-A Web</h1>" > /var/www/html/index.htmlNow Click on launch instance button to create an ec2 instance
You can acces using Server Public IP to Server Web Page.
Step 6— Create VPC-B (Private/App)
VPC → Your VPCs → Create VPC
- VPC only
- Name:
VPC-B - IPv4 CIDR:
20.0.0.0/24
Click on Create VPC button.
Select VPC-B →Actions →Edit Seetings →DNS settings
- Enable DNS hostnames
- Enable DNS resolution
Click on Save button.
Step 7— Create Private Subnet ( VPC-B)
Subnets → Create subnet
- VPC ID:
VPC-B - Subnet name:
Private_subnet_B - IPv4 subnet CIDR block:
20.0.0.0/25
Click on Create subnet button.
Step 8 — Create Route tables ( VPC-B)
Route tables → Create route table
- Name:
PrivateRT-B - VPC: Select VPC-B
- Select (VPC-B) → Subnet associations →Edit subnet associations
- Select
Private_subnet_Band Click on Save associations button.
Step 9— Create EC2 Server in VPC-B
Launch a public EC2 in VPC-B
Services →EC2 → Instances →Launch instances
- Name:
B-app - Amazon Linux 2023
- Instance type:
t2.micro
Key Pair (login):
- Select key pair → Key pair name: ec2_ssh_key
Network settings → Edit:
- VPC: VPC-B
- Subnet: Select Private_subnet_B
- Auto-assign public IP: Disable
- Firewall (SG): Create a new security group
- Security group name: Private_EC2_SG
- Description: Security group for private EC2
Rules:
- SSH → Source: Anywhere (0.0.0.0/0)
Now Click on launch instance button to create an ec2 instance
Step 10— Create VPC-C (Private/DB)
VPC → Your VPCs → Create VPC
- VPC only
- Name:
VPC-C - IPv4 CIDR:
30.0.0.0/24
Click on Create VPC button.
Select VPC-C →Actions →Edit Seetings →DNS settings
- Enable DNS hostnames
- Enable DNS resolution
Click on Save button.
Step 11— Create Private Subnet ( VPC-C)
Subnets → Create subnet
- VPC ID:
VPC-C - Subnet name:
Private_subnet_C - IPv4 subnet CIDR block:
30.0.0.0/25
Click on Create subnet button.
Step 12 — Create Route tables ( VPC-C)
Route tables → Create route table
- Name:
PrivateRT-C - VPC: Select VPC-C
- Select (VPC-C) → Subnet associations →Edit subnet associations
- Select
Private_subnet_Cand Click on Save associations button.
Step 13 — Create EC2 Server in VPC-C
Launch a private EC2 in VPC-C
Services →EC2 → Instances →Launch instances
- Name:
- Amazon Linux 2023
- Instance type:
t2.micro
Key Pair (login):
- Select key pair → Key pair name: ec2_ssh_key
Network settings → Edit:
- VPC: VPC-C
- Subnet: Select Private_subnet_C
- Auto-assign public IP: Disable
- Firewall (SG): Create a new security group
- Security group name: Private_EC2_SG_C
- Description: Security group for private EC2_C
Rules:
- SSH → Source: Anywhere (0.0.0.0/0)
Now Click on launch instance button to create an ec2 instance
Step 14 — Create the Transit Gateway
VPC → Transit gateways → Create
- Name:
DemoTG - Description:
DemoTG - Keep defaults.
Click on Create transit gateway button.
TGW is Regional. It scales and routes at Layer-3 to the next-hop attachment by destination IP.
Step 15 — Create TGW Attachments (A, B, C)
Transit gateway attachments → Create
Attachment for VPC-A:
- Name tag:
A-TGW-Attach - Transit gateway ID: DemoTG
- Attachment type: VPC
- VPC ID: VPC-A
Click on Create gateway attachment button.
If you see like this error message (Security Group referencing is not available in availability zone us-east-1e (subnet subnet-00c5b74853f332ca0)) you can disable Security Group Referencing support options under the VPC attachment section.
Attachment for VPC-B:
- Name tag:
B-TGW-Attach - Transit gateway ID: DemoTG
- Attachment type: VPC
- VPC ID: VPC-B
Click on Create gateway attachment button.
Attachment for VPC-C:
- Name tag:
C-TGW-Attach - Transit gateway ID: DemoTG
- Attachment type: VPC
- VPC ID: VPC-C
Click on Create gateway attachment button.
Step 16 — Configure the TGW Route Table
There’s a Transit Gateway Route Table resource separate from VPC route tables. Do this once to avoid “black hole” surprises:
Transit gateway route tables → use the default (or create CoreRT).
Associations: Associate A-TGW-Attach, B-TGW-Attach, C-TGW-Attach to this TGW route table.
Propagations: Enable propagation for all three attachments so their CIDR blocks appear in the TGW route table automatically.
Full-mesh vs. segmented: With a single TGW route table + all attachments associated & propagated, A, B, C can all reach each other (once VPC route tables point to TGW). For segmentation (e.g., only A can talk to B/C, but B and C can’t talk to each other), use separate TGW route tables and control which CIDRs propagate/associate where.
Step 17 — Add Routes in Each VPC Route Table
Even with TGW propagation, VPCs must know to reach other VPC CIDRs via TGW:
- PublicRT-A (VPC-A):
10.0.0.0/24 → local0.0.0.0/24 → IGW-A20.0.0.0/24 → DemoTG30.0.0.0/24 → DemoTG
Route tables →PublicRT-A →Routes →Edit routes
- PrivateRT-B (VPC-B):
20.0.0.0/24 → local10.0.0.0/24 → DemoTG30.0.0.0/24 → DemoTG
Route tables →PrivateRT-B →Routes →Edit routes
- PrivateRT-C (VPC-C):
30.0.0.0/24 → local10.0.0.0/24 → DemoTG20.0.0.0/24 → DemoTG
Route tables →PrivateRT-B →Routes →Edit routes
Step 8 — Connectivity Test
First we should copy ssh key file to A-web server (Public IP:100.26.49.56)
scp -i "ec2_ssh_key.pem" ec2_ssh_key.pem ec2-user@100.26.49.56:/home/ec2-user/
ec2_ssh_key.pemSSH into A (public IP of A-web):
ssh -i ec2_ssh_key.pem ec2-user@100.26.49.56From A, SSH to B-app server (private IP:20.0.0.94):
ssh -i ec2_ssh_key.pem ec2-user@20.0.0.94From A, SSH to C-db Server(private IP:30.0.0.120):
ssh -i ec2_ssh_key.pem ec2-user@30.0.0.120If both hops succeed, your 3-VPC fabric via TGW is working ✅
🧭 Troubleshooting Cheatsheet
- No route in a VPC route table: Add the other VPC’s CIDR → Target: TGW.
- TGW side missing: Ensure Association + Propagation for each attachment in the TGW route table. AWS Documentation
- Security Groups too strict: Allow SSH from 0.0.0.0/0 into B and C (or open ICMP to test ping).
- Overlapping CIDRs: TGW won’t route overlapping prefixes — use unique blocks.
Conclusion
By using AWS Transit Gateway, we replaced a messy set of one-to-one VPC peerings with a clean and scalable hub-and-spoke design. In this lab, three VPCs (web, app, and database) communicated privately through TGW with simple routing.
In production, you can extend this design to:
- connect dozens of VPCs,
- attach on-prem networks,
- or build secure multi-Region topologies.
