VPC Networking & Subnet Design — CIDR, Public/Private Subnets, NAT & VPC Peering
In this tutorial, you'll learn about VPC Networking & Subnet Design. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
VPC networking lets you create isolated virtual networks in the cloud where you control IP addressing, subnets, route tables, and connectivity to other networks and the internet.
What You'll Learn
You'll learn how to design CIDR blocks, plan public and private subnets, set up NAT gateways, establish VPC peering, and configure route tables for secure cloud networking.
Why It Matters
A poorly designed VPC leads to IP exhaustion, security holes, and costly re-architecture. Enterprise applications require predictable addressing and isolation boundaries. Durga Antivirus Pro's backend uses VPC peering to securely connect its scanning pipeline across multiple AWS accounts.
Real-World Use
An e-commerce platform uses public subnets for load balancers and private subnets for application servers and databases, with NAT gateways for outbound internet and VPC peering to connect separate production and monitoring accounts.
CIDR Blocks and IP Addressing
Classless Inter-Domain Routing (CIDR) defines the IP address range for your VPC. Choose a block that provides enough IPs for current and future workloads without overlapping with other networks.
| CIDR Block | Available IPs | Use Case |
|---|---|---|
| /16 | 65,536 | Large enterprise VPCs |
| /20 | 4,096 | Medium applications |
| /24 | 256 | Small services or environments |
| /28 | 16 | Tiny test VPCs |
# Calculate available IPs in a CIDR block
def available_ips(cidr):
prefix = int(cidr.split("/")[1])
total = 2 ** (32 - prefix)
# AWS reserves 5 IPs per subnet
usable = total - 5
return usable
for block in ["10.0.0.0/16", "10.0.1.0/24", "10.0.2.0/28"]:
print(f"{block}: {available_ips(block)} usable IPs")
Expected output:
10.0.0.0/16: 65531 usable IPs
10.0.1.0/24: 251 usable IPs
10.0.2.0/28: 11 usable IPs
Public vs Private Subnets
Public subnets have a route to an internet gateway. Private subnets do not. Resources in private subnets use NAT gateways for outbound access.
VPC: 10.0.0.0/16
├── Public Subnet A: 10.0.1.0/24 (us-east-1a)
├── Public Subnet B: 10.0.2.0/24 (us-east-1b)
├── Private Subnet A: 10.0.10.0/24 (us-east-1a)
└── Private Subnet B: 10.0.11.0/24 (us-east-1b)
# Terraform: public subnet with Internet Gateway route
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
}
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
Expected behavior: The public subnet can send and receive traffic from the internet. The private subnet has no direct internet access.
NAT Gateways and Outbound Access
Resources in private subnets need outbound internet for updates, patches, and API calls. A NAT Gateway in a public subnet provides this.
flowchart LR A[Private Subnet] -->|Outbound traffic| B[NAT Gateway] B -->|Public subnet| C[Internet Gateway] C --> D[Internet] D -->|Response| C C --> B B --> A style A fill:#f80,color:#fff style B fill:#48f,color:#fff
# NAT Gateway in a public subnet
resource "aws_nat_gateway" "main" {
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public.id
}
resource "aws_route_table" "private" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.main.id
}
}
Expected behavior: Instances in private subnets can reach the internet for updates but cannot be reached directly from the internet.
VPC Peering
VPC peering connects two VPCs using private IP addresses. Traffic stays within AWS's network and never traverses the public internet.
# Create a VPC peering connection (AWS CLI)
aws ec2 create-vpc-peering-connection \
--vpc-id vpc-0abcd1234 \
--peer-vpc-id vpc-0efgh5678 \
--peer-region us-west-2
# Accept the peering request
aws ec2 accept-vpc-peering-connection \
--vpc-peering-connection-id pcx-0a1b2c3d
# Add routes in both VPC route tables
aws ec2 create-route \
--route-table-id rtb-01234567 \
--destination-cidr-block 10.1.0.0/16 \
--vpc-peering-connection-id pcx-0a1b2c3d
Expected behavior: Instances in either VPC can communicate using private IPs as if they were on the same network.
Common Errors
- Overlapping CIDR blocks: Two peered VPCs with overlapping IP ranges cannot route traffic. Plan non-overlapping blocks from the start.
- Missing route table entries: A VPC peering connection exists but no routes point to it. Both sides must have explicit routes.
- NAT Gateway in the wrong subnet: NAT Gateway must be in a public subnet with an Internet Gateway route or it will not provide outbound access.
- Security groups blocking peering traffic: Security groups do not automatically allow traffic from peered VPCs. Add explicit inbound rules.
- Forgetting to disable DNS resolution: Disabling DNS hostnames in a VPC breaks DNS-based service discovery for peered connections.
- Single-AZ subnet design: Placing all subnets in one availability zone creates a single point of failure.
Practice Questions
- What is the minimum CIDR block size AWS recommends for a VPC? /28 provides 16 IPs, but AWS reserves 5 per subnet, leaving 11 usable.
- Why use a NAT Gateway instead of a public IP on each instance? NAT provides centralized outbound access without exposing instances directly to the internet, reducing the attack surface.
- Can two VPCs in different AWS regions be peered? Yes, inter-region VPC peering works across regions. Traffic stays on the AWS global network.
- What happens if you delete a peering connection without removing routes? Traffic is silently dropped. The routes still exist but point to a deleted connection.
- Challenge: Design a three-tier VPC with web, application, and database subnets across two AZs. Use NAT Gateways for app tier outbound access and VPC endpoints for database access to S3.
Mini Project
Design and implement a VPC for a Microservices application using Terraform:
- Create a VPC with CIDR 10.0.0.0/16
- Two public subnets for load balancers (10.0.1.0/24, 10.0.2.0/24)
- Two private subnets for application servers (10.0.10.0/24, 10.0.11.0/24)
- Two private subnets for databases (10.0.20.0/24, 10.0.21.0/24)
- Internet Gateway, NAT Gateway, and route tables
- VPC peering with a monitoring VPC
- Verify connectivity with a test instance in each subnet
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro