
Build a Secure Network on AWS: Phase 1 - VPC and Security Groups Explained
In today's cloud-first world, 95% of successful cyberattacks target misconfigured cloud networks. As an AWS practitioner, understanding Virtual Private Clouds (VPCs) and Security Groups isn't just a skill—it's your first line of defense against sophi...

In today's cloud-first world, 95% of successful cyberattacks target misconfigured cloud networks. As an AWS practitioner, understanding Virtual Private Clouds (VPCs) and Security Groups isn't just a skill—it's your first line of defense against sophisticated cyber threats.
Whether you're a developer deploying your first application or a system administrator securing enterprise workloads, mastering VPC security fundamentals is essential for protecting your digital assets. This hands-on guide will teach you to build fortress-like network architectures using real-world scenarios.
What are VPCs and Security Groups, and Why Should You Care?
Amazon Virtual Private Cloud (VPC) is your private slice of the AWS cloud—imagine it as your own secure data center that you can customize completely. Unlike traditional networking where you're limited by physical infrastructure, VPCs give you software-defined networking superpowers with enterprise-grade security controls.
Security Groups act as virtual firewalls that control traffic at the instance level. Think of them as intelligent bodyguards that inspect every packet and decide whether it should be allowed or blocked based on your rules.
The Cost of Getting It Wrong
According to recent cloud security reports:
83% of organizations have experienced a cloud security incident
Average cost of a cloud breach: $4.88 million
Most common cause: Misconfigured security groups and network access controls
Understanding AWS Security Architecture:
AWS security follows a layered approach, and VPCs form the foundation:
Our Security Architecture Blueprint

This architecture ensures:
✅ Zero direct internet access to your application servers
✅ Encrypted traffic end-to-end
✅ Controlled outbound access for security updates
✅ Load balancer termination for SSL/TLS
Layer 1: Network Isolation (VPC)
Your private cloud environment
Completely isolated from other AWS accounts
Custom IP addressing (CIDR blocks)
Private communication between resources
Layer 2: Subnet Segmentation
Organize resources by function and access needs
Public Subnets: Internet-accessible resources
Web servers, load balancers
Direct route to Internet Gateway
Public IP addresses available
Private Subnets: Internal-only resources
Application servers, databases
No direct internet access
Enhanced security through isolation
Layer 3: Security Groups (Instance-level Firewalls)
Stateful firewalls that inspect traffic
Allow specific ports and protocols
Source-based access control
Automatic return traffic handling
VPC vs. Traditional Networking: Understanding the Revolution
| Feature | Traditional Network | AWS VPC |
| Setup Time | Weeks/Months | Minutes |
| Scalability | Limited by hardware | Virtually unlimited |
| Security | Physical firewalls | Software-defined security |
| Cost | High upfront investment | Pay-as-you-use |
| Flexibility | Fixed configurations | Dynamic, programmable |
| Global Reach | Expensive to expand | Available in 30+ regions |
Real-World Scenario: Securing an Application
Let's build a production-ready, secure architecture for a React application. This isn't just theory—you'll create actual AWS resources that demonstrate enterprise security best practices.
Step-by-Step Implementation: Building Your Secure VPC
Prerequisites: Setting Up Your Environment
Before we begin, ensure you have:
AWS CLI installed and configured
Basic understanding of IP addressing (CIDR notation)
A React application ready for deployment, you can get one here: Ahsan-bashir/React-Task-Manager-AWS/frontend
# Verify AWS CLI installation
aws --version
# Configure your credentials
aws configure
# Enter your Access Key ID, Secret Access Key, Region (us-east-1), Output format (json)
Pro Tip!

Step 1: Creating Your Virtual Private Cloud
# Create your private cloud space
echo "Creating secure VPC..."
VPC_RESPONSE=$(aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=ReactApp-SecureVPC}]')
# Extract and save VPC ID
VPC_ID=$(echo $VPC_RESPONSE | jq -r '.Vpc.VpcId')
echo "✅ VPC Created: $VPC_ID"
# Enable DNS hostnames (critical for load balancers)
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames
echo "✅ DNS hostnames enabled"
💡 What Just Happened?
Created a private network space with 65,536 available IP addresses (10.0.0.0/16)
Enabled DNS hostnames so services can find each other by name
Tagged resources for easy management and cost tracking


Step 2: Network Segmentation with Subnets
# Create PUBLIC subnet for internet-facing resources
echo "Creating public subnet for load balancer..."
PUBLIC_SUBNET_RESPONSE=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=Public-LoadBalancer-Subnet}]')
PUBLIC_SUBNET_ID=$(echo $PUBLIC_SUBNET_RESPONSE | jq -r '.Subnet.SubnetId')
echo "✅ Public Subnet: $PUBLIC_SUBNET_ID"
# Create PRIVATE subnet for application servers
echo "Creating private subnet for application..."
PRIVATE_SUBNET_RESPONSE=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.2.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=Private-App-Subnet}]')
PRIVATE_SUBNET_ID=$(echo $PRIVATE_SUBNET_RESPONSE | jq -r '.Subnet.SubnetId')
echo "✅ Private Subnet: $PRIVATE_SUBNET_ID"
Security Benefit:
Public subnet: Only load balancer exposed to internet
Private subnet: Application servers completely isolated
Network segmentation: Limits blast radius of potential attacks

Step 3: Internet Connectivity and Routing
# Create Internet Gateway for public access
echo "Setting up internet connectivity..."
IGW_RESPONSE=$(aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=SecureApp-IGW}]')
IGW_ID=$(echo $IGW_RESPONSE | jq -r '.InternetGateway.InternetGatewayId')
echo "✅ Internet Gateway: $IGW_ID"
# Attach gateway to VPC
aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
echo "✅ Internet Gateway attached"
# Configure routing for public subnet
PUBLIC_RT_RESPONSE=$(aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=Public-RouteTable}]')
PUBLIC_RT_ID=$(echo $PUBLIC_RT_RESPONSE | jq -r '.RouteTable.RouteTableId')
# Add internet route
aws ec2 create-route --route-table-id $PUBLIC_RT_ID \
--destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID
# Associate public subnet
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_ID --route-table-id $PUBLIC_RT_ID
echo "✅ Public subnet can reach internet"


Step 4: The Crown Jewel - Security Groups Configuration
This is where the magic happens. Security Groups are your primary defense mechanism.
# Security Group for Load Balancer (Internet-facing)
echo "Creating load balancer security group..."
ALB_SG_RESPONSE=$(aws ec2 create-security-group \
--group-name "ReactApp-LoadBalancer-SG" \
--description "Allows HTTPS traffic from internet to load balancer" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=LoadBalancer-SecurityGroup}]')
ALB_SG_ID=$(echo $ALB_SG_RESPONSE | jq -r '.GroupId')
echo "✅ Load Balancer SG: $ALB_SG_ID"
# Allow HTTPS (443) from anywhere - secure encrypted traffic only
aws ec2 authorize-security-group-ingress \
--group-id $ALB_SG_ID \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0 \
--tag-specifications 'ResourceType=security-group-rule,Tags=[{Key=Name,Value=HTTPS-Allow-All}]'
# Allow HTTP (80) for redirect to HTTPS
aws ec2 authorize-security-group-ingress \
--group-id $ALB_SG_ID \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0 \
--tag-specifications 'ResourceType=security-group-rule,Tags=[{Key=Name,Value=HTTP-Redirect-Only}]'
echo "✅ Load balancer accepts HTTPS traffic from internet"

# Security Group for Application Servers (Fortress Mode)
echo "Creating application server security group..."
APP_SG_RESPONSE=$(aws ec2 create-security-group \
--group-name "ReactApp-AppServer-SG" \
--description "Allows traffic ONLY from load balancer - zero direct internet access" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=AppServer-SecurityGroup}]')
APP_SG_ID=$(echo $APP_SG_RESPONSE | jq -r '.GroupId')
echo "✅ App Server SG: $APP_SG_ID"
# CRITICAL: Only allow traffic from load balancer security group
aws ec2 authorize-security-group-ingress \
--group-id $APP_SG_ID \
--protocol tcp \
--port 3000 \
--source-group $ALB_SG_ID \
--tag-specifications 'ResourceType=security-group-rule,Tags=[{Key=Name,Value=LoadBalancer-Only-Access}]'
echo "✅ App servers only accept traffic from load balancer"

🔒 Security Spotlight: This configuration means:
❌ No direct internet access to your application
✅ Only load balancer can communicate with app servers
✅ Encrypted communication enforced
✅ Zero attack surface from internet
Step 5: Secure Remote Access Configuration
# Security Group for Administrative Access
echo "Creating secure SSH access..."
SSH_SG_RESPONSE=$(aws ec2 create-security-group \
--group-name "ReactApp-SSH-SG" \
--description "SSH access restricted to administrator IP only" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=SSH-Admin-Only}]')
SSH_SG_ID=$(echo $SSH_SG_RESPONSE | jq -r '.GroupId')
# Get your current IP address
YOUR_IP=$(curl -s ipinfo.io/ip)
echo "Your IP: $YOUR_IP"
# Allow SSH ONLY from your IP
aws ec2 authorize-security-group-ingress \
--group-id $SSH_SG_ID \
--protocol tcp \
--port 22 \
--cidr $YOUR_IP/32 \
--tag-specifications 'ResourceType=security-group-rule,Tags=[{Key=Name,Value=Admin-SSH-Only}]'
echo "✅ SSH access restricted to your IP address only"

Step 6: Controlled Outbound Access with NAT Gateway
# Create NAT Gateway for secure outbound access
echo "Setting up controlled outbound access..."
# Allocate Elastic IP for NAT Gateway
EIP_RESPONSE=$(aws ec2 allocate-address --domain vpc \
--tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=NAT-Gateway-EIP}]')
EIP_ALLOCATION_ID=$(echo $EIP_RESPONSE | jq -r '.AllocationId')
# Create NAT Gateway in public subnet
NAT_RESPONSE=$(aws ec2 create-nat-gateway \
--subnet-id $PUBLIC_SUBNET_ID \
--allocation-id $EIP_ALLOCATION_ID \
--tag-specifications 'ResourceType=nat-gateway,Tags=[{Key=Name,Value=SecureApp-NAT}]')
NAT_GW_ID=$(echo $NAT_RESPONSE | jq -r '.NatGateway.NatGatewayId')
echo "✅ NAT Gateway: $NAT_GW_ID"
# Wait for NAT Gateway to be available
echo "⏳ Waiting for NAT Gateway (2-3 minutes)..."
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT_GW_ID
echo "✅ NAT Gateway ready"
# Configure private subnet routing through NAT Gateway
PRIVATE_RT_RESPONSE=$(aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=Private-RouteTable}]')
PRIVATE_RT_ID=$(echo $PRIVATE_RT_RESPONSE | jq -r '.RouteTable.RouteTableId')
# Route internet traffic through NAT Gateway
aws ec2 create-route --route-table-id $PRIVATE_RT_ID \
--destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT_GW_ID
# Associate private subnet
aws ec2 associate-route-table --subnet-id $PRIVATE_SUBNET_ID --route-table-id $PRIVATE_RT_ID
echo "✅ Private subnet has controlled outbound access"

Cost Optimization: Smart Resource Management
Understanding VPC costs helps optimize your spending:
| Resource | Cost Factor | Optimization Tip |
| VPC | Free | No cost for basic VPC |
| Subnets | Free | Multiple subnets don't increase costs |
| Internet Gateway | Free | Shared across all public subnets |
| NAT Gateway | ~$32/month | Consider NAT instances for development |
| Elastic IP | Free while attached | Release unused EIPs |
Conclusion: You're Now a VPC Security Expert
You've just implemented enterprise-grade network security using AWS VPCs and Security Groups. This foundation protects your applications using the same principles that secure Fortune 500 companies and government systems.
Key achievements:
✅ Network isolation with private subnets
✅ Defense-in-depth with multiple security layers
✅ Controlled access through security groups
✅ Secure connectivity via NAT Gateway
✅ Monitoring ready architecture
Remember, security is not a destination—it's a journey. Regularly review your security groups, monitor access patterns, and stay updated with AWS security best practices.
The architecture you've built today can handle production workloads, scale to serve millions of users, and protect against sophisticated cyber threats. You're ready to tackle Phase 2 of your AWS security hardening journey!


