DEV Community

Nicolás
Nicolás

Posted on

Security Groups vs Network ACLs: The Two Firewalls You Didn’t Know You Were Using in AWS

Firewalls are essential for deciding what traffic is allowed in or out of a network. In traditional, on-prem networks, controlling traffic is usually straighforward, not because the configuration is simple, but because the structure is (hopefully) well undestood.

You know how the network is laid out, what connects to what, and what should be talking with what. In other words, you (hopefully) know the internal details.

Security teams are used to thinking in terms of:

  • A single firewall (or a small number of them)
  • Clearly defined network edges
  • Rules applied at obvious choke points

When moving to the cloud, this mental model no longer fully applies, although the concept of firewall still exist, it appears under a different name.

Firewalls in AWS

AWS does not have a single perimeter firewall protecting your environment. Instead, traffic control is distributed across multiple layers and services. Security decisions are no longer made in just one place, but at different points within the network, sometimes at the subnet level, sometimes at the resource level.

This shift in approach is often one of the biggest challenges for people new to AWS. The tools are different, the terminology is new, and familiar concepts do not always behave the same way.

Networking basics

Before discussing how we can control traffic in AWS, it is important to understand a few core networking constructs that everything else builds upon.

VPC (Virtual Private Cloud)

A VPC is a logically isolated network within AWS. You can think of it as your own private data center network in the cloud.

Within a VPC, you define:

  • The IP address range (CIDR block)
  • Subnets
  • Routing rules
  • Network security controls

By default, resources inside a VPC cannot be accessed from the internet unless you explicitly allow it.

This gives you full control over how traffic flows into, out of, and within your environment.

Subnet

A subnet is a subdivision of a VPC’s IP address range. Each subnet exists within a single AWS Availability Zone and represents a smaller network segment.

Subnets are commonly used to separate workloads based on purpose or exposure, for example:

  • Public subnets (internet-facing resources)
  • Private subnets (internal services, databases)

Controlling network traffic

Two of the most important network security controls in AWS are Security Groups and Network ACLs. Both act like firewalls, but they operate at different layers and follow different rules.

  • Security Groups: protect individual resources (like EC2 instances)
  • Network ACLs: protect entire subnets

Let's look at the following figure to understand it better:

High-level diagram of controls applied to control traffic in AWS

Traffic flows from the internet into AWS, but before it can reach your application, it must first stop at the subnet level, where a Network ACL verifies whether the traffic is allowed. If it is, the traffic continues and stops at the doorway of your application. There, a gatekeeper performs a second verification check to ensure the traffic is allowed to reach the application.

As you can see, both controls work in combination to protect your workloads, as traffic can be dropped at either layer if the checks are unsuccessful.

Let’s examine them in more detail.

Network ACL

A Network ACL (NACL) acts like a security gate at the entrance of a building. It controls:

  • What traffic can enter a subnet
  • What traffic can leave a subnet

Diagram showing NACL

NACLs are applied at the subnet level and are free of charge. Every subnet must be associated with a NACL. If none is specified, the subnet is associated with the default NACL, which allows all inbound and outbound traffic. A subnet can only be associated with one NACL.

NACLs are composed of rules that control traffic. Each rule can either allow or deny traffic, and rules are evaluated in order based on a number you assign to each rule. Evaluation starts with the lowest number and continues until the traffic matches a rule.

A key concept of NACLs is that they are stateless, meaning inbound and outbound connections are treated separately. This means that both inbound and outbound rules must explicitly allow traffic for a connection to be successful.

You must think about both directions:

  • Inbound traffic must be explicitly allowed
  • Outbound traffic must also be explicitly allowed

Let's look at an example.

Imagine that you have a subnet where you host a public web server meant to be accessed from anywhere in the world by anyone.

You need both HTTP (unencrypted, not recommended) and HTTPS traffic to reach your application.

In this situation, your Inbound rules might look like this:

100 ALLOW HTTP (80) 0.0.0.0/0
110 ALLOW HTTPS (443) 0.0.0.0/0
DENY ALL

Because NACLs, are stateless, we need to have rules allowing the outbound connectivity:

100 ALLOW ALL 0.0.0.0/0
DENY ALL

Security Groups

A security group is associated with a resource and controls the traffic that reaches it and leaves it. In other words, it controls inbound and outbound traffic to and from the resource.

Diagram showing Security Groups

Similar to NACLs, security groups are composed of rules that control both inbound and outbound traffic. The components of these rules are:

  • the source (i.e. IP address, IP range)
  • port range (i.e. 22, 80, 25-30)
  • protocol (TCP, UDP, ICMP)

Unlike NACLs, which support both ALLOW and DENY rules, security groups only support ALLOW rules. Another difference is that you can attach multiple security groups to a single resource.

However, the most important difference between NACLs and security groups is that security groups are stateful. This means they keep track of allowed connections. If inbound traffic is allowed, the corresponding return traffic is automatically allowed.

You only need to think about the initial request.

You do not need to explicitly allow response traffic.

Continuing with the web server example, the traffic has passed the NACL and is now attempting to reach your application.

You create a security group with the following rules:

  • Allow inbound HTTP (port 80) from anywhere (0.0.0.0/0)
  • Allow inbound HTTPS (port 443) from anywhere (0.0.0.0/0)

If a user sends a request on port 80 or 443, the Security Group allows it, and the response is automatically allowed back.

You do not need to add a rule for return traffic.

This is what “stateful” means.

Comparison

NACL vs SG Comparison table

When to use them

Both Network ACLs and Security Groups act as firewalls, and are typically used together rather than as alternatives. You can think of them as different security layers protecting your resources.

Ideally, you should configure both of them appropriately to ensure that only expected traffic reaches your application.

When to Use Security Groups

Security Groups should be your primary mechanism for controlling traffic in AWS and you want:

  • Fine-grained control at the resource level (EC2, ALB, RDS, etc.)
  • Simple, intuitive rules that follow the application logic
  • Automatic handling of return traffic (stateful behavior)
  • Micro-segmentation between tiers (web, application, database)

In practice, most application level access decisions, such as which services can talk to each other, are enforced using Security Groups.

When to Use Network ACLs

Use Network ACLs when you need:

  • A broad security boundary at the subnet level
  • An additional layer of protection to block or restrict traffic
  • Explicit deny rules (which Security Groups do not support)
  • Guardrails that apply to all resources within a subnet

NACLs are often used as a secondary control to enforce high-level policies, such as blocking known malicious IP ranges or preventing unintended exposure.

Top comments (0)