VPC Guide
VPC & Subnet Creation
# Create VPC
aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications \
'ResourceType=vpc,Tags=[{Key=Name,Value=my-vpc}]'
# Create subnets
aws ec2 create-subnet \
--vpc-id vpc-12345678 \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-1a}]'
aws ec2 create-subnet \
--vpc-id vpc-12345678 \
--cidr-block 10.0.10.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-1a}]'
# Enable auto-assign public IP for public subnet
aws ec2 modify-subnet-attribute \
--subnet-id subnet-public1a \
--map-public-ip-on-launch
Internet Gateway & Route Tables
# Create and attach Internet Gateway
aws ec2 create-internet-gateway
aws ec2 attach-internet-gateway \
--internet-gateway-id igw-12345678 \
--vpc-id vpc-12345678
# Create route table for public subnets
aws ec2 create-route-table --vpc-id vpc-12345678
aws ec2 create-route \
--route-table-id rtb-public \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id igw-12345678
# Associate public subnet with public route table
aws ec2 associate-route-table \
--route-table-id rtb-public \
--subnet-id subnet-public1a
# Private route table routes through NAT Gateway
aws ec2 create-route \
--route-table-id rtb-private \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id nat-12345678
NAT Gateway
# Allocate Elastic IP for NAT Gateway
aws ec2 allocate-address --domain vpc
# Create NAT Gateway in PUBLIC subnet
aws ec2 create-nat-gateway \
--subnet-id subnet-public1a \
--allocation-id eipalloc-12345678 \
--tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=nat-1a}]'
# Wait for NAT Gateway to become available
aws ec2 wait nat-gateway-available \
--nat-gateway-ids nat-12345678
# For cost savings: use NAT Instance (single AZ) or
# AWS managed NAT Gateway per AZ for HA
Security Groups vs NACLs
| Feature | Security Groups | Network ACLs |
|---|---|---|
| Level | Instance level | Subnet level |
| State | Stateful (return traffic auto-allowed) | Stateless (must allow both directions) |
| Rules | Allow rules only | Allow and deny rules |
| Processing | All rules evaluated | Rules evaluated in order (lowest #) |
| Default | Deny all inbound, allow all outbound | Allow all in/outbound |
| Use case | Primary defense layer | Subnet-level blocklist (IP blocking) |
VPC Peering
# Request peering connection
aws ec2 create-vpc-peering-connection \
--vpc-id vpc-111 \
--peer-vpc-id vpc-222 \
--peer-region us-west-2 # omit if same region
# Accept peering request (from peer account/region)
aws ec2 accept-vpc-peering-connection \
--vpc-peering-connection-id pcx-12345678
# Add routes in both VPCs
aws ec2 create-route \
--route-table-id rtb-vpc1 \
--destination-cidr-block 10.1.0.0/16 \
--vpc-peering-connection-id pcx-12345678
# Note: VPC peering is NOT transitive
# For hub-and-spoke topology, use AWS Transit Gateway
VPC Endpoints
# Gateway endpoint (S3, DynamoDB - free)
aws ec2 create-vpc-endpoint \
--vpc-id vpc-12345678 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-private
# Interface endpoint (most services - charged)
aws ec2 create-vpc-endpoint \
--vpc-id vpc-12345678 \
--vpc-endpoint-type Interface \
--service-name com.amazonaws.us-east-1.secretsmanager \
--subnet-ids subnet-private1a subnet-private1b \
--security-group-ids sg-endpoint
# List available services
aws ec2 describe-vpc-endpoint-services --query 'ServiceNames'