Filter concepts by levelShowing all levels.

AWS · Security Groups and Network ACLs

Security Groups and Network ACLs

Two filtering layers with opposite defaults — stateful/allow-only at the resource, stateless/ordered at the subnet

  • Security group: stateful, allow-onlyattached to the resource, return traffic automatic
  • NACL: stateless, allow or denyattached to the subnet, rule-number ordered
  • Ephemeral ports need explicit rulesonly in a NACL — security groups handle it automatically
  • No single layer aloneplacement + security group + NACL — each catches a different mistake

1.Security groups: stateful, instance-level firewalls

A security group is a stateful firewall attached to a resource (an instance, a load balancer, an RDS database) — it can only allow traffic, never explicitly deny, and once inbound traffic is allowed, the matching return traffic is automatically allowed back out.

Key features

  • Attached to the resource itself (ENI-level) — not to a subnet
  • Allow-only — there is no explicit "deny" rule in a security group
  • Stateful — allowed inbound traffic's response is automatically allowed outbound, and vice versa
  • A resource can have multiple security groups; the union of all rules applies
  • A security group can reference another security group as its source, not just an IP range
Stateful in practice

Inbound rule added

  • Allow TCP 443 from sg-alb (the load balancer's security group)
  • A request from that source on port 443 is let through

No outbound rule needed for the reply

  • The response to that same connection is automatically allowed out
  • No matching outbound rule had to be added by hand
  • Inbound rule added
    • Allow TCP 443 from sg-alb (the load balancer's security group)
    • A request from that source on port 443 is let through
  • No outbound rule needed for the reply
    • The response to that same connection is automatically allowed out
    • No matching outbound rule had to be added by hand

Command

bash
aws ec2 authorize-security-group-ingress --group-id sg-0abc123 \
  --protocol tcp --port 443 --source-group sg-0alb456

Security groups are stateful and allow-only, attached to the resource itself — return traffic for an allowed connection is automatic, and there is no explicit deny.

2.Network ACLs: stateless, subnet-level rules

A network ACL filters traffic at the subnet boundary, evaluating numbered rules in order until one matches, and — unlike a security group — it is stateless: allowing inbound traffic does not automatically allow the response back out.

Key features

  • Attached to a subnet, not an individual resource
  • Stateless — inbound and outbound rules are entirely independent
  • Rules are numbered and evaluated in order; the first match wins
  • Can explicitly ALLOW or DENY, unlike a security group
  • Every subnet is associated with a network ACL — the default one allows all traffic both ways

A network ACL rule set (evaluated in rule-number order)

A network ACL rule set (evaluated in rule-number order)
Rule #TypeProtocolPortSourceAllow/Deny
100InboundTCP4430.0.0.0/0ALLOW
200InboundTCPall203.0.113.0/24DENY
*Inboundallall0.0.0.0/0DENY (implicit last rule)
Same two rules, opposite outcome — only the numbers changed

DENY evaluated first (rule 50)

  • Rule 50: DENY 203.0.113.0/24
  • Rule 100: ALLOW 0.0.0.0/0
  • Result: that range is blocked

ALLOW evaluated first (rule 50)

  • Rule 50: ALLOW 0.0.0.0/0
  • Rule 100: DENY 203.0.113.0/24 — never reached
  • Result: everyone is allowed
  • DENY evaluated first (rule 50)
    • Rule 50: DENY 203.0.113.0/24
    • Rule 100: ALLOW 0.0.0.0/0
    • Result: that range is blocked
  • ALLOW evaluated first (rule 50)
    • Rule 50: ALLOW 0.0.0.0/0
    • Rule 100: DENY 203.0.113.0/24 — never reached
    • Result: everyone is allowed

Command

text
Rules evaluated in rule-number order → first match wins → default deny-all as the last, unremovable rule

Network ACLs are stateless, subnet-level, and rule-number-ordered — the first matching rule wins, and inbound/outbound must each be explicitly allowed, including the ephemeral-port response.

3.Choosing security groups, NACLs, or inspection

Security groups handle almost all day-to-day access control. Network ACLs add a coarser, explicit-deny subnet boundary on top when needed. Something like AWS WAF or a firewall inspects the actual content of traffic, not just its source and port.

Key features

  • Security groups: the default choice for almost every access-control need
  • Network ACLs: add when an explicit deny or a subnet-wide blanket rule is needed
  • AWS WAF / firewalls: needed when the decision depends on request content, not just IP/port
  • These layers are complementary, not alternatives — most production VPCs use more than one
  • Reach for the simplest layer that solves the problem; add more only when that layer cannot express the rule

Command

text
Most access rules       → security group
Subnet-wide explicit deny → network ACL
Content-aware filtering  → AWS WAF / inspection

Default to a security group for most rules; add a network ACL for a subnet-wide explicit deny; add WAF or inspection only when the decision depends on request content, not just source and port.

4.Designing layered network controls

A single boundary that fails open leaves nothing behind it. Combining security groups (per-resource), network ACLs (per-subnet), and correct routing (public/private placement) means one misconfiguration does not expose everything by itself.

Key features

  • A single security group with an overly broad rule can be caught by a NACL layer above it
  • A subnet placed correctly (private) limits blast radius even if a security group is misconfigured
  • No single layer should be the only thing standing between a resource and unwanted access
  • Layering costs little to design in from the start; it is expensive to retrofit after an incident
  • Defense in depth does not mean redundant identical rules — each layer should catch a different class of mistake

Command

text
Placement (private subnet) + Security group (per-resource) + NACL (per-subnet) = no single point of failure

No single layer — not subnet placement, not a security group, not a NACL — should be the only thing standing between a resource and unwanted access; each layer should catch a different class of mistake.

5.Ephemeral ports and why statefulness matters

A client's reply to a server does not come back on the port it connected to — it comes back to a random high "ephemeral" port the client chose for that connection, which is exactly the traffic a stateless NACL needs its own explicit outbound rule for.

Key features

  • A client connecting to port 443 uses a random source port, typically 1024–65535
  • The server's reply is addressed back to that specific ephemeral port
  • Security groups handle this automatically — statefulness tracks the connection
  • Network ACLs do not — the ephemeral-port range needs its own explicit outbound (or inbound, for a server's replies) rule
  • Forgetting this rule is the single most common NACL connectivity mistake
Where the ephemeral port shows up
Client
Server
  1. 1SYN from port 51422 → 443
  2. 2reply to port 51422not to port 443 on the client
  1. Client → Server: SYN from port 51422 → 443
  2. Server → Client: reply to port 51422 (not to port 443 on the client)

Command

text
Client:1024-65535 → Server:443   (request)
Server:443 → Client:1024-65535   (response, addressed to the ephemeral port)

A reply is addressed to the client's ephemeral port (1024–65535), not the service port the request arrived on — a stateless NACL needs an explicit rule for that range, which a stateful security group never does.

Remember

  • Security groups: stateful, allow-only, attached to the resource — return traffic is automatic.
  • Network ACLs: stateless, allow-or-deny, attached to the subnet — first matching rule number wins.
  • Default to a security group for most rules; add a NACL only for a subnet-wide explicit deny.
  • A NACL needs an explicit outbound rule for the ephemeral port range (1024–65535) to let replies leave.

Pro tip

  • When return traffic specifically is missing, check the NACL's ephemeral-port rule before re-checking the security group.
  • Reference a security group as a rule's source instead of a hardcoded IP range — it stays correct as instances scale.
  • A lower NACL rule number is evaluated first — an intended DENY needs a lower number than any overlapping ALLOW.

Next up

  • DNS and Network Connectivity
  • Load Balancing
  • EC2 — Compute Fundamentals

Sources

  • Security groups vs network ACLs — docs.aws.amazon.com/vpc/latest/userguide/vpc-security-group-network-acl.html
  • Network ACLs — docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html
  • Checked against official AWS documentation 2026-08-21

Spotted a mistake on this page? Tell us.