← Back to Tutorials
Tutorial 08 Intermediate

VPC Security: Building Your AWS Network Fortress

Your VPC is the foundation of your entire cloud security posture. Learn how to implement defense-in-depth with Security Groups, NACLs, AWS WAF, and Shield protection.

35 min implementation
12 min read
Network Security

Why VPC Security Misconfigurations Are So Dangerous

Your AWS VPC is the foundation of your entire cloud security posture. Unlike other vulnerabilities that might affect individual resources, VPC misconfigurations expose your entire network infrastructure to attack, potentially compromising hundreds of resources simultaneously.

πŸ“£
Multi-Layer VPC Defense Architecture: Internet Gateway β†’ WAF β†’ Shield β†’ NACL β†’ Security Groups β†’ EC2 Instances. Each layer provides specific protection against different attack vectors.

The Five Most Critical VPC Attack Vectors

1

Layer 3/4 DDoS Attacks (Network/Transport Layer)

Volumetric attacks that flood your network with massive amounts of trafficβ€”UDP floods, SYN floods, and amplification attacks. These can overwhelm your VPC's network capacity and knock out entire subnets.

2

Layer 7 DDoS Attacks (Application Layer)

Sophisticated HTTP floods targeting your web applications with seemingly legitimate requests. These bypass basic network filters and can exhaust application resources while appearing normal.

3

Overly Permissive Security Groups

Security groups with 0.0.0.0/0 access on critical ports (22, 3389, 3306) expose instances to brute force attacks, data exfiltration, and lateral movement within your VPC.

4

Missing NACL Protection

Default NACLs that allow all traffic remove your subnet-level defense, enabling attackers to move freely between subnets once they breach the perimeter.

5

No Application Layer Filtering

Without WAF protection, attackers can exploit application vulnerabilities like SQL injection, XSS, and OWASP Top 10 attacks directly against your web applications.

Understanding the Defense-in-Depth Strategy

Each security layer provides specific protection capabilities:

  • AWS Shield: Absorbs volumetric L3/L4 attacks before they reach your VPC
  • AWS WAF: Blocks malicious L7 application requests and bot traffic
  • Network ACLs: Provide subnet boundaries and network segmentation
  • Security Groups: Create micro-segmentation around individual resources
1

Create Secure VPC Foundation

~8 minutes

Prerequisites

  • AWS CLI configured with appropriate permissions
  • VPC creation permissions (ec2:CreateVpc, ec2:CreateSubnet, ec2:CreateFlowLogs)
  • Understanding of CIDR block allocation

Design Principles

  • Network Segmentation: Separate public and private subnets across multiple AZs
  • Least Privilege: Default deny with explicit allow rules
  • Defense in Depth: Multiple security layers
  • Monitoring: Enable VPC Flow Logs for all traffic

1.1 Create VPC with Secure Defaults

Console: Navigate to VPC Dashboard β†’ "Create VPC" β†’ Select "VPC and more" for guided setup.

AWS CLI - Create VPC
# Create VPC via AWS CLI
aws ec2 create-vpc \
    --cidr-block 10.0.0.0/16 \
    --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=secure-vpc-production},{Key=Environment,Value=production},{Key=Security,Value=high}]'

# Get VPC ID for subsequent commands
VPC_ID=$(aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=secure-vpc-production" \
    --query 'Vpcs[0].VpcId' --output text)

# Enable DNS hostnames and resolution
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-support

echo "VPC ID: $VPC_ID"

1.2 Create Multi-AZ Subnet Architecture

Create public, private, and database subnets across multiple availability zones.

AWS CLI - Create Subnets
# Create Public Subnets (for load balancers, NAT gateways)
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-subnet-1a},{Key=Type,Value=public}]'

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.2.0/24 \
    --availability-zone us-east-1b \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-subnet-1b},{Key=Type,Value=public}]'

# Create Private Subnets (for application servers)
aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.10.0/24 \
    --availability-zone us-east-1a \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-subnet-1a},{Key=Type,Value=private}]'

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.20.0/24 \
    --availability-zone us-east-1b \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-subnet-1b},{Key=Type,Value=private}]'

# Create Database Subnets (for RDS instances)
aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.50.0/24 \
    --availability-zone us-east-1a \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=database-subnet-1a},{Key=Type,Value=database}]'

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.60.0/24 \
    --availability-zone us-east-1b \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=database-subnet-1b},{Key=Type,Value=database}]'

1.3 Enable VPC Flow Logs

VPC Flow Logs capture network traffic information for monitoring and security analysis.

AWS CLI - Enable VPC Flow Logs
# Create CloudWatch log group for VPC Flow Logs
aws logs create-log-group --log-group-name /aws/vpc/flow-logs/secure-vpc

# Create IAM role for VPC Flow Logs (if not exists)
# The role needs permissions to publish to CloudWatch Logs

# Enable VPC Flow Logs
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/flow-logs/secure-vpc \
    --deliver-logs-permission-arn arn:aws:iam::ACCOUNT-ID:role/VPCFlowLogsRole \
    --tag-specifications 'ResourceType=vpc-flow-log,Tags=[{Key=Name,Value=secure-vpc-flow-logs}]'
βœ“
Foundation Complete: You now have a well-architected VPC with proper network segmentation across multiple availability zones and comprehensive logging enabled.
2

Configure Security Groups Defense

~10 minutes

Security groups act as virtual firewalls at the instance level. We'll create purpose-built security groups following the principle of least privilege.

2.1 Create Web Tier Security Group

For load balancers and web servers that receive public traffic.

AWS CLI - Web Tier Security Group
# Create security group for web tier
WEB_SG=$(aws ec2 create-security-group \
    --group-name web-tier-sg \
    --description "Security group for web tier - load balancers and web servers" \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=web-tier-sg},{Key=Tier,Value=web}]' \
    --query 'GroupId' --output text)

# Allow HTTPS from internet (port 443)
aws ec2 authorize-security-group-ingress \
    --group-id $WEB_SG \
    --protocol tcp \
    --port 443 \
    --cidr 0.0.0.0/0

# Allow HTTP from internet (port 80) - for redirects to HTTPS
aws ec2 authorize-security-group-ingress \
    --group-id $WEB_SG \
    --protocol tcp \
    --port 80 \
    --cidr 0.0.0.0/0

echo "Web Tier Security Group: $WEB_SG"

2.2 Create Application Tier Security Group

For application servers that only receive traffic from the web tier.

AWS CLI - Application Tier Security Group
# Create security group for application tier
APP_SG=$(aws ec2 create-security-group \
    --group-name app-tier-sg \
    --description "Security group for application tier - app servers" \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=app-tier-sg},{Key=Tier,Value=application}]' \
    --query 'GroupId' --output text)

# Allow HTTP from web tier only (port 8080)
aws ec2 authorize-security-group-ingress \
    --group-id $APP_SG \
    --protocol tcp \
    --port 8080 \
    --source-group $WEB_SG

# Allow HTTPS from web tier only (port 8443)
aws ec2 authorize-security-group-ingress \
    --group-id $APP_SG \
    --protocol tcp \
    --port 8443 \
    --source-group $WEB_SG

# Create bastion security group for SSH access
BASTION_SG=$(aws ec2 create-security-group \
    --group-name bastion-sg \
    --description "Security group for bastion host" \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=bastion-sg}]' \
    --query 'GroupId' --output text)

# Allow SSH from bastion host only
aws ec2 authorize-security-group-ingress \
    --group-id $APP_SG \
    --protocol tcp \
    --port 22 \
    --source-group $BASTION_SG

echo "Application Tier Security Group: $APP_SG"

2.3 Create Database Tier Security Group

For RDS instances that only receive traffic from the application tier.

AWS CLI - Database Tier Security Group
# Create security group for database tier
DB_SG=$(aws ec2 create-security-group \
    --group-name database-tier-sg \
    --description "Security group for database tier - RDS instances" \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=database-tier-sg},{Key=Tier,Value=database}]' \
    --query 'GroupId' --output text)

# Allow MySQL/Aurora from application tier only
aws ec2 authorize-security-group-ingress \
    --group-id $DB_SG \
    --protocol tcp \
    --port 3306 \
    --source-group $APP_SG

# Allow PostgreSQL from application tier only
aws ec2 authorize-security-group-ingress \
    --group-id $DB_SG \
    --protocol tcp \
    --port 5432 \
    --source-group $APP_SG

# Allow Redis from application tier only
aws ec2 authorize-security-group-ingress \
    --group-id $DB_SG \
    --protocol tcp \
    --port 6379 \
    --source-group $APP_SG

echo "Database Tier Security Group: $DB_SG"

2.4 Configure Bastion Host Security Group

Restrict SSH access to specific admin IP ranges.

AWS CLI - Bastion Security Group
# Allow SSH from specific admin IP ranges only
# IMPORTANT: Replace with your actual office/VPN IP ranges
aws ec2 authorize-security-group-ingress \
    --group-id $BASTION_SG \
    --protocol tcp \
    --port 22 \
    --cidr 203.0.113.0/24  # Replace with your office IP range

# Allow SSH from corporate VPN range
aws ec2 authorize-security-group-ingress \
    --group-id $BASTION_SG \
    --protocol tcp \
    --port 22 \
    --cidr 198.51.100.0/24  # Replace with your VPN IP range

echo "Bastion Security Group: $BASTION_SG"
⚠️
Security Best Practice: Never use 0.0.0.0/0 for SSH (port 22), RDP (port 3389), or database ports. Always restrict access to specific IP ranges or security groups. Replace the example IP ranges above with your actual office/VPN IP addresses.
βœ“
Micro-Segmentation Complete: Your instances now have purpose-built security groups that enforce the principle of least privilege and prevent lateral movement between tiers.
3

Set Up NACL Network Barriers

~8 minutes

Network ACLs provide subnet-level stateless firewall protection. Unlike security groups, NACLs can explicitly deny traffic and provide an additional layer of defense.

3.1 Create Public Subnet NACL

Controls traffic entering and leaving public subnets.

AWS CLI - Public Subnet NACL
# Create NACL for public subnets
PUBLIC_NACL=$(aws ec2 create-network-acl \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=network-acl,Tags=[{Key=Name,Value=public-nacl},{Key=Tier,Value=public}]' \
    --query 'NetworkAcl.NetworkAclId' --output text)

# INBOUND RULES
# Allow inbound HTTPS from internet
aws ec2 create-network-acl-entry \
    --network-acl-id $PUBLIC_NACL \
    --rule-number 100 \
    --protocol tcp \
    --rule-action allow \
    --ingress \
    --port-range From=443,To=443 \
    --cidr-block 0.0.0.0/0

# Allow inbound HTTP from internet (for redirects)
aws ec2 create-network-acl-entry \
    --network-acl-id $PUBLIC_NACL \
    --rule-number 110 \
    --protocol tcp \
    --rule-action allow \
    --ingress \
    --port-range From=80,To=80 \
    --cidr-block 0.0.0.0/0

# Allow ephemeral ports for return traffic
aws ec2 create-network-acl-entry \
    --network-acl-id $PUBLIC_NACL \
    --rule-number 120 \
    --protocol tcp \
    --rule-action allow \
    --ingress \
    --port-range From=1024,To=65535 \
    --cidr-block 0.0.0.0/0

# OUTBOUND RULES
# Allow outbound HTTPS
aws ec2 create-network-acl-entry \
    --network-acl-id $PUBLIC_NACL \
    --rule-number 100 \
    --protocol tcp \
    --rule-action allow \
    --egress \
    --port-range From=443,To=443 \
    --cidr-block 0.0.0.0/0

# Allow outbound HTTP
aws ec2 create-network-acl-entry \
    --network-acl-id $PUBLIC_NACL \
    --rule-number 110 \
    --protocol tcp \
    --rule-action allow \
    --egress \
    --port-range From=80,To=80 \
    --cidr-block 0.0.0.0/0

# Allow ephemeral ports outbound
aws ec2 create-network-acl-entry \
    --network-acl-id $PUBLIC_NACL \
    --rule-number 120 \
    --protocol tcp \
    --rule-action allow \
    --egress \
    --port-range From=1024,To=65535 \
    --cidr-block 0.0.0.0/0

echo "Public NACL: $PUBLIC_NACL"

3.2 Create Database Subnet NACL

Strictly controls traffic to database subnets with explicit deny rules.

AWS CLI - Database Subnet NACL
# Create NACL for database subnets
DATABASE_NACL=$(aws ec2 create-network-acl \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=network-acl,Tags=[{Key=Name,Value=database-nacl},{Key=Tier,Value=database}]' \
    --query 'NetworkAcl.NetworkAclId' --output text)

# INBOUND RULES - Allow MySQL from private subnets only
aws ec2 create-network-acl-entry \
    --network-acl-id $DATABASE_NACL \
    --rule-number 100 \
    --protocol tcp \
    --rule-action allow \
    --ingress \
    --port-range From=3306,To=3306 \
    --cidr-block 10.0.10.0/24  # Private subnet 1a

aws ec2 create-network-acl-entry \
    --network-acl-id $DATABASE_NACL \
    --rule-number 110 \
    --protocol tcp \
    --rule-action allow \
    --ingress \
    --port-range From=3306,To=3306 \
    --cidr-block 10.0.20.0/24  # Private subnet 1b

# Allow PostgreSQL from private subnets
aws ec2 create-network-acl-entry \
    --network-acl-id $DATABASE_NACL \
    --rule-number 120 \
    --protocol tcp \
    --rule-action allow \
    --ingress \
    --port-range From=5432,To=5432 \
    --cidr-block 10.0.10.0/24

aws ec2 create-network-acl-entry \
    --network-acl-id $DATABASE_NACL \
    --rule-number 130 \
    --protocol tcp \
    --rule-action allow \
    --ingress \
    --port-range From=5432,To=5432 \
    --cidr-block 10.0.20.0/24

# OUTBOUND RULES - Allow ephemeral ports for responses
aws ec2 create-network-acl-entry \
    --network-acl-id $DATABASE_NACL \
    --rule-number 100 \
    --protocol tcp \
    --rule-action allow \
    --egress \
    --port-range From=1024,To=65535 \
    --cidr-block 10.0.0.0/16

echo "Database NACL: $DATABASE_NACL"

3.3 Associate NACLs with Subnets

Link the NACLs to their respective subnets.

AWS CLI - Associate NACLs
# Get subnet IDs
PUBLIC_SUBNET_1A=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=public-subnet-1a" \
    --query 'Subnets[0].SubnetId' --output text)

PUBLIC_SUBNET_1B=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=public-subnet-1b" \
    --query 'Subnets[0].SubnetId' --output text)

DATABASE_SUBNET_1A=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=database-subnet-1a" \
    --query 'Subnets[0].SubnetId' --output text)

DATABASE_SUBNET_1B=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=database-subnet-1b" \
    --query 'Subnets[0].SubnetId' --output text)

# Get current NACL associations to replace
# Note: Each subnet can only be associated with one NACL

# Associate public NACL with public subnets
PUBLIC_ASSOC_1A=$(aws ec2 describe-network-acls \
    --filters "Name=association.subnet-id,Values=$PUBLIC_SUBNET_1A" \
    --query 'NetworkAcls[0].Associations[?SubnetId==`'$PUBLIC_SUBNET_1A'`].NetworkAclAssociationId' --output text)

aws ec2 replace-network-acl-association \
    --association-id $PUBLIC_ASSOC_1A \
    --network-acl-id $PUBLIC_NACL

# Repeat for other subnets...
echo "NACL associations updated"
βœ“
Network Segmentation Complete: Your subnets now have subnet-level firewall protection with explicit allow rules and network segmentation between tiers.
4

Deploy AWS WAF and Shield Protection

~9 minutes

AWS WAF protects your web applications from common web exploits and Layer 7 DDoS attacks. AWS Shield provides always-on DDoS protection at the network layer.

4.1 Create WAF Web ACL with Managed Rules

Use AWS Managed Rules for comprehensive protection against common threats.

JSON - WAF Web ACL Configuration
{
    "Name": "production-web-acl",
    "Scope": "REGIONAL",
    "DefaultAction": {
        "Allow": {}
    },
    "Description": "Production Web ACL with comprehensive protection",
    "Rules": [
        {
            "Name": "AWSManagedRulesCommonRuleSet",
            "Priority": 1,
            "OverrideAction": { "None": {} },
            "Statement": {
                "ManagedRuleGroupStatement": {
                    "VendorName": "AWS",
                    "Name": "AWSManagedRulesCommonRuleSet"
                }
            },
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "CommonRuleSetMetric"
            }
        },
        {
            "Name": "AWSManagedRulesKnownBadInputsRuleSet",
            "Priority": 2,
            "OverrideAction": { "None": {} },
            "Statement": {
                "ManagedRuleGroupStatement": {
                    "VendorName": "AWS",
                    "Name": "AWSManagedRulesKnownBadInputsRuleSet"
                }
            },
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "KnownBadInputsMetric"
            }
        },
        {
            "Name": "AWSManagedRulesAmazonIpReputationList",
            "Priority": 3,
            "OverrideAction": { "None": {} },
            "Statement": {
                "ManagedRuleGroupStatement": {
                    "VendorName": "AWS",
                    "Name": "AWSManagedRulesAmazonIpReputationList"
                }
            },
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "IpReputationMetric"
            }
        },
        {
            "Name": "RateLimitRule",
            "Priority": 4,
            "Statement": {
                "RateBasedStatement": {
                    "Limit": 2000,
                    "AggregateKeyType": "IP"
                }
            },
            "Action": { "Block": {} },
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "RateLimitMetric"
            }
        }
    ],
    "VisibilityConfig": {
        "SampledRequestsEnabled": true,
        "CloudWatchMetricsEnabled": true,
        "MetricName": "ProductionWebACL"
    }
}
AWS CLI - Create Web ACL
# Save the JSON above to waf-webacl.json, then create the Web ACL
aws wafv2 create-web-acl \
    --cli-input-json file://waf-webacl.json \
    --region us-east-1

# Get Web ACL ARN for association
WEB_ACL_ARN=$(aws wafv2 list-web-acls \
    --scope REGIONAL \
    --region us-east-1 \
    --query "WebACLs[?Name=='production-web-acl'].ARN" --output text)

# Associate Web ACL with Application Load Balancer
# Replace ALB_ARN with your actual ALB ARN
aws wafv2 associate-web-acl \
    --web-acl-arn $WEB_ACL_ARN \
    --resource-arn arn:aws:elasticloadbalancing:us-east-1:ACCOUNT-ID:loadbalancer/app/production-alb/1234567890 \
    --region us-east-1

4.2 Understanding AWS Shield Protection

AWS Shield Standard (Free) is automatically enabled for all AWS customers and provides:

  • Protection against common Layer 3/4 DDoS attacks
  • Always-on detection and automatic mitigation
  • Coverage for CloudFront, Route 53, ELB, and other AWS services

AWS Shield Advanced ($3,000/month) provides enhanced protection for organizations requiring:

  • 24/7 access to AWS DDoS Response Team (DRT)
  • Advanced attack diagnostics and visibility
  • Cost protection against DDoS-related scaling charges
  • Enhanced protection for EC2, ELB, CloudFront, and Route 53
  • Access to AWS WAF at no additional cost for protected resources
πŸ’‘
Shield Advanced Consideration: For most SMBs, Shield Standard combined with properly configured WAF rules provides adequate DDoS protection. Consider Shield Advanced if you handle critical financial transactions, healthcare data, or have strict uptime SLAs.
βœ“
Application Layer Protection Active: Your web applications are now protected against Layer 7 attacks, bot traffic, and known malicious IPs with automatic rate limiting.

Validate Your Configuration

Use this checklist to verify your VPC security implementation is complete:

Security Validation Script

Run this script to programmatically verify your VPC security configuration:

Bash Script
#!/bin/bash
# VPC Security Validation Script

echo "=========================================="
echo "VPC Security Configuration Validation"
echo "=========================================="

# Check VPC Flow Logs
echo -e "\n[1] Checking VPC Flow Logs..."
FLOW_LOGS=$(aws ec2 describe-flow-logs \
    --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].FlowLogId' --output text)
if [ -n "$FLOW_LOGS" ]; then
    echo "βœ“ VPC Flow Logs enabled: $FLOW_LOGS"
else
    echo "βœ— WARNING: No active VPC Flow Logs found!"
fi

# Check for overly permissive security groups
echo -e "\n[2] Checking for overly permissive security groups..."
OPEN_SSH=$(aws ec2 describe-security-groups \
    --query 'SecurityGroups[?IpPermissions[?FromPort==`22` && IpRanges[?CidrIp==`0.0.0.0/0`]]].GroupId' --output text)
if [ -z "$OPEN_SSH" ]; then
    echo "βœ“ No security groups with SSH open to 0.0.0.0/0"
else
    echo "βœ— WARNING: Security groups with SSH open to internet: $OPEN_SSH"
fi

OPEN_RDP=$(aws ec2 describe-security-groups \
    --query 'SecurityGroups[?IpPermissions[?FromPort==`3389` && IpRanges[?CidrIp==`0.0.0.0/0`]]].GroupId' --output text)
if [ -z "$OPEN_RDP" ]; then
    echo "βœ“ No security groups with RDP open to 0.0.0.0/0"
else
    echo "βœ— WARNING: Security groups with RDP open to internet: $OPEN_RDP"
fi

# Check WAF Web ACLs
echo -e "\n[3] Checking WAF Web ACLs..."
WAF_ACLS=$(aws wafv2 list-web-acls --scope REGIONAL \
    --query 'WebACLs[*].Name' --output text 2>/dev/null)
if [ -n "$WAF_ACLS" ]; then
    echo "βœ“ WAF Web ACLs found: $WAF_ACLS"
else
    echo "! No WAF Web ACLs found in this region"
fi

# Check subnet count and distribution
echo -e "\n[4] Checking subnet architecture..."
SUBNET_COUNT=$(aws ec2 describe-subnets \
    --query 'Subnets[*].SubnetId' --output text | wc -w)
AZ_COUNT=$(aws ec2 describe-subnets \
    --query 'Subnets[*].AvailabilityZone' --output text | tr '\t' '\n' | sort -u | wc -l)
echo "βœ“ Total subnets: $SUBNET_COUNT across $AZ_COUNT availability zones"

echo -e "\n=========================================="
echo "Validation complete!"
echo "==========================================

Common Mistakes to Avoid

βœ—

Using 0.0.0.0/0 for administrative ports like SSH (22), RDP (3389), or databases. Always restrict to specific IP ranges or use bastion hosts.

βœ—

Relying solely on security groups without implementing NACLs. Defense-in-depth requires multiple layers of protection.

βœ—

Not enabling VPC Flow Logs. Without flow logs, you have no visibility into network traffic patterns or attack attempts.

βœ—

Placing databases in public subnets. Databases should always be in private subnets with no direct internet access.

βœ—

Skipping WAF for web applications. Without WAF, you're exposed to SQL injection, XSS, and other OWASP Top 10 vulnerabilities.

βœ—

Using default NACLs without customization. Default NACLs allow all trafficβ€”configure explicit rules for each subnet tier.

Stop Managing VPC Security Manually

With complex network architectures and constantly changing configurations, manual security management becomes impossible. AWSight automatically monitors your VPC security posture 24/7, detects misconfigurations before they become breaches, and provides real-time insights across your entire network infrastructure.

References