Topic 3.3
NACLs & VPC Endpoints
In one line
Network ACLs are a stateless, subnet-level firewall with explicit allow and deny rules; VPC endpoints let private resources reach AWS services without traversing the internet or a NAT.
Think of it like this
A security group is a guard at each apartment door who remembers who went in. A NACL is the gate at the end of the lane with a rulebook — it checks every person in BOTH directions and remembers nobody, so if you allowed someone in, you must separately allow them to leave.
Key ideas
- 01
NACLs are STATELESS: return traffic must be explicitly allowed. Since clients use random EPHEMERAL ports (1024–65535) for replies, a NACL allowing inbound 443 must also allow OUTBOUND to 1024–65535, or responses are silently dropped.
- 02
NACL rules are NUMBERED and evaluated lowest-first; the first match wins. They support DENY rules — their main practical use is quickly blocking a known-bad CIDR at the subnet edge, which security groups can't do.
- 03
The default NACL allows everything; most teams leave it that way and rely on security groups. If you do customise NACLs, keep them coarse (subnet-tier boundaries) — fine-grained rules belong in security groups.
- 04
GATEWAY ENDPOINTS (S3 and DynamoDB only) add a route to your route tables; they're free and should be in essentially every VPC. INTERFACE ENDPOINTS (PrivateLink) place an ENI with a private IP in your subnets for almost every other service (ECR, SSM, Secrets Manager, CloudWatch, STS...), with private DNS so the normal service hostname resolves to it. They cost per hour per AZ plus per GB.
- 05
Endpoints serve two purposes: COST (skip NAT processing charges) and SECURITY (fully private subnets with no internet path at all can still call AWS APIs). Endpoint POLICIES can additionally restrict which buckets or actions are reachable through that endpoint — a guard against data exfiltration to an attacker's bucket.
Code & diagrams
# S3 gateway endpoint — free, route-table based
aws ec2 create-vpc-endpoint --vpc-id $VPC \
--service-name com.amazonaws.ap-south-1.s3 \
--vpc-endpoint-type Gateway \
--route-table-ids $PRIV_RT_A $PRIV_RT_B
# Interface endpoints needed to pull images from ECR in a subnet with no NAT
for svc in ecr.api ecr.dkr logs sts; do
aws ec2 create-vpc-endpoint --vpc-id $VPC \
--service-name com.amazonaws.ap-south-1.$svc \
--vpc-endpoint-type Interface --private-dns-enabled \
--subnet-ids $APP_A $APP_B --security-group-ids $SG_ENDPOINTS
doneOnly our own buckets are reachable through this endpoint — copying data to an outside bucket from inside the VPC fails.
{
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::acme-*", "arn:aws:s3:::acme-*/*"]
}
]
}Explain it without notes
You add a NACL rule allowing inbound TCP 443 to a public subnet, but clients' HTTPS connections hang. Security groups are correct. Why?
What's the difference between a gateway endpoint and an interface endpoint?
Practice
Write NACL rules (number, direction, port, source/dest, action) that block 203.0.113.0/24 but allow HTTPS from everyone else into a public subnet.
An ECS task in a private subnet with no NAT fails with CannotPullContainerError. Which endpoints would you add?
Trade-offs
- ↔
Interface endpoints make private subnets truly private and can be cheaper than NAT for heavy AWS-API traffic, but each one costs per AZ per hour; for low-traffic environments a NAT gateway may be cheaper than a dozen endpoints.
Done when you can
I can explain why NACLs need ephemeral-port rules.
I use NACL deny rules only for coarse blocking and security groups for everything else.
I add an S3 gateway endpoint to every VPC.
I know which interface endpoints a no-NAT private subnet needs for my workload.