Key differences (at a glance)
- Security groups: stateful, operate at the instance/resource level, only support allow rules.
- NACLs: stateless, operate at the subnet level, support allow and deny rules, and evaluate rules top‑down by rule number.
For more background, see the AWS documentation: Network ACLs and Security Groups.
Step 1 — Make security groups permissive (so NACLs are what you test)
Temporarily change the security groups for your EC2 instances to be permissive (allow all inbound and outbound traffic). This ensures the security group does not block anything and the NACL becomes the effective traffic filter.
webserver-sg) and edit that group’s inbound and outbound rules to allow all traffic.
Step 2 — Confirm both instances are on the same subnet
NACLs are applied to subnets. If both instances are in the same subnet, the same NACL rules will apply to both.
Step 3 — Edit the subnet’s Network ACL rules
- Open the VPC console → Security → Network ACLs.
- Select the ACL associated with the subnet that contains your instances.
- Remember: rules are evaluated top‑down by rule number. An explicit Deny with a lower rule number will be matched before a later Allow.
22) and leave other protocols implicitly denied by the default catch‑all deny at the bottom. Because NACLs are stateless, you must also add matching outbound rules to allow return traffic (or vice versa).
Practical notes:
- If you allow inbound SSH (
22), add outbound rules that permit the ephemeral port range (typically1024–65535) so the SSH session can establish return traffic. - If you allow outbound HTTP/HTTPS, add inbound rules to permit the ephemeral return ports for responses.
Step 4 — Allow HTTP/HTTPS for your web server
Add inbound rules to permit HTTP (TCP 80) and HTTPS (TCP 443) so that web traffic reaches your instance. When adding them, give them rule numbers that place them after your SSH rule if you want SSH evaluated first.
The VPC console will display the inbound rules and the final DENY catch‑all.

Troubleshooting package downloads and ephemeral ports
If a server doesn’t yet have a web server (for example, server two), try installing NGINX. You may see downloads hang or ping fail if the NACL does not permit return traffic on ephemeral ports. Failing ping example when NACL blocks return traffic:- NACLs are stateless. If you permit outbound HTTP(S) for package downloads, the inbound responses from remote servers use ephemeral ports (client-side ports typically in the
1024–65535range). If inbound rules do not explicitly permit those ephemeral return ports, the responses will be dropped.
- Add an inbound rule that allows the ephemeral port range
1024–65535(recommended over allowing all). - As a short-term measure, you can add an inbound “allow all” rule (e.g., rule number
130) to let downloads complete, then tighten rules afterward.

NACLs are stateless: you must explicitly add matching rules for both inbound and outbound traffic (or otherwise permit return traffic). Security groups are stateful and automatically allow return traffic for permitted connections.
Example: using explicit Deny rules with NACLs
NACLs support explicit Deny rules, which security groups do not. Because rules are evaluated by ascending rule number, a Deny with a lower number will override a later Allow. Example use case:- Deny SSH from a specific CIDR block (lower rule number).
- Allow SSH from other sources (higher rule number).

Summary checklist
- Confirm security groups are permissive while testing NACLs so security groups do not interfere.
- Remember NACL evaluation order: lower rule numbers are evaluated first.
- For any allowed outbound traffic, explicitly allow inbound return traffic (ephemeral ports) as NACLs are stateless.
- Use Deny rules in NACLs when you need to explicitly block traffic at the subnet level.
- AWS: Network ACLs — https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html
- AWS: Security Groups — https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html