Security Groups vs. NACLs: The VPC Firewall Pair the SAA-C03 Tests Every Time
Security Groups and NACLs both protect your VPC, but they operate at different layers, follow different rules, and fail in completely different ways. Master the stateful vs. stateless distinction — and the ephemeral port trap — before your SAA-C03.
Here is the scenario that trips up thousands of SAA-C03 candidates every year:
A web application is running in a public subnet. Inbound port 443 is allowed by the Security Group. The application is unreachable from the internet. A solutions architect checks the Security Group and confirms it is correct. What else should they check?
If your first instinct wasn't "the subnet's Network ACL," you've found your blind spot. And if you don't know why the NACL could block traffic even when the Security Group allows it, you're going to miss a whole category of VPC questions on your exam.
Security Groups and NACLs are the two AWS-native firewall mechanisms that protect resources inside a VPC. The exam treats them as a pair — if you know one but not the other, or you conflate them, you'll second-guess yourself on every networking question. They're listed explicitly in the "close cousins" that fail the most people, and for good reason: they look deceptively similar on the surface and diverge sharply on every detail that matters.
This post goes deep on both. You'll come away with a precise mental model for stateful vs. stateless filtering, a clear sense of where each layer operates in the VPC, and the ability to navigate every variant of this question the SAA-C03 can throw at you.
Where Each Layer Lives in the VPC
Before comparing them, understand where each mechanism sits in the network path. This geography is the reason the exam can construct scenarios where one is correct and the other doesn't apply.
Network ACLs (NACLs) operate at the subnet boundary. Every subnet in your VPC has exactly one NACL associated with it. Any traffic crossing into or out of the subnet is evaluated against the NACL's rules — whether that traffic is coming from the internet, another subnet, a VPC peering connection, or a VPN gateway. The NACL doesn't know or care what's inside the subnet; it only sees the traffic at the gate.
Security Groups operate at the network interface (ENI) level. Every EC2 instance, RDS instance, Lambda function in a VPC, EFS mount target, and load balancer network interface has one or more Security Groups attached directly to it. Traffic must pass the Security Group to reach the resource — and then, on the way back out, it must pass the Security Group again.
The critical implication: traffic traveling between two resources passes through both layers. A request from the internet to an EC2 instance in a public subnet:
- Hits the NACL on the subnet (inbound check)
- Hits the EC2 instance's Security Group (inbound check)
- The instance responds; the response hits the Security Group (outbound check)
- The response hits the subnet's NACL (outbound check)
- Leaves the subnet toward the internet
Both must agree to let traffic through. A Security Group allow rule means nothing if the NACL has already dropped the packet at the subnet boundary — and that's exactly the scenario at the top of this post.
Security Groups: The Instance-Level Stateful Firewall
Security Groups are AWS's most commonly used network control mechanism. They're attached to ENIs and follow a set of rules that are worth knowing precisely.
Allow Rules Only — No Explicit Deny
Security Groups only have allow rules. There is no mechanism to explicitly deny a specific IP address or CIDR range. Traffic that matches no rule is denied implicitly. Traffic that matches any allow rule is permitted.
This is critical for the exam: if you need to block a specific IP address, a Security Group cannot do it. There is no rule type to add. This is the clean signal that directs you to NACLs for "block this malicious IP" requirements.
Default Security Group behavior:
- Inbound: Deny all (no default allow rules, except that the default Security Group in a VPC allows inbound from other resources in the same Security Group).
- Outbound: Allow all (a single outbound rule permits all traffic to 0.0.0.0/0 by default). You can remove this and restrict outbound as well.
Stateful: Return Traffic Is Automatic
This is the most important Security Group property. Security Groups are stateful, meaning they track connection state. If an inbound connection is permitted, the return traffic for that connection is automatically allowed outbound — regardless of what your outbound rules say. And vice versa: if an outbound connection is allowed, the inbound return traffic is automatically permitted.
In practical terms: you add an inbound rule allowing port 443 from 0.0.0.0/0. A user connects to your web server over HTTPS. The response traffic flows back to the user. You never need to think about what port the response uses — the Security Group's connection tracking handles it. No ephemeral port configuration required.
This makes Security Groups operationally simple and easy to reason about. The exam tests whether you understand why they're simple: because they're stateful.
Security Groups Can Reference Other Security Groups
One of Security Groups' most powerful features — and an exam favorite — is that you can specify another Security Group as the source or destination in a rule, rather than an IP address or CIDR block.
Example: your application tier's Security Group allows inbound port 3306 (MySQL) from the web tier's Security Group ID. This means only EC2 instances that are members of the web tier Security Group can reach the database — regardless of their IP addresses. As you scale the web tier and add new instances, those instances automatically inherit the right to reach the database without any Security Group rule changes.
This is the canonical way to implement layered security between tiers (web → app → database) in a VPC. The exam tests it in the form: "How can the solutions architect ensure only the application servers can connect to the database, even as the number of application servers changes?"
Multiple Security Groups Per Instance
A single EC2 instance (ENI) can have up to five Security Groups attached simultaneously by default (a soft quota that can be raised to 16). The rules from all attached Security Groups are combined: a packet is allowed if it matches an allow rule in any of the attached groups. There is no concept of a more-specific rule overriding a less-specific one — the most permissive rule wins across all groups.
Network ACLs: The Subnet-Level Stateless Firewall
NACLs are older, more powerful in some ways, and considerably more complex to operate. The complexity comes from two properties that are the exact opposite of Security Groups: stateless and ordered rules with explicit deny.
Stateless: You Must Configure Both Directions
NACLs are stateless. They have no concept of connection tracking. Every packet is evaluated independently, as if it arrived for the first time. This means:
- An inbound rule allowing port 443 does NOT automatically allow the server's response traffic to leave.
- You must add a separate outbound rule to allow the response traffic out.
- You must know what port the response will use — and this is where candidates get tripped up.
When a client browser connects to your web server on port 443, the TCP handshake assigns a random ephemeral port (also called an ephemeral or dynamic port) on the client's side for the return path. The web server's response travels back to the client's IP address on that ephemeral port. If your NACL's outbound rules don't allow traffic to that ephemeral port range, the response packets are silently dropped.
The RFC-defined ephemeral port range is 49152–65535, but operating systems differ:
- Linux kernels: 32768–60999 (configurable via
/proc/sys/net/ipv4/ip_local_port_range) - Windows: 49152–65535
- AWS recommends covering 1024–65535 in NACL rules to be safe
A complete NACL configuration for a public-facing web server typically looks like:
Inbound rules:
| Rule # | Type | Protocol | Port | Source | Action |
|---|---|---|---|---|---|
| 100 | HTTPS | TCP | 443 | 0.0.0.0/0 | ALLOW |
| 110 | HTTP | TCP | 80 | 0.0.0.0/0 | ALLOW |
| 120 | Custom TCP | TCP | 1024-65535 | 0.0.0.0/0 | ALLOW |
| * | All traffic | All | All | 0.0.0.0/0 | DENY |
Outbound rules:
| Rule # | Type | Protocol | Port | Destination | Action |
|---|---|---|---|---|---|
| 100 | HTTPS | TCP | 443 | 0.0.0.0/0 | ALLOW |
| 110 | HTTP | TCP | 80 | 0.0.0.0/0 | ALLOW |
| 120 | Custom TCP | TCP | 1024-65535 | 0.0.0.0/0 | ALLOW |
| * | All traffic | All | All | 0.0.0.0/0 | DENY |
Rule 120 inbound allows the ephemeral ports used in responses from the internet when the instance initiates an outbound connection (e.g., downloading software updates). Rule 120 outbound allows the ephemeral ports used by clients' return addresses when those clients connect to the instance.
The most common exam trap in this area: a candidate correctly adds an inbound NACL rule for port 443 and is then confused why the connection still doesn't work. The outbound ephemeral port rule is missing. Security Groups work without ephemeral port thinking; NACLs require it.
Numbered Rules Evaluated in Order: First Match Wins
Unlike Security Groups (where all rules are evaluated and the most permissive wins), NACL rules are evaluated in ascending numeric order. The first matching rule wins, and evaluation stops immediately. The final rule is always * (the catch-all DENY that cannot be deleted).
This order-dependency matters in two exam-relevant ways:
Explicit deny before an allow: You can block a specific IP with a low-numbered DENY rule, and then add a higher-numbered ALLOW rule for broader traffic. For example: Rule 50 denies 203.0.113.42/32, Rule 100 allows 0.0.0.0/0. Traffic from that malicious IP hits Rule 50 first and is dropped; everyone else flows through Rule 100.
Accidental rule ordering problems: If you put a broad ALLOW rule at Rule 100 and a specific DENY at Rule 200, the specific DENY is never reached for traffic that already matched Rule 100. The exam tests this in "why is the NACL not blocking the expected traffic?" style questions.
AWS recommends leaving gaps in rule numbering (100, 200, 300…) so you can insert rules between existing ones without renumbering.
Default NACL vs. Custom NACL: A Critical Distinction
This is a frequently missed exam detail:
Default NACL (automatically associated with new subnets): Has inbound and outbound rules that ALLOW all traffic (* allow rules). A default NACL is permissive by default — it lets everything through. In a brand-new VPC, nothing at the NACL layer blocks you, which is why the Security Group is often the effective firewall.
Custom NACL (manually created): Has only the default deny-all * rule in both directions when created — it DENY all traffic until you add explicit allow rules. A new custom NACL drops everything.
The exam exploits this in: "A solutions architect creates a new NACL and associates it with the public subnet. The application becomes unreachable. What happened?" The answer: a custom NACL starts with deny-all, so the architect needed to add explicit allow rules before associating it.
Explicit Deny: The One Thing SGs Cannot Do
NACLs support both ALLOW and DENY rules. This makes them the only mechanism in a VPC that can explicitly reject traffic from a specific IP address. This is one of the exam's cleanest test signals:
"Block traffic from a known malicious IP address" → NACL DENY rule.
Security Groups cannot do this. You cannot add a deny rule to a Security Group. If malicious traffic matches no Security Group rule, it's dropped by default — but you can't prevent it from being evaluated, and you can't explicitly communicate "this IP is blocked." For IP-level blocking, NACLs are the right tool.
The Master Comparison Table
| Dimension | Security Groups | Network ACLs |
|---|---|---|
| Layer of operation | Instance / ENI | Subnet boundary |
| State tracking | Stateful (return traffic automatic) | Stateless (must configure both directions) |
| Rule types | Allow only (no deny) | Allow and Deny |
| Rule evaluation | All rules evaluated; most permissive wins | Rules evaluated in number order; first match wins |
| Explicit deny possible? | No | Yes |
| Can block a specific IP? | No (can only fail to allow it) | Yes (DENY rule) |
| Can reference other SGs? | Yes (by SG ID) | No |
| Applied to | Individual ENIs / instances | All resources in the subnet |
| Default inbound | Deny all | Allow all (default NACL) / Deny all (custom NACL) |
| Default outbound | Allow all | Allow all (default NACL) / Deny all (custom NACL) |
| Max rules per resource | 60 inbound + 60 outbound per SG (up to 5 SGs) | 20 inbound + 20 outbound per NACL |
| Ephemeral ports needed? | No (stateful) | Yes (for return traffic) |
| Scope of effect | Per-ENI granularity | Entire subnet at once |
| Cost | Free | Free |
Three Scenario Walkthroughs
Scenario 1: The Unreachable Web Server
A company runs a web application on EC2 instances in a public subnet. The Security Group on the instances allows inbound TCP 443 from 0.0.0.0/0. The VPC has an Internet Gateway. A DevOps engineer tries to load the site and gets a timeout. The solutions architect reviews the Security Group and confirms the rule is correct. What is the most likely cause?
Correct answer: The subnet's Network ACL is blocking traffic.
How to reason through it:
- The Security Group allows port 443 inbound — that's confirmed correct. ✓
- The Internet Gateway exists — the routing path is present. ✓
- The timeout (not a connection refused) suggests the packet is being dropped silently, not rejected by an application. ✓
- Security Groups are applied at the ENI level and would show the HTTPS allow. ✓
- The NACL is at the subnet level and was not mentioned. If it's a custom NACL that was recently associated with the subnet, it starts with deny-all. Even one missing NACL rule on a stateless firewall can block traffic the Security Group is happy to allow. → NACL is the most likely culprit.
Why not the route table? A route table problem would affect all traffic, not just HTTPS specifically. The question implies HTTPS-specific behavior.
Why not the Security Group outbound rule? Security Groups are stateful — there's no need to configure outbound for return traffic on an inbound connection.
Why not the Internet Gateway? An Internet Gateway doesn't block by protocol; it provides routing. An IGW problem would affect all traffic types.
The exam exploits a specific cognitive gap: candidates check the Security Group (the most familiar control) and assume there's nothing else. The NACL is the forgotten layer.
Scenario 2: Blocking a Malicious IP Address
A company's web application is being hit by a coordinated HTTP flood from a single IP address: 198.51.100.25. The security team wants to block all traffic from this IP immediately at the network layer, without modifying application code. How should the solutions architect implement this?
Correct answer: Add an ALLOW rule for existing traffic and a DENY rule for 198.51.100.25/32 at a lower rule number in the subnet's Network ACL.
More precisely: add a DENY rule for 198.51.100.25/32, all ports, inbound, with a rule number lower than any existing broad allow rules.
How to reason through it:
- Security Groups cannot deny — they only have allow rules. Removing an allow rule doesn't block one specific IP; it blocks the entire CIDR range it was covering. There's no mechanism to add an exception. → Security Groups are eliminated.
- NACLs support explicit DENY rules — this is exactly the right tool. Add
Rule 90: DENY TCP 198.51.100.25/32 all portsbeforeRule 100: ALLOW TCP 0.0.0.0/0 port 80. Traffic from the malicious IP hits Rule 90 first, is denied, and Rule 100 never evaluates for that IP. All other traffic continues to hit Rule 100 and is allowed. - Rule ordering is critical: If you add the DENY at Rule 200 but the broad ALLOW is at Rule 100, the IP matches Rule 100 first and is allowed through. The DENY at 200 is never reached. The fix: assign the DENY a number lower than the broad ALLOW.
Alternative approaches the exam may offer: AWS WAF (correct for L7 protection but operates at the load balancer level, not the subnet NACL level), Security Group modification (cannot deny a specific IP), or route table changes (dropping route table entries would affect all traffic, not one IP).
The exam-clean answer for "block a specific IP at the network layer within a VPC" is always NACL DENY rule.
Scenario 3: Allowing Only Specific Tiers to Communicate
A three-tier web application runs in a VPC. The web tier is in a public subnet, the application tier and database tier are in private subnets. The solutions architect wants to ensure only the web tier EC2 instances can connect to the application tier on port 8080, and only the application tier can connect to the database on port 3306. No other traffic should be permitted to these tiers, even from within the VPC. How should the solutions architect implement this?
Correct answer: Use Security Group rules that reference the source Security Group by ID for each tier.
How to reason through it:
- The requirement is about which resources can connect, not which IPs or subnets. The web tier might be in a subnet with CIDR 10.0.1.0/24, but the NACL doesn't know whether traffic is from a web-tier instance vs. any other resource in that subnet. A NACL rule allowing port 8080 from 10.0.1.0/24 would allow any resource in that subnet.
- Security Groups can reference other Security Groups: App tier SG: inbound port 8080 from
sg-webtier(the web tier's SG ID). Only instances insg-webtiermatch this rule — not other instances in the same subnet, not other VPC resources, not admins. Database SG: inbound port 3306 fromsg-apptier. Precise, automatic, and scales with instance count. - NACLs are not the right tool here — they can't reference Security Groups, only IPs and CIDRs. Subnet-level filtering would need to know IP ranges, which aren't guaranteed to be exclusive to a single tier.
The key exam signal: "Only resources of type X should connect to Y, regardless of IP address" → Security Group referencing by SG ID. "Block a specific IP" or "apply a rule to all resources in a subnet" → NACL.
The Mental Model: What Question Does Each Layer Answer?
Here is the durable mental model that cuts through every variant of this question:
Security Groups answer: "Is this specific resource allowed to send/receive this traffic?"
Security Groups are resource-centric. You attach them to an ENI and they follow that resource everywhere, regardless of which subnet it's in. They answer the question "is this EC2 instance, RDS database, or Lambda function allowed to accept this connection?" Their stateful nature means you describe relationships, not individual packet rules — "the web tier talks to the app tier on port 8080" is a single inbound rule.
NACLs answer: "Is this traffic allowed to cross this subnet boundary?"
NACLs are perimeter-centric. They guard the subnet gate and apply to everything crossing it in either direction. They answer "should this traffic even be allowed into (or out of) this subnet?" Their stateless nature means they operate on individual packets — they're more like traditional firewall ACLs that evaluate each packet independently.
When you need both:
- Use NACLs as your outer perimeter: enforce broad subnet-level policies, block known-bad IPs or ranges, add a defense-in-depth layer that a misconfigured Security Group can't bypass.
- Use Security Groups as your inner perimeter: enforce precise resource-to-resource rules, reference other SGs for dynamic tier-based access, and handle return traffic automatically.
The layered model: think of NACLs as the lobby security guard who checks whether you're on the building's banned list, and Security Groups as the individual office door that checks whether you have a key. Both must say yes.
Common Exam Traps and How to Dodge Them
Trap 1: Thinking Security Groups can block a specific IP. They cannot. SGs are allow-only. "Block this IP" → NACL DENY rule. Every single time. This is a clean, reliable signal — don't second-guess it.
Trap 2: Forgetting ephemeral ports in NACL outbound rules. This is the single most common "why is my NACL not working?" scenario. You add inbound rules for your application port but forget that response traffic leaves via ephemeral ports 1024–65535 on the client's end. Add outbound ALLOW for 1024–65535 to 0.0.0.0/0 (or your specific destination CIDR). Conversely, if the EC2 instance initiates outbound connections (OS updates, API calls), you need an inbound ephemeral port rule for the return traffic too.
Trap 3: Confusing default NACL (allow-all) with custom NACL (deny-all). The default NACL is permissive. A new custom NACL is not. An exam question where "the solutions architect created a new NACL and traffic stopped working" is testing this distinction. Answer: the custom NACL blocks all traffic by default and needs explicit allow rules before it's production-safe.
Trap 4: Getting rule ordering wrong on NACLs. DENY rules must have a lower rule number than the ALLOW rules they're meant to override. NACL evaluation stops at the first match. A DENY at rule 200 with an ALLOW at rule 100 means the DENY is never reached for traffic that hits rule 100 first.
Trap 5: Thinking Security Group return traffic rules are needed. SGs are stateful. If you allow inbound port 443, you do NOT need to add an outbound rule for port 1024–65535 to allow the response. Return traffic is automatically tracked and allowed. Adding an explicit outbound allow doesn't hurt, but it's unnecessary and the exam is checking whether you know it's unnecessary.
Trap 6: Assuming NACLs replace Security Groups or vice versa. They work in layers. A question that asks "how do you ensure defense in depth?" may expect both. Traffic must pass BOTH layers; strengthening one does not compensate for a gap in the other.
Trap 7: Using subnet CIDRs when you should reference Security Groups. For tier-to-tier communication within a VPC, referencing Security Group IDs is more precise and more scalable than CIDR ranges. A CIDR covers an entire subnet; a Security Group reference covers exactly the instances you intend. If the question mentions "only the application servers" (not "only the application subnet"), the answer is Security Group referencing, not a NACL CIDR rule.
Trap 8: Forgetting that NACLs are associated per-subnet, not per-VPC. You can have different NACLs on different subnets within the same VPC. The public subnet can have a different NACL from the private subnets. The exam may present a scenario where the public subnet's NACL is relaxed but the private subnet's NACL is locked down — these are independent configurations.
Exam-Day Checklist: VPC Security Layer Questions
When a VPC networking or security question comes up:
- Does the question involve blocking a specific IP address? → NACL DENY rule only. Security Groups cannot deny.
- Is traffic mysteriously failing despite the Security Group allowing it? → Check the NACL. A custom NACL with no rules denies everything.
- Did someone create a new custom NACL and associate it with a subnet? → It denies all traffic by default until explicit allow rules are added.
- Are you configuring NACL rules manually? → Remember ephemeral ports (1024–65535) for return/response traffic in the opposite direction.
- Is the question about controlling access between application tiers? → Security Group referencing by SG ID, not NACL CIDR rules.
- Does the question ask about which layer affects ALL resources in a subnet? → NACL (not Security Group). NACLs apply to every resource crossing the subnet boundary.
- Is there a rule ordering question in a NACL? → Lower number wins; DENY must be numbered lower than the broad ALLOW it's meant to override.
- Does the question mention "stateless" or require configuring both inbound and outbound separately? → NACL (stateless). Security Groups are stateful — return traffic is automatic.
- Is the question about scaling access as more instances are added to a tier? → Security Group referencing by SG ID (automatically covers new instances with no rule changes).
- Does the question ask about a default NACL vs. a custom NACL? → Default = allows all; Custom (new) = denies all.
The Core Rule You Cannot Afford to Forget
The entire topic collapses into one clean rule you can carry into the exam room:
Security Groups are stateful and allow-only — use them for resource-to-resource access control. NACLs are stateless and support deny — use them for subnet-level perimeter control and IP blocking.
When both apply (which is always), traffic must pass both. A Security Group rule means nothing if a NACL drops the packet at the subnet gate first. A NACL allow rule means nothing if the Security Group on the target instance doesn't permit the connection.
Keep this layered picture clear, know the ephemeral port quirk cold, and this entire category of SAA-C03 question goes from "two answers look right" to "obvious" — which is exactly the outcome you want on exam day.
Drill This Under Timed Conditions
Reading the stateful vs. stateless distinction here is one thing. Applying it correctly under a two-minute timer, when an exam question is deliberately offering "add an outbound Security Group rule for ephemeral ports" as a plausible distractor, is another. That precision comes from practice.
CertCoach generates SAA-level scenario questions on VPC security, scores you by domain so you can see if Secure Architectures is your weak spot, and lets you ask follow-up questions — "wait, why couldn't I use a Security Group deny rule here?" — until the concept clicks rather than just feeling familiar.
Start free: take the 10-question diagnostic — no signup, no card — and find out where you stand on VPC security questions in under 10 minutes. When you're ready to drill, the CertCoach Pass is $29, one-time — no subscription, well under the cost of your $150 exam voucher.