AWS Networking & Security

TL;DR

VPC isolates your network. Subnets split it into public/private zones. Security Groups are stateful firewalls per resource. NACLs are stateless firewalls per subnet. IAM Policies control API-level access. Route 53 handles DNS. CloudFront caches content at edge locations globally.

Explain Like I'm 12

Your VPC is like your house. Subnets are rooms — the living room (public, anyone can visit) and the bedroom (private, only family). Security Groups are the locks on each door — they remember who came in and let them back out. NACLs are the front gate guard who checks everyone coming AND going, with no memory. IAM decides who gets a key to the house in the first place.

VPC Architecture Overview

AWS VPC architecture showing public and private subnets, security groups, NACLs, internet gateway, NAT gateway, and route tables

VPC Deep Dive

A VPC is a logically isolated section of the AWS cloud where you launch resources. You define its IP range using CIDR notation.

CIDR Blocks & Subnets

CIDRIPs AvailableCommon Use
10.0.0.0/1665,536VPC (large)
10.0.0.0/204,096VPC (medium)
10.0.1.0/24256 (251 usable)Subnet
Info: AWS reserves 5 IPs per subnet (first 4 + last 1). A /24 subnet has 256 IPs, but only 251 are usable for your resources.

Public vs. Private Subnets

  • Public subnet — Route table has a route to an Internet Gateway (IGW). Resources can have public IPs and be reached from the internet.
  • Private subnet — No direct internet route. Resources can reach the internet outbound through a NAT Gateway (in a public subnet), but can't be reached from outside.
# Create a VPC
VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 \
  --query 'Vpc.VpcId' --output text)

# Create public subnet
PUB_SUBNET=$(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 subnet
PRIV_SUBNET=$(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 and attach Internet Gateway
IGW_ID=$(aws ec2 create-internet-gateway \
  --query 'InternetGateway.InternetGatewayId' --output text)
aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID \
  --vpc-id $VPC_ID
Tip: Always create subnets in at least 2 AZs for high availability. A common pattern is 2 public + 2 private subnets across 2 AZs.

Security Groups vs. NACLs

Both filter network traffic, but they work differently:

FeatureSecurity GroupNACL
LevelInstance/ENI levelSubnet level
StatefulnessStateful (return traffic auto-allowed)Stateless (must allow both directions)
RulesAllow rules onlyAllow AND Deny rules
EvaluationAll rules evaluated togetherRules evaluated in order (lowest number first)
DefaultDeny all inbound, allow all outboundAllow all inbound and outbound
# Create a security group for a web server
SG_ID=$(aws ec2 create-security-group \
  --group-name web-server-sg \
  --description "Allow HTTP/HTTPS from anywhere, SSH from my IP" \
  --vpc-id $VPC_ID \
  --query 'GroupId' --output text)

# Allow HTTPS from anywhere
aws ec2 authorize-security-group-ingress --group-id $SG_ID \
  --protocol tcp --port 443 --cidr 0.0.0.0/0

# Allow SSH from a specific IP only
aws ec2 authorize-security-group-ingress --group-id $SG_ID \
  --protocol tcp --port 22 --cidr 203.0.113.50/32
Warning: Never open SSH (port 22) to 0.0.0.0/0 in production. Restrict it to specific IPs or use AWS Systems Manager Session Manager for remote access without opening any ports.

IAM Policies in Depth

IAM policies are JSON documents that define permissions. They follow the principle of least privilege — grant only the access needed.

Policy Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3ReadOnly",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-data-bucket",
        "arn:aws:s3:::my-data-bucket/*"
      ],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "203.0.113.0/24"
        }
      }
    }
  ]
}
Info: AWS evaluates all applicable policies together. An explicit Deny always overrides an Allow. If there's no matching statement, the default is implicit deny.

Common IAM Patterns

PatternWhat It DoesExample
Identity-basedAttached to user/group/role"This developer can read S3"
Resource-basedAttached to a resource"This S3 bucket allows cross-account access"
Permission boundaryMax permissions limit"This role can never delete production resources"
SCP (Org-level)Guardrail for entire accounts"No account can launch in ap-east-1"

Route 53 & CloudFront

Route 53 is AWS's DNS service. CloudFront is the CDN that caches content at 400+ edge locations worldwide.

Route 53 Routing Policies

  • Simple — One record, one destination
  • Weighted — Split traffic by percentage (A/B testing, blue-green deploys)
  • Latency — Route to the Region with lowest latency for the user
  • Failover — Primary/secondary with health checks
  • Geolocation — Route based on user's country/continent
# Create a CloudFront distribution for an S3 static site
aws cloudfront create-distribution \
  --origin-domain-name my-bucket.s3.amazonaws.com \
  --default-root-object index.html
Tip: CloudFront + S3 is the cheapest way to host a static website globally. Add Route 53 for a custom domain and ACM for free SSL certificates.

Test Yourself

What's the difference between a stateful and stateless firewall? Give an AWS example of each.

A stateful firewall (Security Group) remembers connections — if you allow inbound traffic on port 443, the return traffic is automatically allowed without a separate outbound rule. A stateless firewall (NACL) treats each packet independently — you must explicitly allow both inbound port 443 AND outbound ephemeral ports (1024-65535) for the connection to work.

A web server in a public subnet needs to reach a database in a private subnet. What networking components make this work?

Both subnets are in the same VPC, so they can communicate by default via local routing. The web server's security group allows outbound to the database port (e.g., 5432). The database's security group allows inbound on port 5432 from the web server's security group ID (not a CIDR — this is more secure and dynamic).

Why does NAT Gateway need to be in a public subnet?

A NAT Gateway translates private IPs to its own public IP for outbound internet traffic. It needs to be in a public subnet (one with an Internet Gateway route) so it can reach the internet. Private subnet route tables point 0.0.0.0/0 to the NAT Gateway, which then forwards traffic through the IGW.

How does IAM policy evaluation work when multiple policies apply?

AWS evaluates all applicable policies (identity-based, resource-based, permission boundaries, SCPs). The logic: (1) Start with implicit deny. (2) Check for any explicit deny — if found, deny (this always wins). (3) Check for any Allow. (4) If no Allow found, deny (implicit). Key: explicit Deny > Allow > implicit Deny.

When would you use Route 53 latency-based routing vs. CloudFront?

Route 53 latency routing directs users to the AWS Region with the lowest network latency — useful when you have the same application deployed in multiple Regions. CloudFront caches static/dynamic content at edge locations worldwide. Use both together: CloudFront for caching static assets, Route 53 latency routing for API endpoints that need to hit the nearest Regional backend.

Interview Questions

Design a secure VPC architecture for a 3-tier web application (web, app, database).

Create a VPC with 6 subnets across 2 AZs: 2 public (web tier + ALB), 2 private (app tier), 2 private (database tier). Web tier security groups allow 80/443 from 0.0.0.0/0. App tier allows traffic only from the web tier SG. Database tier allows 5432/3306 only from the app tier SG. NAT Gateway in public subnet for outbound from private subnets. NACLs as an additional defense layer. Use VPC Flow Logs for auditing.

How would you securely allow a Lambda function in Account A to access an S3 bucket in Account B?

Two approaches: (1) Resource-based policy: Add a bucket policy on Account B's S3 bucket that allows Account A's Lambda role ARN. (2) Cross-account IAM role: Create a role in Account B that trusts Account A, with S3 permissions. Lambda assumes this role via sts:AssumeRole. Option 1 is simpler for S3; option 2 is more flexible for multiple services.

A security audit found that your EC2 instances have public IPs they don't need. How do you fix this without downtime?

Move the instances behind an Application Load Balancer in a public subnet, then move the instances to private subnets (no auto-assign public IP). Update the subnet's route table to use a NAT Gateway for outbound internet. Update security groups so instances only accept traffic from the ALB's security group. Use AWS Systems Manager Session Manager for SSH access instead of public IPs.