Defense in Depth
VPCs provide two distinct mechanisms for controlling traffic: Security Groups and Network Access Control Lists (Network ACLs). They operate at different layers and have different behaviors. Understanding both — and when each applies — is essential.
Security Groups: The Instance-Level Firewall
A Security Group is a stateful, virtual firewall attached to individual resources (EC2 instances, RDS databases, load balancers). "Stateful" means: if you allow outbound traffic to a destination, the reply traffic is automatically allowed back in, without needing an explicit inbound rule.
Key characteristics:
- Applied at the resource level, not the subnet level.
- Allow rules only — you cannot write an explicit deny rule. Traffic not matching any allow rule is implicitly denied.
- Stateful — return traffic is automatically permitted.
- Multiple security groups can be attached to a single resource.
Example: Allow inbound HTTPS from anywhere, and SSH only from your office IP:
Inbound Rules:
Port 443 (HTTPS) Source: 0.0.0.0/0
Port 22 (SSH) Source: 203.0.113.10/32
Outbound Rules:
All traffic Destination: 0.0.0.0/0
Network ACLs: The Subnet-Level Firewall
A Network ACL (NACL) is a stateless firewall applied at the subnet boundary. Every packet is evaluated independently — there is no connection tracking. This means you must explicitly allow both inbound AND outbound traffic for every connection, including the ephemeral (response) ports.
Key characteristics:
- Applied at the subnet level — affects all resources in the subnet.
- Supports both allow and deny rules — you can explicitly block specific IP ranges.
- Stateless — return traffic must be explicitly permitted.
- Rules are evaluated in numbered order (lowest number first); the first matching rule wins.
| Feature | Security Group | Network ACL |
|---|---|---|
| Level | Resource | Subnet |
| State | Stateful | Stateless |
| Rule types | Allow only | Allow and Deny |
| Rule evaluation | All rules evaluated | First match wins |
When to use NACLs: NACLs are most useful for broad, subnet-wide blocks — for example, blocking a known malicious IP range from ever entering a subnet, regardless of what security groups say. For fine-grained, per-resource control, security groups are the right tool.
A common interview scenario: "You've added an inbound allow rule in your Security Group for port 443, but HTTPS traffic still isn't reaching your instance. What do you check?" Walk through the layers: (1) Does the subnet's route table have a route to the Internet Gateway? (2) Does the instance have a public IP? (3) Does the Network ACL allow inbound port 443 AND outbound on ephemeral ports (1024–65535) — remember, NACLs are stateless. (4) Is the Security Group rule actually saved and attached to the correct instance?