An Overview of AWS Security
Groups (SGs) and Network Access Control
Lists (NACLs).
Focus:
- How they work,
- Key differences,
- Best practices,
- Real-world
use cases,
- Troubleshooting
insights — from a DevSecOps / Cloud
Engineering perspective.
Breakdown:
- Overview,
- Technical Behavior,
- How They Work Together,
- Common Misconfigurations &
Troubleshooting,
- Sample Scenario,
- Best Practices,
- Security Architecture Sample (Multi-tier App),
- DevSecOps Integration.
1. Overview
|
Feature |
Security
Groups (SGs) |
Network
ACLs (NACLs) |
|
Scope |
Attached to ENIs (Elastic Network
Interfaces), which belong to EC2 instances, Load Balancers,
etc. |
Associated with subnets in a VPC |
|
Layer |
Operates at the instance level
(ENI) |
Operates at the subnet level |
|
Statefulness |
Stateful – Return traffic is automatically allowed |
Stateless – Return traffic must be explicitly allowed |
|
Rules Type |
Only allow rules |
Allow and deny rules |
|
Default Behavior |
Denies all inbound traffic, allows
all outbound traffic |
Allows all inbound/outbound traffic (by default NACL) |
|
Evaluation Order |
All rules are evaluated together;
implicit deny if not matched |
Rules are evaluated in order,
starting from the lowest numbered rule |
|
Attached To |
ENIs (EC2, ALB, RDS, Lambda ENI, etc.) |
Subnets (affects all ENIs in subnet) |
2. Technical Behavior
Security
Groups (SGs)
- Stateful:
- When twtech allows inbound TCP traffic
on port 22, the response
traffic (ephemeral ports) is automatically
allowed, even if no outbound rule allows it.
- Implicit deny:
- If a rule doesn’t explicitly allow
traffic, it’s dropped.
- Applied at the ENI level:
- An EC2 instance can have multiple SGs,
and rules are aggregated (union of
all allow rules).
- Rule evaluation:
- No priority numbers — all rules are
checked, and if any match, the packet is allowed.
Example:
Inbound Rule:
- Type: SSH (22)
- Source: 203.0.113.0/24
- Means: Only that CIDR block can initiate SSH
sessions.
- Outbound is allowed to anywhere (0.0.0.0/0) by default, but twtech can restrict it.
Network ACLs (NACLs)
- Stateless:
- twtech must create both inbound and outbound rules to allow bidirectional communication.
- Rule evaluation:
- Lowest numbered rule wins.
- Default NACL:
- Allows all inbound and outbound traffic.
- Custom NACL:
- Denies all inbound and outbound traffic by default until rules are added.
- Rules include an explicit DENY option.
Example:
- Rule #100 ALLOW TCP 22 203.0.113.0/24
- Rule #200 DENY ALL ALL
NB:
- Here, SSH is allowed for the specified source, everything else denied.
3. How They Work Together
|
Layer |
Filtering |
Applied
To |
Example |
|
|
NACL |
Subnet-level. |
Ingress/Egress for the entire subnet. |
Controls traffic entering/leaving
subnet |
|
|
SG |
Instance-level. |
ENI (interface). |
Controls traffic to/from specific
instance |
|
Traffic
flow example (Inbound):
- Packet enters VPC subnet.
- Inbound NACL evaluated (stateless).
- If allowed → reaches ENI.
- Security Group inbound rules evaluated (stateful).
- If allowed → packet delivered to
instance.
Outbound flow:
- Instance
sends packet.
- SG outbound rules checked (stateful).
- If allowed → passes
subnet boundary.
- Outbound NACL checked.
- If allowed → leaves VPC.
4. Common Misconfigurations &
Troubleshooting
|
Issue |
Root
Cause |
Fix |
|
Can’t
SSH into EC2 |
SG inbound missing TCP:22 rule or
NACL denies it. |
Add inbound SG rule for TCP:22 and
ensure NACL allows it |
|
Web
app unreachable from internet |
SG inbound missing HTTP/HTTPS rule. |
Add SG inbound 80/443 from 0.0.0.0/0
(or CDN/WAF IPs) |
|
Traffic
blocked randomly |
Overlapping NACL rules, order issues. |
Check rule numbers and implicit DENY |
|
Return
traffic blocked |
NACL missing reverse-direction rule. |
Add matching outbound (for inbound) or inbound (for outbound) |
|
EFS
mount fails |
NACL or SG missing NFS (2049). |
Add TCP 2049 in both inbound and
outbound SG + NACL |
6. Sample Scenario
Goal: Allow a web app on EC2 to be reachable
on port 80 from anywhere.
SG
Inbound:
- Type: HTTP
- Protocol: TCP
- Port: 80
- Source: 0.0.0.0/0
Outbound:
- Type: All Traffic
- Destination: 0.0.0.0/0
NACL
Inbound:
- Rule #100 ALLOW TCP 80 0.0.0.0/0
- Rule #200 ALLOW TCP 1024-65535 0.0.0.0/0
- Rule #300 DENY ALL
Outbound:
- Rule #100 ALLOW TCP 1024-65535 0.0.0.0/0
- Rule #200 ALLOW TCP 80 0.0.0.0/0
- Rule #300 DENY ALL
6. Best Practices
✅ Use
Security Groups as twtech primary
defense for EC2-level access control.
✅ Use NACLs for coarse-grained subnet-level boundaries (like DMZ vs.
private subnets).
✅ Least privilege – open only
required ports and IP ranges.
✅ Use descriptions in rules –
document the reason for each port/IP.
✅ Avoid overly
broad rules like 0.0.0.0/0 unless behind
WAF, CDN, or VPN.
✅ Consider automation (Terraform,
CloudFormation, AWS Config) for consistent SG/NACL
rules.
✅ Enable VPC Flow
Logs to trace blocked/allowed traffic for debugging.
7. Security Architecture Example (Multi-tier App)
|
Layer |
Subnet |
SG
Rules |
NACL
Rules |
|
Public
(Web) |
Public Subnet |
Inbound 80/443 from Internet |
Inbound allow 80/443, outbound allow
ephemeral ports |
|
App |
Private Subnet |
Inbound 8080 from Web tier |
Inbound allow 8080 from Web subnet,
outbound allow 3306 |
|
DB |
Private Subnet |
Inbound 3306 from App tier |
Inbound allow 3306 from App subnet,
outbound allow ephemeral |
8. DevSecOps
Integration
Integrate SG and NACL management with:
- Terraform or Pulumi for IaC-based policy control.
- AWS Config rules:
- restricted-ssh or restricted-common-ports
- vpc-sg-open-only-to-authorized-ports
- GuardDuty + Security Hub for anomaly detection on network access.
- Automated SG cleaner to remove unused rules.
Project: Hands-On
- How twtech uses the Network
Access Control List (NACL) and Security groups to assign by a
client’s operating system (OS) for outbound connections in its environment.
Search for AWS service: Network ACLs
Step-1: From the EC2 console
Start a http server in the Bastion Host (server):
Step-2:
Install http package in Bastion Host Server with the command:
sudo yum install httpd
-y
Step-3:
Enable the webserver with a command: This creates a soft link for httpd
sudo systemctl enable httpd
Step-4:
Start the webserver with the command:
sudo systemctl start httpd
Step-5:
Check status of the webserver with the command:
sudo systemctl status httpd
Step-6:
Switch to root user:
sudo su
Add some worlds into the httpd file: /var/www.html/index.html
echo "Hello twtech NACL Team" > /var/www/html/index.html
Step-7:
Edit and add (allow traffice to) HTTP(80) on the Bastion Host firewall (security group)
Edit security group:
From:
To:
Save changes in inbound rules(SG)
Step-8:
Return to EC2 console and Copy the Public IPv4 address of Bastion
Host (where httpd is installed) to
access it on the browser.
From Google chrome browser:
Step-9:
To demonstrate how NACL and Security group works, twtech needs to: Edit the
inbound rules of DefaultNACL:
From:
Rule #100: Allow all traffic from anywhere
To:
Rule # 80:
Deny only HTTP (80) traffic from anywhere.
Remember to click on: Sort by rule numbers
From:
To:
Save changes in NACL rules:
twtech explanation:
- twtech has blockes the default NACL traffic to httpd client installed: to verify
behavior when default NACL traffic is
block.
- Return to
browse and try to access the httpd again.
- Default NACL is acting as the firewall and
blocks traffic to hpptd
From:
To:
refresh page
Again if twtech edits the default NACL inbound rules:
To Rule # 140:
Deny all HTTP
(80) traffic from anywhere.
From:
How twtech demonstrates the behavior of default NACL outbound rules to traffic.
From:Rule #100 only: Allow
all traffic from anywhere
To:
Rule #100 only: Deny
all traffic from anywhere
Save changes:
Trying the browser again to see the behavior: when all
traffic is denied on the outbound rule of default NACL
- Again: Accessing
the httpd from browser is blocked by default NACL
From:
twtech Final thoughts:
- NACL and Security group work
together.
- Default NACL rules (inbound) may affect the behavior of traffic
irrespective of the right Port assigned at the firewall (security group)
- For troubleshooting network
issues, make sure the right (needed)
ports is opened on the Security group ( firewall) as well as make sure the right
configuration (Rule# / Acess deny or
Allow) is assigned on the NACL (inbound/outbound) rules
Restoring traffic to httpd:
· Check the security group of the
Bastion Host server (where
httpd is installed)
· Check both the NACL inbound /
outbound Rules for proper configuration.
Application accessible again on the browser:
twtech demonstration on how outbound rule behavior to traffic for the applications:
Edit:
From:
To: Delete
rule that allows all outbound (outgoing) traffic.
Save changes: No outbound rules
twtech can still access the http application on the browser: the outbound rule has no impact to
traffic if not assigned
twtech explanation:
- The inbound rule is stateful (does not change except altered).
- But outbound rule is statelss (if traffic is allow in the inbound rule, the outbound rule will return traffic Normally without being affected)
No comments:
Post a Comment