VPC & Networking Deep Dive
Subnets, routing tables, NAT gateways, VPC endpoints, and network connectivity patterns
VPC & Networking Deep Dive
Master AWS networking architecture with free flashcards and hands-on configuration practice. This lesson covers Virtual Private Clouds (VPCs), subnets, routing, internet gateways, NAT gateways, security groups, and network ACLsβessential concepts for building secure, scalable cloud infrastructure and passing the AWS Solutions Architect certification.
Welcome to AWS Networking
π» Understanding AWS networking is fundamental to building secure and performant cloud applications. Amazon Virtual Private Cloud (VPC) gives you complete control over your virtual networking environment, including IP address ranges, subnets, route tables, and network gateways. Whether you're deploying a simple web application or a complex multi-tier architecture, VPC networking forms the foundation of your AWS infrastructure.
Think of a VPC as your own isolated data center in the cloudβbut with the flexibility, scalability, and managed services that AWS provides. Unlike traditional networking, where physical constraints limit your options, AWS VPC lets you define network topologies programmatically and modify them on demand.
π Security is built into every layer of AWS networking, from subnet isolation to security groups and network ACLs. Understanding these components and how they interact is crucial for architecting solutions that meet compliance requirements while maintaining operational efficiency.
Core Concepts
π Virtual Private Cloud (VPC)
A VPC is a logically isolated section of the AWS cloud where you launch AWS resources in a virtual network that you define. Each VPC exists within a single AWS Region but can span multiple Availability Zones.
Key characteristics:
- CIDR block: You assign an IPv4 CIDR block when creating a VPC (e.g., 10.0.0.0/16)
- Regional scope: VPCs cannot span regions, but you can connect VPCs across regions using VPC peering or Transit Gateway
- Default vs Custom: Each AWS account comes with a default VPC in each region, but you should create custom VPCs for production workloads
- Tenancy: Choose between default (shared hardware) or dedicated (single-tenant hardware)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β AWS REGION (us-east-1) β β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β VPC (10.0.0.0/16) β β β β β β β β ββββββββββββββββββββ ββββββββββββββββββββ β β β β β Availability β β Availability β β β β β β Zone A β β Zone B β β β β β β β β β β β β β β π₯οΈ Subnets β β π₯οΈ Subnets β β β β β β π Security β β π Security β β β β β β π‘ Resources β β π‘ Resources β β β β β ββββββββββββββββββββ ββββββββββββββββββββ β β β β β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π‘ Best Practice: Use RFC 1918 private IP ranges for your VPCs:
- 10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
- 172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
- 192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
π’ Subnets
Subnets are subdivisions of your VPC's IP address range where you actually launch resources. Each subnet exists within a single Availability Zone and must be associated with a route table.
Types of subnets:
| Subnet Type | Route to Internet | Use Case | Example Resources |
|---|---|---|---|
| Public Subnet | β Via Internet Gateway | Internet-facing resources | Web servers, load balancers, NAT gateways |
| Private Subnet | β No direct route | Backend resources | Databases, application servers, Lambda functions |
| VPN-Only Subnet | π Via Virtual Private Gateway | Hybrid connectivity | On-premises integration resources |
CIDR block considerations:
- AWS reserves 5 IP addresses in every subnet
- First 4 IPs and last IP are reserved
- Example: In 10.0.1.0/24 (256 IPs), only 251 are usable
Reserved IPs in 10.0.1.0/24:
- 10.0.1.0 β Network address
- 10.0.1.1 β VPC router
- 10.0.1.2 β DNS server
- 10.0.1.3 β Reserved for future use
- 10.0.1.255 β Network broadcast
π§ Memory Device - Public vs Private: "Public subnets are like a shop with street-facing windows (IGW)βanyone can see in. Private subnets are like the back roomβno windows, just a delivery door (NAT) if you need to send things out."
πͺ Internet Gateway (IGW)
An Internet Gateway is a horizontally scaled, redundant, and highly available VPC component that allows communication between instances in your VPC and the internet.
Key properties:
- One per VPC: Each VPC can have only one IGW attached
- Highly available: AWS-managed, no single point of failure
- No bandwidth constraints: Scales automatically
- Performs NAT: Translates private IP to public IP for instances with public IPs
How it works:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INTERNET β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββ
β Internet Gatewayβ β Attached to VPC
β (IGW) β
ββββββββββ¬ββββββββββ
β
ββββββββββββββββ΄βββββββββββββββ
β Route Table β
β 0.0.0.0/0 β IGW β β Public route
ββββββββββββββββ¬βββββββββββββββ
β
βββββββββββ΄ββββββββββ
β Public Subnet β
β β
β π₯οΈ EC2 Instance β β Has public IP
β Private: 10.0.1.5β
β Public: 54.x.x.x β
βββββββββββββββββββββ
Configuration example:
## Create Internet Gateway
aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=my-igw}]'
## Attach to VPC
aws ec2 attach-internet-gateway \
--internet-gateway-id igw-1234567890abcdef0 \
--vpc-id vpc-0abcd1234efgh5678
## Add route to route table
aws ec2 create-route \
--route-table-id rtb-1234567890abcdef0 \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id igw-1234567890abcdef0
π NAT Gateway vs NAT Instance
NAT (Network Address Translation) allows instances in private subnets to initiate outbound traffic to the internet while preventing inbound connections from the internet.
| Feature | NAT Gateway | NAT Instance |
|---|---|---|
| Availability | Highly available within AZ | Single point of failure |
| Bandwidth | Up to 45 Gbps | Depends on instance type |
| Maintenance | AWS-managed | You manage |
| Cost | Per hour + data transfer | EC2 instance cost |
| Security Groups | Cannot be associated | Can use security groups |
| Port Forwarding | Not supported | Manual configuration |
| Bastion Server | Not supported | Can be used as bastion |
π‘ Best Practice: Use NAT Gateway for production workloads. NAT instances are only cost-effective for development/testing or when you need bastion host functionality.
NAT Gateway architecture:
INTERNET
β
β
ββββββββββ΄βββββββββ
β Internet Gatewayβ
ββββββββββ¬βββββββββ
β
βββββββββββββββ΄βββββββββββββββ
β Public Subnet (AZ-A) β
β β
β ββββββββββββββββββββ β
β β NAT Gateway β βββββΌβββ Elastic IP
β β (nat-gateway) β β
β ββββββββββ¬ββββββββββ β
ββββββββββββββΌβββββββββββββββββ
β
β Route: 0.0.0.0/0 β NAT
β
ββββββββββββββββββββββββββββββ
β Private Subnet (AZ-A) β
β β
β π₯οΈ EC2 (10.0.2.10) β β Can reach internet
β πΎ RDS (10.0.2.20) β (outbound only)
ββββββββββββββββββββββββββββββ
## Create NAT Gateway
aws ec2 create-nat-gateway \
--subnet-id subnet-1234567890abcdef0 \
--allocation-id eipalloc-0abcd1234efgh5678
## Update private subnet route table
aws ec2 create-route \
--route-table-id rtb-private123 \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id nat-0abcd1234efgh5678
β οΈ High Availability: Deploy one NAT Gateway per Availability Zone. If an AZ fails, resources in other AZs won't be affected.
π Route Tables
Route tables contain rules (routes) that determine where network traffic is directed. Every subnet must be associated with a route table.
Route components:
- Destination: CIDR block to match
- Target: Where to send matching traffic (IGW, NAT, VGW, local, etc.)
- Propagation: Routes can be static or dynamically propagated
Example route tables:
Public Subnet Route Table:
| Destination | Target | Purpose |
|---|---|---|
| 10.0.0.0/16 | local | VPC internal communication |
| 0.0.0.0/0 | igw-xxxxx | Internet access |
Private Subnet Route Table:
| Destination | Target | Purpose |
|---|---|---|
| 10.0.0.0/16 | local | VPC internal communication |
| 0.0.0.0/0 | nat-xxxxx | Outbound internet via NAT |
Route priority: When multiple routes match, AWS uses the most specific route (longest prefix match).
Example: Traffic to 10.0.1.50
Route table:
- 10.0.0.0/16 β local
- 10.0.1.0/24 β vgw-xxxxx
- 0.0.0.0/0 β igw-xxxxx
Result: Uses 10.0.1.0/24 route (most specific)
π‘ Exam Tip: The "local" route is automatically created and cannot be deleted. It enables communication within the VPC.
π Security Groups
Security Groups act as virtual firewalls for EC2 instances, controlling inbound and outbound traffic at the instance level. They are statefulβreturn traffic is automatically allowed.
Key characteristics:
- Stateful: If you allow inbound traffic, outbound response is automatically allowed
- Allow rules only: You cannot create deny rules (use NACLs for that)
- Default deny: All inbound traffic is denied by default
- Default allow: All outbound traffic is allowed by default
- Multiple SGs: An instance can have multiple security groups
- Changes apply immediately: No need to reboot instances
Security Group example:
{
"GroupName": "web-server-sg",
"Description": "Security group for web servers",
"InboundRules": [
{
"IpProtocol": "tcp",
"FromPort": 80,
"ToPort": 80,
"IpRanges": ["0.0.0.0/0"]
},
{
"IpProtocol": "tcp",
"FromPort": 443,
"ToPort": 443,
"IpRanges": ["0.0.0.0/0"]
},
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"IpRanges": ["203.0.113.0/24"]
}
],
"OutboundRules": [
{
"IpProtocol": "-1",
"IpRanges": ["0.0.0.0/0"]
}
]
}
Referencing other security groups:
## Allow traffic from another security group
aws ec2 authorize-security-group-ingress \
--group-id sg-database123 \
--protocol tcp \
--port 3306 \
--source-group sg-webserver456
This allows database access only from instances in the web server security groupβno hardcoded IPs needed!
π‘οΈ Network Access Control Lists (NACLs)
Network ACLs are stateless firewalls that operate at the subnet level. They provide an additional layer of security beyond security groups.
Key characteristics:
- Stateless: Return traffic must be explicitly allowed
- Allow and deny rules: You can create both allow and deny rules
- Rule evaluation: Rules are evaluated in order, starting with the lowest number
- Default NACL: Allows all inbound and outbound traffic
- Custom NACL: Denies all traffic by default until you add rules
- One per subnet: Each subnet must be associated with exactly one NACL
| Feature | Security Group | Network ACL |
|---|---|---|
| Level | Instance level | Subnet level |
| State | Stateful | Stateless |
| Rules | Allow only | Allow and deny |
| Rule processing | All rules evaluated | Rules in order until match |
| Applied to | Specific instances | All instances in subnet |
| Default | Deny all inbound | Allow all traffic |
NACL rule example:
| Rule # | Type | Protocol | Port Range | Source | Allow/Deny |
|---|---|---|---|---|---|
| 100 | HTTP | TCP | 80 | 0.0.0.0/0 | ALLOW |
| 110 | HTTPS | TCP | 443 | 0.0.0.0/0 | ALLOW |
| 120 | SSH | TCP | 22 | 203.0.113.0/24 | ALLOW |
| 130 | Ephemeral | TCP | 1024-65535 | 0.0.0.0/0 | ALLOW |
| * | All | All | All | 0.0.0.0/0 | DENY |
β οΈ Critical: Remember to allow ephemeral ports (1024-65535) for return traffic in NACLs, since they're stateless!
π§ Memory Device - SG vs NACL: "Security Groups are like a bouncer who remembers you (stateful)βonce you're in, you can leave freely. NACLs are like a border checkpoint (stateless)βyou need documents both entering AND leaving."
π VPC Peering
VPC Peering is a networking connection between two VPCs that enables routing using private IP addresses. Peered VPCs can be in different regions or AWS accounts.
Characteristics:
- Not transitive: If VPC A peers with VPC B, and VPC B peers with VPC C, VPC A cannot reach VPC C
- No overlapping CIDR: VPCs must have non-overlapping IP ranges
- Cross-region: Peering works across regions
- Cross-account: You can peer VPCs in different AWS accounts
- Cost: Data transfer charges apply
βββββββββββββββββββ βββββββββββββββββββ
β VPC A β β VPC B β
β 10.0.0.0/16 ββββββββββΊβ 10.1.0.0/16 β
β β Peering β β
β π₯οΈ App Servers β β πΎ Databases β
βββββββββββββββββββ βββββββββββββββββββ
β β
Route table Route table
10.1.0.0/16 β pcx-xxx 10.0.0.0/16 β pcx-xxx
Non-transitive example:
ββββββββ ββββββββ ββββββββ βVPC A ββββββββββΊβVPC B ββββββββββΊβVPC C β β10.0.xβ Peer β10.1.xβ Peer β10.2.xβ ββββββββ ββββββββ ββββββββ β VPC A CANNOT talk to VPC C β Must create direct peering AβC
π‘ Alternative: For complex hub-and-spoke topologies, consider AWS Transit Gateway instead of multiple peering connections.
π VPC Endpoints
VPC Endpoints enable private connections between your VPC and AWS services without requiring an Internet Gateway, NAT device, VPN, or Direct Connect.
Types:
1. Interface Endpoints (AWS PrivateLink)
- Elastic network interface with private IP
- Supports most AWS services (S3, DynamoDB, CloudWatch, etc.)
- Charges: Per hour + data processing
- Uses security groups
2. Gateway Endpoints
- Route table target
- Only supports S3 and DynamoDB
- Free (no additional charge)
- Uses VPC endpoint policies
WITHOUT VPC Endpoint
ββββββββββββββββββββββββββββββββββββ
β Private Subnet β
β β
β π₯οΈ EC2 Instance β
ββββββββββ¬ββββββββββββββββββββββββββ
β
β
NAT Gateway β IGW β Internet β S3
π° Cost + Latency
WITH VPC Endpoint
ββββββββββββββββββββββββββββββββββββ
β Private Subnet β
β β
β π₯οΈ EC2 Instance βββ π‘ VPC β
β Endpoint β
ββββββββββ¬βββββββββββββββββ¬βββββββββ
β β
ββββββββββββββββββ
Direct connection to S3
π° Free + Low Latency
## Create S3 Gateway Endpoint
aws ec2 create-vpc-endpoint \
--vpc-id vpc-12345678 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-12345678
## Create Interface Endpoint (e.g., for CloudWatch)
aws ec2 create-vpc-endpoint \
--vpc-id vpc-12345678 \
--vpc-endpoint-type Interface \
--service-name com.amazonaws.us-east-1.logs \
--subnet-ids subnet-12345678 \
--security-group-ids sg-12345678
π‘ Cost Optimization: Use Gateway Endpoints for S3 and DynamoDBβthey're free!
Real-World Examples
Example 1: Three-Tier Web Application Architecture
Let's design a production-ready VPC for a web application with web servers, application servers, and databases.
Requirements:
- High availability across 2 Availability Zones
- Public-facing web tier
- Private application and database tiers
- Secure database access
Architecture:
VPC: 10.0.0.0/16
Availability Zone A:
- Public Subnet: 10.0.1.0/24 (Web servers, NAT Gateway)
- Private Subnet: 10.0.2.0/24 (App servers)
- Private Subnet: 10.0.3.0/24 (Databases)
Availability Zone B:
- Public Subnet: 10.0.11.0/24 (Web servers, NAT Gateway)
- Private Subnet: 10.0.12.0/24 (App servers)
- Private Subnet: 10.0.13.0/24 (Databases)
Implementation:
## Create VPC
VPC_ID=$(aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--query 'Vpc.VpcId' \
--output text)
## Enable DNS hostnames
aws ec2 modify-vpc-attribute \
--vpc-id $VPC_ID \
--enable-dns-hostnames
## Create Internet Gateway
IGW_ID=$(aws ec2 create-internet-gateway \
--query 'InternetGateway.InternetGatewayId' \
--output text)
aws ec2 attach-internet-gateway \
--vpc-id $VPC_ID \
--internet-gateway-id $IGW_ID
## Create public subnet in AZ-A
PUBLIC_SUBNET_A=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a \
--query 'Subnet.SubnetId' \
--output text)
## Create private app subnet in AZ-A
PRIVATE_APP_A=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.2.0/24 \
--availability-zone us-east-1a \
--query 'Subnet.SubnetId' \
--output text)
## Create route table for public subnets
PUBLIC_RT=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--query 'RouteTable.RouteTableId' \
--output text)
## Add route to Internet Gateway
aws ec2 create-route \
--route-table-id $PUBLIC_RT \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id $IGW_ID
## Associate public subnet with route table
aws ec2 associate-route-table \
--route-table-id $PUBLIC_RT \
--subnet-id $PUBLIC_SUBNET_A
## Create NAT Gateway (requires Elastic IP)
EIP_ID=$(aws ec2 allocate-address \
--domain vpc \
--query 'AllocationId' \
--output text)
NAT_GW=$(aws ec2 create-nat-gateway \
--subnet-id $PUBLIC_SUBNET_A \
--allocation-id $EIP_ID \
--query 'NatGateway.NatGatewayId' \
--output text)
## Create route table for private subnets
PRIVATE_RT=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--query 'RouteTable.RouteTableId' \
--output text)
## Add route to NAT Gateway
aws ec2 create-route \
--route-table-id $PRIVATE_RT \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id $NAT_GW
## Associate private subnet with route table
aws ec2 associate-route-table \
--route-table-id $PRIVATE_RT \
--subnet-id $PRIVATE_APP_A
Security Group configuration:
## Web tier security group (allows HTTP/HTTPS from internet)
WEB_SG=$(aws ec2 create-security-group \
--group-name web-tier-sg \
--description "Web tier security group" \
--vpc-id $VPC_ID \
--query 'GroupId' \
--output text)
aws ec2 authorize-security-group-ingress \
--group-id $WEB_SG \
--protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \
--group-id $WEB_SG \
--protocol tcp --port 443 --cidr 0.0.0.0/0
## App tier security group (allows traffic only from web tier)
APP_SG=$(aws ec2 create-security-group \
--group-name app-tier-sg \
--description "Application tier security group" \
--vpc-id $VPC_ID \
--query 'GroupId' \
--output text)
aws ec2 authorize-security-group-ingress \
--group-id $APP_SG \
--protocol tcp --port 8080 \
--source-group $WEB_SG
## Database tier security group (allows traffic only from app tier)
DB_SG=$(aws ec2 create-security-group \
--group-name db-tier-sg \
--description "Database tier security group" \
--vpc-id $VPC_ID \
--query 'GroupId' \
--output text)
aws ec2 authorize-security-group-ingress \
--group-id $DB_SG \
--protocol tcp --port 3306 \
--source-group $APP_SG
Why this works:
- Web servers in public subnets can receive internet traffic
- NAT Gateways in each AZ provide outbound internet for private subnets
- Security groups enforce least privilege (webβappβdb)
- High availability through multi-AZ deployment
- Databases are completely isolated from direct internet access
Example 2: VPC Flow Logs for Troubleshooting
VPC Flow Logs capture information about IP traffic going to and from network interfaces in your VPC. They're invaluable for troubleshooting connectivity issues.
Enable Flow Logs:
## Create CloudWatch log group
aws logs create-log-group --log-group-name /aws/vpc/flowlogs
## Create IAM role for Flow Logs
cat > trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "vpc-flow-logs.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}
EOF
ROLE_ARN=$(aws iam create-role \
--role-name VPCFlowLogsRole \
--assume-role-policy-document file://trust-policy.json \
--query 'Role.Arn' \
--output text)
## Attach policy
aws iam attach-role-policy \
--role-name VPCFlowLogsRole \
--policy-arn arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
## Create Flow Log
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids $VPC_ID \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogs \
--deliver-logs-permission-arn $ROLE_ARN
Flow Log record format:
version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status
Example:
2 123456789012 eni-abc123de 172.31.16.5 172.31.16.21 49152 80 6 20 4000 1620000000 1620000060 ACCEPT OK
Query rejected traffic:
-- CloudWatch Insights query
fields @timestamp, srcAddr, dstAddr, dstPort, action
| filter action = "REJECT"
| stats count() by dstPort
| sort count desc
This helps identify:
- Which ports are being blocked
- Source IPs attempting connections
- Whether security groups or NACLs are blocking traffic
Example 3: Hybrid Cloud Connectivity with VPN
Connecting your on-premises data center to AWS using Site-to-Site VPN.
Architecture components:
βββββββββββββββββββββββββββββββββββββββββββ
β On-Premises Data Center β
β β
β π’ Corporate Network (192.168.0.0/16) β
β β
β Customer Gateway Device β
β (Physical/Virtual Router) β
ββββββββββββββββ¬βββββββββββββββββββββββββββ
β
β IPsec VPN Tunnel
β (Encrypted)
β
ββββββββββββββββββββββββββββββββββββββββββββ
β AWS Cloud β
β β
β ββββββββββββββββββββββββββββββββββ β
β β Virtual Private Gateway β β
β β (Attached to VPC) β β
β ββββββββββββ¬ββββββββββββββββββββββ β
β β β
β ββββββββββββ΄ββββββββββββββββββββββ β
β β VPC (10.0.0.0/16) β β
β β β β
β β π₯οΈ Private Subnets β β
β β πΎ Shared Resources β β
β ββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββ
Setup:
## Create Customer Gateway (represents your on-premises router)
CGW_ID=$(aws ec2 create-customer-gateway \
--type ipsec.1 \
--public-ip 203.0.113.12 \
--bgp-asn 65000 \
--query 'CustomerGateway.CustomerGatewayId' \
--output text)
## Create Virtual Private Gateway
VGW_ID=$(aws ec2 create-vpn-gateway \
--type ipsec.1 \
--query 'VpnGateway.VpnGatewayId' \
--output text)
## Attach VGW to VPC
aws ec2 attach-vpn-gateway \
--vpn-gateway-id $VGW_ID \
--vpc-id $VPC_ID
## Create VPN Connection
VPN_ID=$(aws ec2 create-vpn-connection \
--type ipsec.1 \
--customer-gateway-id $CGW_ID \
--vpn-gateway-id $VGW_ID \
--query 'VpnConnection.VpnConnectionId' \
--output text)
## Enable route propagation
aws ec2 enable-vgw-route-propagation \
--route-table-id $PRIVATE_RT \
--gateway-id $VGW_ID
Configuration downloaded from AWS:
VPN Tunnel #1:
- Outside IP Address: 54.123.45.67
- Inside IP Address: 169.254.44.1/30 (AWS side)
- Inside IP Address: 169.254.44.2/30 (Customer side)
- Pre-Shared Key: [generated key]
VPN Tunnel #2:
- Outside IP Address: 54.123.45.68
- Inside IP Address: 169.254.45.1/30 (AWS side)
- Inside IP Address: 169.254.45.2/30 (Customer side)
- Pre-Shared Key: [generated key]
π‘ High Availability: AWS creates two VPN tunnels per connection. Configure both on your customer gateway for redundancy.
π Security: All traffic through VPN tunnels is encrypted using IPsec. You can also use AWS Direct Connect for dedicated private connectivity.
Example 4: VPC Endpoint for S3 Cost Optimization
Reducing data transfer costs by accessing S3 through a VPC endpoint instead of the internet.
Before (using NAT Gateway):
## Instance in private subnet accessing S3
## Route: Instance β NAT Gateway β IGW β Internet β S3
## Costs incurred:
## - NAT Gateway per hour: $0.045
## - NAT Gateway data processing: $0.045/GB
## - Data transfer out to internet: $0.09/GB (first 10TB)
## For 1TB of S3 access per month:
## NAT Gateway: $0.045 Γ 730 hours = $32.85
## Data processing: $0.045 Γ 1000 GB = $45.00
## Data transfer: $0.09 Γ 1000 GB = $90.00
## TOTAL: $167.85/month
After (using VPC Endpoint):
## Create S3 Gateway Endpoint
VPCE_ID=$(aws ec2 create-vpc-endpoint \
--vpc-id $VPC_ID \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids $PRIVATE_RT \
--query 'VpcEndpoint.VpcEndpointId' \
--output text)
## Apply endpoint policy (optional, restricts access)
cat > endpoint-policy.json <<EOF
{
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-app-bucket/*"
}]
}
EOF
aws ec2 modify-vpc-endpoint \
--vpc-endpoint-id $VPCE_ID \
--policy-document file://endpoint-policy.json
## Verify route table automatically updated
aws ec2 describe-route-tables \
--route-table-ids $PRIVATE_RT
## Output includes:
## Destination: pl-12345678 (S3 prefix list)
## Target: vpce-xxxxx (VPC Endpoint)
## NEW COST for 1TB of S3 access per month:
## Gateway Endpoint: $0.00 (FREE)
## Data transfer: $0.00 (stays in AWS network)
## TOTAL: $0.00/month
## SAVINGS: $167.85/month = $2,014.20/year!
Verification test:
## From EC2 instance in private subnet
aws s3 ls s3://my-app-bucket/ --region us-east-1
## Check flow logs to verify traffic uses endpoint
aws logs filter-log-events \
--log-group-name /aws/vpc/flowlogs \
--filter-pattern "[version, account, eni, srcaddr, dstaddr=*amazonaws.com*]"
π― Best Practice: Always use Gateway Endpoints for S3 and DynamoDB in production environments. The cost savings are significant, and there's no performance penalty.
Common Mistakes
β οΈ Mistake 1: Forgetting to enable auto-assign public IP
Instances in public subnets won't be reachable from the internet without public IPs.
## WRONG: Launch instance without public IP
aws ec2 run-instances \
--subnet-id $PUBLIC_SUBNET \
--image-id ami-12345678
## Result: Instance has no public IP, unreachable from internet
## CORRECT: Enable at subnet level
aws ec2 modify-subnet-attribute \
--subnet-id $PUBLIC_SUBNET \
--map-public-ip-on-launch
## OR specify at launch time
aws ec2 run-instances \
--subnet-id $PUBLIC_SUBNET \
--image-id ami-12345678 \
--associate-public-ip-address
β οΈ Mistake 2: Not allowing ephemeral ports in NACL
Return traffic uses random high ports (1024-65535). Blocking these breaks connections.
## WRONG: Only allow specific ports
Inbound: 80, 443
Outbound: 80, 443
## Result: HTTP requests fail because responses can't return
## CORRECT: Allow ephemeral ports
Inbound: 80, 443, 1024-65535 (for return traffic)
Outbound: 80, 443, 1024-65535 (for responses)
β οΈ Mistake 3: Overlapping CIDR blocks in VPC peering
## WRONG: Both VPCs use 10.0.0.0/16
VPC-A: 10.0.0.0/16
VPC-B: 10.0.0.0/16
## Result: Cannot create peering connection (routing conflicts)
## CORRECT: Non-overlapping ranges
VPC-A: 10.0.0.0/16
VPC-B: 10.1.0.0/16
## Result: Peering works, routing is unambiguous
β οΈ Mistake 4: Placing NAT Gateway in private subnet
NAT Gateways must be in public subnets with IGW routes.
## WRONG: NAT Gateway in private subnet
aws ec2 create-nat-gateway \
--subnet-id $PRIVATE_SUBNET \
--allocation-id $EIP_ID
## Result: NAT Gateway can't reach internet
## CORRECT: NAT Gateway in public subnet
aws ec2 create-nat-gateway \
--subnet-id $PUBLIC_SUBNET \
--allocation-id $EIP_ID
β οΈ Mistake 5: Not using separate route tables for public/private subnets
## WRONG: All subnets use main route table with IGW route
## Result: "Private" subnets are actually public!
## CORRECT: Explicit route table associations
## Public subnets β Route table with IGW
## Private subnets β Route table with NAT Gateway
β οΈ Mistake 6: Hardcoding IP addresses in security groups
## WRONG: Reference by IP
Source: 10.0.2.15/32 (app server IP)
## Result: Breaks when instance is replaced
## CORRECT: Reference by security group
Source: sg-app-tier-12345
## Result: Works regardless of IP changes
β οΈ Mistake 7: Single NAT Gateway for all AZs
## WRONG: One NAT Gateway in AZ-A for all private subnets
## Result: If AZ-A fails, private subnets in other AZs lose internet
## CORRECT: One NAT Gateway per AZ
## AZ-A private subnets β NAT Gateway in AZ-A public subnet
## AZ-B private subnets β NAT Gateway in AZ-B public subnet
β οΈ Mistake 8: Not planning CIDR blocks for growth
## WRONG: /24 VPC with 251 usable IPs
VPC: 10.0.0.0/24
## Result: Run out of IPs quickly
## CORRECT: /16 VPC with 65,531 usable IPs
VPC: 10.0.0.0/16
## Allows for multiple subnets across AZs with room to grow
Key Takeaways
β VPC fundamentals:
- VPCs provide isolated network environments within AWS
- CIDR planning is criticalβuse /16 for VPCs, /24 for subnets
- AWS reserves 5 IPs in every subnet (first 4 + last 1)
- VPCs are regional, subnets are AZ-specific
β Routing and connectivity:
- Internet Gateway enables internet access for public subnets (one per VPC)
- NAT Gateway provides outbound internet for private subnets (deploy per AZ)
- Route tables determine traffic flowβuse explicit associations
- VPC endpoints eliminate internet routing for AWS services (free for S3/DynamoDB)
β Security layers:
- Security Groups: Stateful, instance-level, allow rules only
- NACLs: Stateless, subnet-level, allow and deny rules
- Default deny inbound, default allow outbound (security groups)
- Remember ephemeral ports (1024-65535) for NACLs
β High availability patterns:
- Deploy resources across multiple Availability Zones
- Use one NAT Gateway per AZ (not shared)
- Implement redundant VPN tunnels
- Consider Transit Gateway for complex topologies
β Cost optimization:
- Use Gateway Endpoints for S3 and DynamoDB (free)
- Right-size NAT Gateways or use NAT instances for dev/test
- VPC Flow Logs help identify unused resources
- Consolidate VPN connections where possible
β Troubleshooting checklist:
- Route table has correct routes?
- Security groups allow traffic?
- NACLs allow traffic (including ephemeral ports)?
- Public subnet has IGW route?
- Private subnet has NAT Gateway route?
- VPC endpoints configured correctly?
- Flow Logs show expected traffic patterns?
π Further Study
- AWS VPC Official Documentation: https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html
- AWS Well-Architected Framework - Networking: https://docs.aws.amazon.com/wellarchitected/latest/framework/networking.html
- AWS VPC Connectivity Options Whitepaper: https://docs.aws.amazon.com/whitepapers/latest/aws-vpc-connectivity-options/welcome.html
π Quick Reference Card
| Component | Purpose | Key Fact |
|---|---|---|
| VPC | Isolated virtual network | Regional, assign CIDR block |
| Subnet | IP subdivision | AZ-specific, 5 IPs reserved |
| Internet Gateway | Internet access | One per VPC, highly available |
| NAT Gateway | Outbound internet | Deploy per AZ, costs $$$ |
| Route Table | Traffic direction | Most specific route wins |
| Security Group | Instance firewall | Stateful, allow only |
| NACL | Subnet firewall | Stateless, allow/deny |
| VPC Peering | VPC-to-VPC connection | Not transitive |
| VPC Endpoint | Private AWS service access | Gateway (free) vs Interface |
| VPN Gateway | Hybrid connectivity | IPsec encrypted tunnels |
π’ Essential Port Numbers
| 22 | SSH | 80 | HTTP |
| 443 | HTTPS | 3306 | MySQL |
| 5432 | PostgreSQL | 1024-65535 | Ephemeral |
π° Cost Comparison
| Resource | Hourly Cost | Data Cost |
|---|---|---|
| NAT Gateway | $0.045 | $0.045/GB |
| VPC Endpoint (Interface) | $0.01 | $0.01/GB |
| VPC Endpoint (Gateway) | FREE | FREE |