RizTech Academy logo
RizTech Academy
NetworkingLesson 3 of 530 min

Security groups and NACLs

Routing decides where traffic can go; security groups decide what traffic is actually allowed to reach each resource. They are AWS's primary firewall, you will configure them constantly, and getting them right — tight but not broken — is core to a secure network. This lesson is security groups (and their less-used cousin, network ACLs), and the patterns that keep them both secure and manageable.

Security groups: a firewall around each resource

A security group is a virtual firewall attached to a resource (an EC2 instance, an EKS node, a load balancer, a database). It has rules that say which traffic is allowed in (inbound) and out (outbound). Two defining properties:

  • Default-deny inbound. A security group blocks all inbound traffic unless a rule explicitly allows it. You open only the specific ports and sources you need — nothing is reachable by default. (Outbound is default-allow unless you restrict it.)
  • Stateful. If you allow an inbound request, the response is automatically allowed back out — you do not write a matching outbound rule for return traffic. This makes them much simpler than stateless firewalls: you think in terms of "who may connect to this", and replies just work.

A rule specifies a protocol, a port (or range), and a source — and the source is where security groups become powerful.

The key pattern: reference security groups, not IP ranges

The single most important security-group practice: let rules reference other security groups as their source, not IP ranges. Instead of "allow port 5432 from 10.0.10.0/24" (an IP range that might be too broad and changes as you resize), you write "allow port 5432 from the app security group." This means: only resources in the app security group may reach the database on 5432.

Consider a standard three-tier web app:

  • Load-balancer SG — allows inbound 443 (HTTPS) from the internet (0.0.0.0/0). This is the only thing open to the world.
  • App SG — allows inbound on the app port (say 3000) only from the load-balancer SG. So the app is reachable only through the load balancer, never directly from the internet.
  • Database SG — allows inbound 5432 only from the app SG. So the database is reachable only by the application, not by anything else — not the load balancer, not the internet, not another service.

This chain — internet → LB → app → database, each layer only reachable from the layer in front — gives you defence in depth almost for free, and it stays correct as you scale (add more app servers to the app SG and they are automatically allowed to the database; no IP ranges to update). Referencing security groups by identity rather than by address is the pattern that makes AWS networking both secure and maintainable, and it is the one thing to take from this lesson.

Least privilege for the network

Security groups are least privilege (the IAM lesson) applied to the network, and the same discipline applies:

  • Open only the specific ports you need, from the specific sources that need them. Never "allow all traffic from anywhere" (0.0.0.0/0 on all ports) — that is the network equivalent of AdministratorAccess and a serious exposure.
  • Never open SSH (22) or database ports to 0.0.0.0/0. An SSH or database port open to the whole internet is scanned and attacked within minutes. If you need SSH access, restrict it to a known IP or (better) use AWS Systems Manager Session Manager, which gives you a shell on an instance through IAM with no open SSH port at all — the modern, keyless way to reach a server.
  • Restrict the source as tightly as the port. A wide-open port to a narrow source is fine; a narrow port to the whole internet is often not.

The recurring mistake — and a common way AWS environments get breached — is a security group with 0.0.0.0/0 on a sensitive port because someone opened it "to test" and never closed it. Treat every inbound rule as a deliberate exposure you must justify.

Network ACLs: the subnet-level backstop

AWS has a second, lower-level firewall: the network ACL (NACL), which operates at the subnet level (security groups are per-resource). Differences worth knowing:

  • NACLs are stateless — unlike security groups, you must allow both the inbound and the outbound (return) traffic explicitly. This makes them fiddlier.
  • NACLs are subnet-wide — they apply to everything in a subnet, as a coarse backstop.

In practice, you do most of your work with security groups, and leave NACLs at their permissive default for most designs. NACLs are useful as a coarse, subnet-level guardrail — for example, to hard-block a known-bad IP range across a whole subnet, or to add a belt-and-braces deny that security groups back up. Know they exist and what they are for, but security groups are where you spend your time and where your real access control lives.

Check your work

Security group = a virtual firewall per resource with inbound/outbound rules. Default-deny inbound (open only what you need), stateful (a reply to an allowed request is automatically allowed back — no return rule needed). A rule = protocol + port + source.

Key pattern — reference SGs, not IPs: source a rule from another security group, not an IP range. Three- tier: LB SG (443 from 0.0.0.0/0) → App SG (app port from LB SG only) → DB SG (5432 from App SG only). Each layer reachable only from the one in front — defence in depth that stays correct as you scale (no IP ranges to update).

Network least privilege: open only specific ports from specific sources; never SSH/DB ports to 0.0.0.0/0 (scanned in minutes) — restrict to a known IP or use SSM Session Manager (shell via IAM, no open SSH port). The classic breach is a 0.0.0.0/0 sensitive port left open "to test".

NACLs: subnet-level, stateless (allow inbound and return), coarse backstop — leave mostly default; security groups are where your real access control lives.

Practice

  1. Explain what "default-deny inbound" and "stateful" mean for a security group and why stateful is simpler.
  2. Design the three security groups for a load-balancer → app → database chain, referencing SGs as sources.
  3. Explain why referencing a security group as a source beats an IP range, especially as you scale.
  4. Explain why opening SSH or a database port to 0.0.0.0/0 is dangerous, and two safer alternatives.
  5. Explain the difference between a security group and a network ACL (level, statefulness) and when you'd use a NACL.
  6. Identify the exposure in a security group that allows all ports from 0.0.0.0/0, and fix it.

Official documentation

Next: VPC endpoints and private connectivity.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship