Exposed AWS Private Network
An internal API in a subnet named "private" answered requests from the internet. I traced it to a shared route table with an internet gateway route, gave the backend its own private route table, and confirmed the API still worked inside the VPC.
Status: REMEDIATED · VERIFIED
TOOLS
Objective
I set out to check whether the separation between a public web server and an internal API was actually enforced, find what exposed the API, fix it, and confirm the two could still talk inside the VPC.
Scenario
The design put a public web server in room32-web-public and an internal API server in room32-backend-private. I wanted to know whether the backend subnet was really cut off from direct internet access.
What I found
0.0.0.0/0 -> Internet GatewayThe private subnet routed to the internet
The backend subnet was associated with room32-shared-rt, the same route table the public subnet used, and it carried a default route to the internet gateway.
From outside, a request to the API on port 8080 came back with the API's response. The workload meant for VPC-only traffic was directly reachable from the internet. The root cause was the missing dedicated private route table.
Public IPs handed out automatically
The backend subnet had MapPublicIpOnLaunch enabled, so the API instance had been given a public IP. Together with the route above, that made it addressable from anywhere.
What I did
- Checked the subnets
I listed the VPC subnets and their
MapPublicIpOnLaunchsetting. - Read the backend route table
I found the shared table and its internet gateway route.
- Found the public IP
I listed the running instances and saw the public IP on
room32-internal-api. - Proved the exposure
A request from the internet to port 8080 returned the internal API's response.
- Gave the backend its own route table
I created
room32-private-rt, confirmed it held only the local VPC route, and swapped the backend subnet onto it. - Stopped automatic public IPs
I disabled
MapPublicIpOnLaunchon the backend subnet.
Validation
The new route table holds only the local route, and the subnet no longer assigns public IPs. A request from the internet now gets no response, while the web server can still reach the API on its private IP:
room32-private-rt: 10.0.0.0/16 -> local
MapPublicIpOnLaunch: False
From the internet: no response
From the web server: curl -s http://10.0.2.10:8080 -> API respondsBefore and after
| CONTROL | BEFORE | AFTER |
|---|---|---|
| Backend route table | Shared with the public subnet | Dedicated private table |
| Internet gateway route | 0.0.0.0/0 to IGW | Removed |
| Public IP auto-assignment | Enabled | Disabled |
| API from the internet | Reachable | No response |
| API inside the VPC | Working | Working |
What I recommend
- 01Give private workloads their own route tables.
- 02Turn off automatic public IP assignment on private subnets.
- 03Review VPC routing regularly for unintended internet paths.
- 04Test that the deployed network matches the intended segmentation, not just the names.
“Network segmentation has to be enforced through routing and network controls. Naming a subnet "private" does not make it private.”
SKILLS IT PROVES
- Cloud Security
- AWS VPC
- Network Segmentation
- Network Security
- Security Risk Assessment
- Vulnerability Remediation
- Security Hardening
- AWS CLI