Lab 02: The Hardened Subnet That Broke Everything
A security review tightened the data tier NACL to permit only the database port. Inbound looks correct, the security groups allow the traffic, both hosts are healthy — and every connection now hangs. Neither host can see why.
- Debugging time
- ~25 min
- Reading time
- 14 min
- Reported by
- Data Platform
- Tier
- Associate
Reporting service cannot reach the database after a NACL hardening change
Reported by Data Platform
- Environment
- staging
- Region
- us-east-1
- Client subnet
- 10.0.0.0/24 (app-a)
- Target subnet
- 10.0.11.0/24 (data-a)
- Change ref
- CHG-2291 — NACL tightening
Security review flagged that the data tier subnet had a permissive network ACL. We shipped CHG-2291 last night to restrict it to just the database port.
Since then the reporting service cannot connect. It hangs on connect and times out. We have not changed the application, the security groups, or any routing.
What we verified before escalating:
- The data tier NACL explicitly allows inbound TCP 5432 from the VPC CIDR. That is the port.
- The database security group allows 5432 from the app tier security group.
- The app tier security group allows all outbound.
- Both instances are running and both subnets are in the same VPC and AZ.
- The database process is listening —
ss -lntpon it showed0.0.0.0:5432before we lost access.
We are being asked to roll back CHG-2291, but nobody can explain what is actually wrong with it, and the security finding is legitimate. We would rather understand it than revert blindly.
What you are working with
Two subnets in one VPC. No NAT Gateway, no internet gateway on the data side, no Transit Gateway. The failing flow never leaves the VPC.
The connection under investigation is the local one between the two subnets. Only the data subnet has an explicit network ACL, and both of its rules name the service port.
- EC2
Reporting service
i-… in subnet-app-a (10.0.0.0/24)
- FILTER
App subnet NACL — outbound
allow all
- RTB
VPC local route
10.0.0.0/16 → local
- FILTER
Data subnet NACL — inbound
rule 100: allow tcp 5432 from 10.0.0.0/16
- FILTER
Database security group
allow 5432 from sg-app
- DEST
Database host
10.0.11.20:5432 — listening
The outbound path is clean and every check on the ticket confirms it. The request arrives. Trace the reply instead.
Scope and constraints
- In scope: network ACLs, security groups, and the difference between them.
- Out of scope: the database itself, DNS, routing, and the application. The listener works and accepts connections.
- The security finding behind CHG-2291 is valid. Reverting to allow-all is not the answer — find a configuration that is both tight and correct.
- You get a shell on the app tier host only. The data host has no route off the VPC, so Session Manager cannot reach it. That constraint is deliberate and it is part of the lesson.
Deploy the broken state
Download the file below into an empty directory and apply it. Two t3.micro instances, no NAT
Gateway, no interface endpoints — this lab is deliberately cheap to run.
terraform init
terraform apply
# Shell on the app tier
terraform output -raw start_session_command
# The target
terraform output -raw data_private_ipFull source: main.tf. It provisions the VPC, both
subnets and their NACLs, both security groups, VPC Flow Logs to CloudWatch, and two instances. The
data host runs a small Python TCP listener on 5432 — Python because that subnet has no egress to
install anything with.
Allow about two minutes after apply for the listener to start and for flow log records to begin appearing. Flow logs aggregate on a 60-second interval here, so the first records are not instant.
Sign in to continue this lab
This lab is free — it just needs an account. One covers every free lab, on any device, and there is no card and no trial.
Solve it yourself first if you can. The brief is open and needs no account.
Sign in to continue this lab
This lab is free — it just needs an account. One covers every free lab, on any device, and there is no card and no trial.
Solve it yourself first if you can. The brief is open and needs no account.