AWS Cloud Practitioner Study Notes · Part 26
AWS Security Groups vs Network ACLs: Stateful and Stateless Firewalls
AWS Cloud Practitioner study notes comparing security groups and NACLs by scope, state, rule evaluation, allow/deny behaviour, and troubleshooting.
AWS VPC networking has two important firewall layers: security groups and Network Access Control Lists (NACLs). The exam distinction is straightforward once you compare their scope, state, rule types, and evaluation order.
This is Part 26 of the AWS Cloud Practitioner Study Notes series. Part 17 introduced security groups; this article compares them directly with NACLs and shows how both controls affect a connection.
Security groups and NACLs at a glance
| Feature | Security group | Network ACL |
|---|---|---|
| Scope | Resource or network interface | Entire subnet |
| State | Stateful | Stateless |
| Rule types | Allow only | Allow and deny |
| Inbound rules | Yes | Yes |
| Outbound rules | Yes | Yes |
| Rule evaluation | Rules are aggregated | Lowest-numbered matching rule wins |
| Typical purpose | Primary resource-level firewall | Subnet-level guardrail or explicit blocking |
A useful analogy is a gated community:
- NACL: Security at the neighbourhood entrance, affecting every house in the neighbourhood.
- Security group: The lock on an individual house, with rules specific to that house.
Traffic normally needs to pass the route, subnet controls, resource controls, and application listener before the application can process it. A correct security-group rule cannot fix a missing route, and a correct route cannot bypass a blocking NACL.
Security groups
A security group is a virtual firewall associated with a resource or its network interface. EC2 instances use security groups, and other AWS resources can also use them when they expose network interfaces.
A security-group rule can specify:
- Protocol, such as TCP, UDP, or ICMP
- Port or port range
- Source for inbound traffic
- Destination for outbound traffic
- IPv4 CIDR, IPv6 CIDR, another security group, or a prefix list
Example HTTPS rule:
| Direction | Protocol | Port | Source or destination |
|---|---|---|---|
| Inbound | TCP | 443 | 0.0.0.0/0 |
This permits HTTPS traffic from any IPv4 address if the route, public addressing, NACL, and application also allow the connection. It does not automatically allow IPv6; IPv6 needs a separate rule.
Security groups are stateful
Stateful means AWS tracks the connection. If an inbound SSH request is permitted on TCP port 22, the response traffic is automatically allowed back through the security group. You do not need to create a separate outbound rule specifically for that response, although the security group’s outbound configuration still matters for new outbound connections.
The same principle applies in the other direction: if an outbound connection is allowed, the response traffic can return as part of the tracked connection.
Security groups allow but cannot deny
Security groups support allow rules only. Anything not allowed by the combined security-group rules is denied. You cannot add an explicit “deny this IP address” rule to a security group.
If multiple security groups are associated with one resource, AWS aggregates their rules. If any associated security group allows the traffic, the security-group layer allows it.
New security groups have no inbound rules, so inbound traffic is denied until you add an allow rule. A newly created security group has a default outbound allow rule that you can remove or restrict.
Network ACLs
A Network ACL is a stateless firewall associated with a subnet. Every subnet has one associated NACL at a time. A NACL can be associated with multiple subnets, but each subnet can use only one NACL association at a time.
Because the NACL applies to the subnet, every resource in that subnet is affected by its inbound and outbound rules.
NACL rules contain:
- Rule number
- Protocol
- Port range
- Source or destination CIDR
- Allow or deny action
NACLs are stateless
A stateless control does not remember that a packet belongs to an approved connection. The inbound request and outbound response are evaluated independently.
For example, if a client connects to an EC2 web server on TCP port 443:
- The inbound NACL rules must allow TCP 443 from the client.
- The security group must allow TCP 443.
- The application processes the request.
- The outbound NACL rules must allow the response traffic, including the required ephemeral client port range.
If the outbound NACL rule is missing, the response can be blocked even though the inbound request was allowed.
NACLs support explicit deny rules
NACLs can allow or deny traffic. This makes them useful when you need a subnet-level guardrail or an explicit deny for a known malicious CIDR range.
Example:
| Rule number | Action | Protocol | Port | Source |
|---|---|---|---|---|
| 100 | Allow | TCP | 80 | 0.0.0.0/0 |
| 110 | Allow | TCP | 443 | 0.0.0.0/0 |
| 120 | Deny | All | All | 198.51.100.10/32 |
* | Deny | All | All | 0.0.0.0/0 |
The example uses 198.51.100.10/32 as a documentation address. Replace it with the real CIDR that needs to be blocked.
NACL rule evaluation order
AWS evaluates NACL rules from the lowest rule number to the highest. It stops at the first rule that matches the traffic. Later rules are not considered.
This makes rule numbering important. For example, if rule 100 allows all HTTPS traffic and rule 110 denies one malicious IP, the deny rule will never be reached for HTTPS traffic from that IP because rule 100 matches first.
To deny the specific address, put the narrower deny rule before the broader allow rule:
| Rule number | Action | Source | Port |
|---|---|---|---|
| 100 | Deny | 198.51.100.10/32 | 443 |
| 110 | Allow | 0.0.0.0/0 | 443 |
Use gaps such as 100, 200, and 300 so that new rules can be inserted later without renumbering the whole ACL.
Default and custom NACLs
A default NACL is configured to allow all inbound and outbound traffic for associated subnets, subject to its rules. A custom NACL starts by blocking traffic until you add the required inbound and outbound rules.
This difference is a common exam trap:
- New security group: No inbound rules; inbound traffic is denied until allowed.
- Default NACL: Allows all traffic by default.
- New custom NACL: Blocks traffic until rules are added.
Do not confuse a default NACL with a custom NACL. Always check the actual rules and subnet association when troubleshooting.
Security group versus NACL in a web application
Consider a VPC with a web subnet:
| Layer | Example rule | Responsibility |
|---|---|---|
| Route table | 0.0.0.0/0 → Internet Gateway | Provides a possible public path |
| NACL | Allow TCP 443; allow response ports; deny selected CIDRs | Subnet-level filtering |
| Web security group | Allow TCP 443 from intended clients | Resource-level filtering |
| Application | HTTPS listener on port 443 | Processes the request |
The NACL is shared by every resource in the subnet, while each resource can have its own security-group combination. For example, a web server can allow TCP 443, while an application server in the same subnet allows TCP 8080 and a database allows only its database port.
Practical security-group and NACL design
Use security groups as the primary resource-level control:
- Allow only the ports the application needs.
- Reference another security group for application-to-database traffic where appropriate.
- Restrict SSH and RDP to trusted administrator ranges or controlled access services.
- Avoid
0.0.0.0/0for administration ports. - Add IPv6 rules separately when the workload is dual-stack.
Use NACLs when a subnet-level policy is useful:
- Block a known malicious CIDR at the subnet boundary.
- Apply coarse-grained rules across all resources in a subnet.
- Add defence in depth for sensitive or public subnets.
- Control both inbound and outbound directions explicitly.
NACLs are not automatically better because they can deny traffic. They are stateless and can be harder to maintain, especially when return traffic and ephemeral ports are not included correctly.
Troubleshooting a blocked connection
When an EC2 instance or service cannot be reached, check the layers in order:
- Is the resource running and listening on the expected port?
- Does the subnet route table have a route to the client or destination?
- Is the Internet Gateway, NAT Gateway, VPN, Transit Gateway, or endpoint path correct?
- Does the subnet’s NACL allow the request in the correct direction?
- Does the NACL allow the response out, including ephemeral ports where required?
- Does the resource’s security group allow the protocol, port, and source?
- Is the operating-system firewall blocking the connection?
- Are DNS resolution, public/private IP addressing, and the application configuration correct?
For a stateful security group, focus on whether the initiating direction is allowed. For a stateless NACL, check both directions independently.
Cloud Practitioner exam notes
- Protects an EC2 resource: Security group
- Protects an entire subnet: Network ACL
- Stateful: Security group
- Stateless: Network ACL
- Allow rules only: Security group
- Allow and deny rules: Network ACL
- Security-group rule evaluation: All rules are aggregated
- NACL rule evaluation: Lowest number first; first match wins
- Response traffic automatically allowed: Security group
- Response traffic needs a separate rule: Network ACL
- Explicitly block a malicious CIDR: Network ACL
- Restrict one application tier from another: Security groups are usually the clearer control
Final takeaway
Security groups and NACLs are complementary VPC controls, not interchangeable firewalls. Security groups protect resources with stateful allow rules. NACLs protect subnets with stateless allow and deny rules evaluated in number order.
The exam shortcut is:
Security group = resource-level, stateful, allow-only.
NACL = subnet-level, stateless, allow-and-deny.
When diagnosing a real connection, remember that routing must first provide a path, both firewall layers must permit the traffic, and the application must be listening on the expected port.