EduFlow
AWS Cloud Foundations
0%

Section 3 · Core Services

Networking: Amazon VPC, Subnets and Security Groups

18 min4 min readSpot the bug

Lesson at a glance

Lay out a VPC with public and private subnets in two Availability Zones, explain what makes a subnet public, and lock traffic down with security groups and network ACLs.

  1. 1A VPC and its subnets
  2. 2What makes a subnet public
  3. 3Security groups: stateful firewalls on resources
  4. 4Network ACLs: stateless rules on subnets
  5. 5What this costs

No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.

Lantern’s old server had a public IP address and a firewall that, honestly, nobody had looked at in two years. Its database listened on port 5432 on the same machine. On AWS the database will run on its own, and the first question is: who can even reach it? The answer is designed in Amazon VPC, your private network inside AWS.

A VPC and its subnets

A VPC (virtual private cloud) is an isolated network in one Region with an IP range you choose, such as 10.0.0.0/16 (65,536 addresses). Every Region gives each account a default VPC with public subnets, handy for experiments; production gets a VPC you design.

A subnet is a slice of that range inside one Availability Zone, such as 10.0.1.0/24 (256 addresses, of which AWS reserves five). Because subnets are zonal, resilience means pairs: Lantern uses two AZs, each with one public and one private subnet.

A VPC with CIDR 10.0.0.0/16 spans two Availability Zones, each with a public and a private subnet. The public subnets route to the internet gateway. Private subnets in both AZs hold the database and app and send outbound traffic through one NAT gateway in AZ a. Internet gateway VPC 10.0.0.0/16 AZ a AZ b Public 10.0.1.0/24 NAT gateway Private 10.0.11.0/24 RDS primary, app Public 10.0.2.0/24 load balancer (later) Private 10.0.12.0/24 RDS standby, app
Lantern’s VPC: public and private subnets in two Availability Zones

What makes a subnet public

Nothing about the subnet itself. It is the route table:

Text
Public route table               Private route table
10.0.0.0/16  -> local            10.0.0.0/16  -> local
0.0.0.0/0    -> igw-0abc...      0.0.0.0/0    -> nat-0def...

A subnet whose route table sends 0.0.0.0/0 (everything not local) to an internet gateway is public: a resource there with a public IP can talk to the internet and be reached from it. A private subnet has no route to the internet gateway, so nothing on the internet can start a connection to it. If private resources need to start outbound connections, say to download OS updates, they route through a NAT gateway that sits in a public subnet.

Lantern’s database and the migration server go in private subnets. The public subnets hold only the NAT gateway and, later, a load balancer.

Security groups: stateful firewalls on resources

A security group is an allow-list attached to a resource’s network interface: an instance, an RDS database, a Lambda function inside the VPC. Three properties make them pleasant to work with:

  • Allow rules only. Anything not allowed is denied. New groups allow no inbound traffic and all outbound.
  • Stateful. If a request is allowed in, the reply is allowed out automatically.
  • They can reference each other. “Allow 5432 from the lantern-app-sg group” means “from anything wearing that group”, however many instances that is and whatever their IPs.
Terminal
aws ec2 authorize-security-group-ingress \
  --group-id sg-0db1111111111111a \
  --protocol tcp --port 5432 \
  --source-group sg-0app222222222222b

That one rule says it all: the database accepts PostgreSQL from the app tier and nothing else.

Network ACLs: stateless rules on subnets

A network ACL filters traffic at the subnet boundary. It differs from a security group in every way:

Security group Network ACL
Attached to Resources (network interfaces) Subnets
Rules Allow only Allow and deny
State Stateful: replies allowed Stateless: replies need rules
Order All rules considered Lowest rule number first, first match wins

Because ACLs are stateless, allowing inbound 443 is not enough: the reply leaves from port 443 to the client’s ephemeral port (1024–65535), and the outbound rules must allow that too. The default network ACL allows everything both ways, and most teams leave it that way and do the real work in security groups. Reach for a custom ACL when you need a subnet-wide deny, such as blocking an abusive address range.

What this costs

The VPC, subnets, route tables, security groups and ACLs are free. What bills is what you put in them: NAT gateways per hour plus per gigabyte, public IPv4 addresses per hour, and cross-AZ traffic per gigabyte. One NAT gateway per AZ is the resilient choice; a single shared one saves money and accepts that an AZ failure cuts private outbound traffic. For Lantern’s size, the sensible default is one NAT gateway plus gateway endpoints, and revisit when traffic grows. (Since late 2025 AWS also offers a regional NAT gateway that spreads across AZs by itself and needs no public subnet; compare its price before you switch.)

That completes the core services. Section four puts them together and ships the new Lantern.

Key takeaways

  • A VPC is your private network in one Region, and each subnet is an address range inside a single Availability Zone.
  • A subnet is public only because its route table sends 0.0.0.0/0 to an internet gateway; private subnets have no such route.
  • Security groups are stateful allow-lists attached to resources, and they can name another security group as the allowed source.
  • Network ACLs are stateless rule lists on subnets, evaluated in number order, and can deny as well as allow.
  • NAT gateways and public IPv4 addresses bill by the hour, while gateway endpoints let private subnets reach S3 and DynamoDB at no extra charge.

Further reading

Check your understanding

3 questions

Question 1 of 3

Two subnets in Lantern’s VPC are identical except that one has a route 0.0.0.0/0 → igw-0abc… in its route table. What does that route change?

Question 2 of 3

Lantern’s database security group must accept PostgreSQL connections only from the app servers. Which inbound rule is best?

Question 3 of 3

A network ACL allows inbound TCP 443 from anywhere, but HTTPS requests to an instance in the subnet time out, while its security group allows 443. What is the likely cause?

Practice

Spot the bug

Review the security group script

A volunteer wrote this script to create Lantern’s security groups during the migration. The comments describe the intent, and the intent is right. Select every line where the code does not match a safe version of that intent.

Select the line(s) you think are wrong, then check.