DEV Community

Cover image for Security Groups vs NACLs in AWS: A Beginner's Guide with Real Examples
Vishal Patil
Vishal Patil

Posted on

Security Groups vs NACLs in AWS: A Beginner's Guide with Real Examples

When you launch your first EC2 instance, you quickly meet two names that sound almost the same: Security Group and Network ACL (NACL). Both filter network traffic, both use rules, and both live inside your VPC. So why does AWS give us two of them?

They protect different layers and behave differently. Once you understand that, problems like "why can't I reach my server even though my Security Group is open?" become much easier to solve.

In this article, I'll explain both in simple terms, compare them side by side, and walk through four practical examples.

How traffic flows

Internet --> [ NACL ] --> [ Security Group ] --> EC2 instance
              (subnet)        (instance)
Enter fullscreen mode Exit fullscreen mode

Traffic from the internet meets the NACL at the subnet edge first, then the Security Group at the instance. Traffic must be allowed by both to reach your application.

What is a Security Group?

A Security Group is a virtual firewall attached to an instance (more precisely, to its network interface). It controls which traffic is allowed in and out of that resource.

  • Stateful: if inbound traffic is allowed, the reply is automatically allowed out, and vice versa. You don't write a rule for the response.
  • Allow rules only: you can say what is permitted, but you cannot write an explicit deny.
  • All rules are evaluated: if any rule matches, the traffic is allowed.
  • Defaults: a new Security Group denies all inbound traffic and allows all outbound traffic.
  • Flexible sources: a rule can point to an IP range (CIDR) or to another Security Group.
  • An instance can have multiple Security Groups, and one Security Group can be used by many instances.

What is a Network ACL (NACL)?

A NACL is a firewall at the subnet boundary. Every instance in the subnet is subject to it, whether or not anyone configured the instance itself.

  • Stateless: inbound and outbound are judged separately. If you allow a request in, you must also allow the response out.
  • Allow and Deny rules: you can explicitly block traffic, such as a single bad IP address.
  • Numbered rules: they are checked from the lowest number upward, and the first match wins. A final catch-all rule (*) denies anything unmatched.
  • Defaults: the default NACL in a VPC allows all inbound and outbound traffic. A custom NACL you create denies everything until you add rules.
  • Each subnet is associated with exactly one NACL, while one NACL can cover many subnets.

Security Group vs NACL: side-by-side

Feature Security Group Network ACL
Works at Instance / network interface level Subnet level
State Stateful (return traffic automatic) Stateless (return traffic needs its own rule)
Rule types Allow only Allow and Deny
Rule evaluation All rules evaluated together In number order, first match wins
Default (new) Inbound denied, outbound allowed Default NACL allows all; custom NACL denies all
Applies to Only resources it is attached to Every resource in the associated subnet
Best used for Day-to-day, fine-grained access control Broad subnet guardrails and blocking specific IPs

Easy way to remember: the NACL is the security guard at the building gate, checking everyone who enters or leaves and able to turn people away by name. The Security Group is the lock on your office door, deciding who can enter that specific room.

Example 1: A public web server (Security Group)

You launch an EC2 instance running a website. You want visitors on HTTP/HTTPS, but only you on SSH.

Type Protocol / Port Source Purpose
HTTP TCP 80 0.0.0.0/0 Public website traffic
HTTPS TCP 443 0.0.0.0/0 Secure website traffic
SSH TCP 22 YOUR.IP.ADDRESS/32 Admin access from your IP only

Because Security Groups are stateful, you don't need an outbound rule for the web page responses. They flow back automatically.

Example 2: App and database tiers (Security Group referencing a Security Group)

Your database should only talk to your application servers. Create two Security Groups:

  • app-sg: allows inbound 80/443 from the internet.
  • db-sg: allows inbound TCP 3306 (MySQL) with the source set to app-sg.

Now only instances carrying app-sg can reach the database, even if their IP addresses change. This is much cleaner than maintaining IP lists.

Example 3: Blocking a malicious IP (NACL)

Suppose your logs show repeated attack attempts from 203.0.113.50. A Security Group can't deny, so it can't block one address while keeping the rest of the internet open. A NACL can. Add a Deny rule with a lower number than your Allow rules so it is checked first:

Rule # Type Port Source Action
90 All traffic All 203.0.113.50/32 DENY
100 HTTP 80 0.0.0.0/0 ALLOW
110 HTTPS 443 0.0.0.0/0 ALLOW
* All traffic All 0.0.0.0/0 DENY

Traffic from 203.0.113.50 matches rule 90 and is dropped. Everyone else continues to rules 100 and 110. Rule order matters: if the deny were numbered

Top comments (0)