Network Security: Security Groups and NACLs
Two firewall layers in a VPC: stateful security groups on resources and stateless network ACLs on subnets.
What is it?
AWS gives you two built-in packet filters inside a VPC:
- Security group (SG): attached to an instance's network interface. Stateful: if you allow a request in, the reply is automatically allowed out, and vice versa. Only allow rules exist; anything not allowed is denied.
- Network ACL (NACL): attached to a subnet. Stateless: inbound and outbound are judged separately, so you must also allow return traffic (usually ephemeral ports). It supports allow and deny rules evaluated in number order.
Default behavior: a new security group denies all inbound and allows all outbound. The default NACL of a default VPC allows all traffic in and out; a NACL you create yourself starts by denying everything.
Security groups can reference other security groups as sources, which lets you say 'the app tier may talk to the database tier' without hard-coding IPs.
Explain like I'm 10
A subnet's NACL is the guard at an office building's front desk who checks every person in and every person out against a written list, and treats the two directions as separate decisions. A security group is the receptionist at each company's door who remembers 'I invited this visitor' - so when the visitor leaves, no re-check is needed.
Examples
A web tier security group
Security group: web-sg (stateful)
Direction Protocol Port Source / Destination Purpose
--------- -------- ----- ----------------------- -------------------
Inbound TCP 443 0.0.0.0/0 public HTTPS
Inbound TCP 22 203.0.113.10/32 admin SSH from office
Outbound All All 0.0.0.0/0 default egress
Security group: db-sg
Inbound TCP 5432 source = web-sg only app tier may connect
(No other inbound rules -> everything else denied)A NACL pair (stateless: both directions needed)
Rule Dir Protocol Ports Source/Dest Action
---- ------- -------- ----------- --------------- ------
100 Inbound TCP 443 0.0.0.0/0 ALLOW
110 Inbound TCP 1024-65535 0.0.0.0/0 ALLOW <- replies to our outbound calls
120 Inbound All All 198.51.100.0/24 DENY (blocked bad range; lower number wins)
100 Outbound TCP 1024-65535 0.0.0.0/0 ALLOW <- replies to clients
110 Outbound TCP 443 0.0.0.0/0 ALLOW
* Both All All 0.0.0.0/0 DENY (implicit final rule)Rule 120 would never match traffic already allowed by rule 100/110 - NACL rules are processed by number. Put specific denies at lower numbers than broad allows.
Create and open a security group
SG=$(aws ec2 create-security-group --group-name web-sg \
--description "web tier" --vpc-id vpc-0abc1234 --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" \
--protocol tcp --port 443 --cidr 0.0.0.0/0How it works
Walk a request through: a client sends HTTPS to a web server in a subnet. Traffic first meets the subnet's NACL inbound rules; if allowed, it reaches the instance's security group, which checks inbound rules. The response skips the security group's outbound evaluation (it is tracked as part of the connection), but it must pass the NACL outbound rules because NACLs do not track connections.
Because NACLs are blunt (per subnet, IP/port based), most day-to-day control uses security groups; NACLs are an extra layer, handy for blocking a specific IP range at the subnet edge.
client --> [ NACL in ] --> [ SG in ] --> instance
client <-- [ NACL out ] <-- (reply auto-allowed by SG)
^ stateless: needs its own ruleWhy does it exist?
Defense in depth: a mistake in one control should not expose everything. Instance-level and subnet-level filters give layered protection and different tools - SGs for precise allow-lists, NACLs for coarse allow/deny at the boundary.
When to use it
Use security groups on every resource, with tight sources. Use NACLs when you need explicit deny rules or a coarse subnet-level guard.
When not to use it
Do not rely on a NACL alone to protect instances, and do not open 0.0.0.0/0 on administrative ports like SSH or RDP; use Systems Manager Session Manager or a bastion with restricted sources.
Common mistakes
Forgetting ephemeral-port return rules in a NACL and wondering why connections hang.
Expecting a security group to support deny rules.
Opening port 22 or 3389 to the world.
Misordering NACL rule numbers so a broad allow shadows a specific deny.
Hard-coding IPs where a security group reference would follow the instances automatically.
Practice exercises
- Easy:
State two differences between security groups and NACLs.
- Medium:
Write SG rules for a three-tier app (ALB, app, database) where each tier only accepts traffic from the tier before it.
- Medium:
Use the CIDR calculator to find the range for a /27 and write a NACL rule that blocks it.
- Hard:
A client times out on HTTPS although the SG allows 443 and the NACL has an inbound 443 allow. Find the most likely missing rule and explain why.
Interview questions
What does stateful mean for a security group?
Return traffic for an allowed connection is automatically permitted without a separate rule.
Can a security group deny traffic explicitly?
No, it only has allow rules; unmatched traffic is denied by default. Use a NACL for explicit denies.
What are the default rules of a new security group?
All inbound denied, all outbound allowed.
Exam-style: Which acts at the subnet level and is stateless?
Network ACL.
Exam-style: Which acts at the instance level and is stateful?
Security group.