VPC
Additional Resources
AWS Networking Fundamentals Guide
VPC Basics
What is a VPC?
A Virtual Private Cloud (VPC) is an isolated area of your AWS account with its own virtual network and IP address space. Nearly every AWS resource deploys into a VPC.
A VPC, or virtual private cloud, is an isolated area of your AWS account that has its own virtual network and IP address space. Just about every AWS resource deploys into a VPC. If you don’t explicitly specify a VPC, the resource will be deployed into the Default VPC, which is part of every AWS account created after 2013. If for some reason you deleted the Default VPC in your account, either use a different region (each region has its own Default VPC) or create a new Default VPC using the AWS Web Console. Otherwise, you’ll need to update almost every example to include a vpc_id or subnet_id parameter pointing to a custom VPC.
VPCs can’t span across regions, they are always within one. You can create up to 5 VPC within a Region (unless you request more). To communicate across regions, you would use VPC peering, VPN, or Transit Gateway to connect separate VPCs in different regions.
Default VPC
Every AWS account created after 2013 includes a Default VPC in each region.
If you don't specify a VPC, resources deploy to the Default VPC automatically
If for some reason you deleted the Default VPC in your account, either use a different region (each region has its own Default VPC) or create a new Default VPC using the AWS Web Console.
Each region has its own Default VPC with a Public Subnet in each AZ and an internet gateway. It can allow you to quickly launch public internet facing EC2 instances (or other resources) without additional setup. This however, is only recommended for experimenting, because for many real-world cases you'll likely not want directly public facing resources. You should create custom VPCs for your specific use cases.
Without a Default VPC, you'll need to specify vpc_id or subnet_id parameters pointing to a custom VPC when creating resources.
IP Addressing and CIDR Blocks
What is a CIDR Block?
CIDR (Classless Inter-Domain Routing) defines a range of private IP addresses available within your VPC.
Or how many private IP addresses are available in the VPC.
Any resource that will be deployed in this VPC will be assigned an IP address from that range.
If you want a resource to be public, you will need to assign a public IP address to it which will come from a pool of AWS managed public IPs. So CIDR is only responsible for private IP addresses.
Can be IPv4 or IPv6.
Tool: Use cidr.xyz for CIDR calculations
IP Address Structure
IPv4 addresses consist of 32 bits total
Divided into 4 octets (8 bits each)
Each octet can range from 0-255
Example:
10.0.0.0
Understanding CIDR Notation
Example: 10.0.0.0/16
10.0.0.0= Starting address of the network/16= Prefix length (how many bits define the network portion)
Breakdown:
32 total bits in an IPv4 address
/16 means first 16 bits (2 octets) are fixed for the network
Remaining 16 bits (2 octets) are available for host addresses
This allows 65,536 possible IP addresses (2^16)
Visual representation:

This means that every IP address in that private network will start with 10.0._._, where the other 2 numbers can be anything from the range 0-255.
All IPs in this network: 10.0.0.0 through 10.0.255.255
Different Prefix Lengths
If you had other prefix length, you would allow more places to be used as network part of the address.

/16
16
16
65,536
10.0.0.0 - 10.0.255.255
/24
24
8
256
10.0.0.0 - 10.0.0.255
/28
28
4
16
10.0.0.0 - 10.0.0.15
Private vs Public IP Addresses
CIDR blocks assign private IPs used within your VPC
Public IPs come from AWS-managed pools and must be explicitly assigned
Resources need public IPs to be directly accessible from the internet
IPv6 Support
VPCs can also use IPv6 CIDR blocks in addition to or instead of IPv4.
Subnets: Public vs Private
Subnets are segments of your VPC's IP address range where you can place groups of isolated resources.
Public Subnets
Resources can communicate directly with the internet
Require an Internet Gateway
Typically host: Load Balancers, NAT Gateways, Bastion Hosts
A “public subnet” in AWS is not truly public in the sense of being exposed to everyone. It is still private, internal, and isolated inside your VPC.
The term “public” only means:
Resources inside this subnet can reach the internet directly because the subnet’s route table has a default route (0.0.0.0/0) pointing to an Internet Gateway (IGW).
Nothing more.
A public subnet = private AWS subnet with a route to the Internet Gateway.
That’s it.
It is still:
inside your VPC (isolated from other VPCs)
using private IP addresses
governed by security groups and NACLs
invisible to the internet unless you allow it
not reachable unless an instance inside has a public IP or Elastic IP
So even “public” subnets aren’t exposed unless you explicitly open them.
But in AWS networking, it's a logical concept:
Public subnet = traffic may go out to the internet
Private subnet = traffic cannot go out directly
Neither is actually “public” in the sense of a LAN with no firewall.
What does get exposed in a public subnet?
Only resources that meet all of these conditions:
They have a public IP or Elastic IP
Their subnet route table has 0.0.0.0/0 → IGW
Their security group allows inbound internet traffic
Their NACL allows inbound/outbound traffic
If any of those is missing → they are NOT reachable from the internet.
Why do we even need “public subnets”?
To host things that must talk directly to the internet, such as:
load balancers (ALB/NLB with public IP)
bastion hosts (if not using SSM Session Manager)
NAT gateways
public-facing APIs
reverse proxies
CloudFront origins (if you’re not using OAC)
Everything else (databases, app servers, EMR, ECS tasks, Lambda ENIs) belongs in private subnets.
Public ≠ Unsecured
Example:
EC2 in public subnet
Public IP: yes
SG: denies all inbound → Completely unreachable, despite being in a public subnet.
EC2 in private subnet
NAT gateway: yes
SG: allows egress → Can access internet outbound but cannot be accessed inbound
Private Subnets
Resources cannot be directly accessed from the internet
Can initiate outbound connections via NAT Gateway
Typically host: Application servers (EC2), Databases (RDS), Internal services
Best Practice
Use private subnets for application and data layers, public subnets only for internet-facing components.
Gateways and Connectivity
Internet Gateway (IGW)
Enables communication between your VPC and the internet
Allows resources in public subnets to send/receive internet traffic
Horizontally scaled, redundant, and highly available
Required for resources that need direct internet access
Use cases:
Receiving requests through Application Load Balancers
Allowing users to access public-facing applications
Downloading updates and patches from the internet
NAT Gateway (Network Address Translation)
Allows resources in private subnets to access the internet or other AWS services
But prevents the internet from initiating inbound connections to those resources
Acts as a one-way door for outgoing traffic but protects from ingoing traffic
Think of it as: A controlled doorway that allows outbound traffic while protecting internal resources.
Architecture:
NAT Gateway resides in a public subnet
Private subnet resources route through it for internet access
Provides security by hiding private IPs from the internet
Use cases:
Downloading software updates and patches
Accessing external APIs
Pulling container images
Connecting to external databases or services
Key Difference
Internet Gateway: Two-way communication (public subnets)
NAT Gateway: One-way outbound only (private subnets)
What is Elastic IP (EIP)?
What it is: A static, public IPv4 address that you can attach to an EC2 instance or NAT gateway.
Why it exists: Normally, EC2 public IPs change when you stop/start the instance. Elastic IP stays the same, so you can reliably point clients or DNS records to the instance.
Typical use-cases:
When a public-facing server needs a fixed IP (e.g., a legacy app that doesn't use DNS).
When you need a stable SSH/RDP access point.
When you want to quickly remap the IP to another instance during failure (zero DNS propagation time).
Key notes:
Only IPv4.
AWS charges you when an EIP is not attached, encouraging you not to “hoard” public IPs.
Route Tables
What are Route Tables?
Route Tables contain rules (routes) that determine where network traffic is directed within your VPC.
Default Route Table
When you create a VPC, AWS automatically creates a default Route Table that:
Allows internal communication within the VPC (between subnets)
Does NOT include routes for internet connectivity
Route Table Association
Each subnet must be associated with one Route Table
Multiple subnets can share the same Route Table
You can create custom Route Tables for different requirements
Configuring Route Tables
For Public Subnets:
This routes all internet-bound traffic (0.0.0.0/0) to the Internet Gateway.
For Private Subnets:
This routes internet-bound traffic through the NAT Gateway in the public subnet.
Important
Without proper route configurations, your subnets won't know how to direct traffic to the internet or even within the VPC itself.
Security: ACLs and Security Groups
AWS provides two layers of security for controlling network traffic.
Security Groups (Instance-Level Firewall)
Characteristics:
Operate at the instance level (EC2, RDS, etc.)
Stateful: Return traffic is automatically allowed
Act as virtual firewalls for individual resources
Default Behavior:
❌ Deny all inbound traffic by default
✅ Allow all outbound traffic by default
Rules:
Specify allowed traffic using protocol, port, and source/destination
No explicit "deny" rules (only allow rules)
Changes take effect immediately
Example: EC2 Security Group
Security Group Chaining
A powerful pattern where Security Groups reference each other:
Example Architecture:
ALB Security Group: Allows HTTP/HTTPS from internet (
0.0.0.0/0)EC2 Security Group: Allows traffic only from ALB Security Group
RDS Security Group: Allows traffic only from EC2 Security Group
Traffic Flow:
This creates a secure chain where each layer only accepts traffic from the previous layer.
Network ACLs (Subnet-Level Firewall)
Characteristics:
Operate at the subnet level
Stateless: Must explicitly allow both inbound AND outbound traffic
Provide an additional security layer
Rules are evaluated in numerical order
Default Behavior:
✅ Allow all inbound traffic by default
✅ Allow all outbound traffic by default
When to Use:
Implementing security policies at the subnet level
Blocking specific IP ranges across all resources in a subnet
Meeting compliance requirements for layered security
Granular control over traffic patterns
Example: Network ACL
Security Groups vs Network ACLs
Level
Instance
Subnet
State
Stateful
Stateless
Rules
Allow only
Allow and Deny
Default
Deny inbound, Allow outbound
Allow all
Evaluation
All rules
Numerical order
Return Traffic
Automatic
Must be explicit
Best Practices
Use Security Groups as your primary defense
Use Network ACLs for additional subnet-level controls
Implement Security Group chaining for layered security
Follow the principle of least privilege (only allow necessary traffic)
Load Balancing
Application Load Balancer (ALB)
The ALB distributes incoming application traffic across multiple backend targets (EC2 instances, containers, etc.).
Why Use an ALB?
Distributes traffic for high availability
Performs health checks on targets
Supports path-based and host-based routing
Handles SSL/TLS termination
Provides connection draining and sticky sessions
Typical Architecture:
Placement:
ALB must be in public subnets (at least 2 for high availability)
Targets (EC2) typically in private subnets
ALB Security Group allows internet traffic
EC2 Security Group allows traffic only from ALB
Key Features:
Layer 7 (Application layer) routing
Content-based routing
WebSocket and HTTP/2 support
Integration with AWS services (ECS, EKS, Lambda)
VPC Peering
What is VPC Peering?
A VPC peering connection allows two VPCs to communicate using private IP addresses as if they were in the same network.
Documentation: AWS VPC Peering Guide
Use Cases:
Connecting different environments (dev, staging, prod)
Sharing resources between different applications
Connecting VPCs across different AWS accounts
Multi-region architectures
Limitations:
No transitive peering (if VPC A peers with B, and B peers with C, A cannot communicate with C)
CIDR blocks cannot overlap
Must update route tables in both VPCs
Configuration Steps:
Create peering connection request
Accept the request in the peer VPC
Update route tables in both VPCs
Update Security Groups to allow traffic
Troubleshooting Connectivity
When encountering connectivity issues, check these components in order:
1. Route Tables
✅ Does the subnet have a route to the destination?
✅ Is the route pointing to the correct target (IGW, NAT, etc.)?
✅ Is the subnet associated with the correct Route Table?
2. Internet Gateway / NAT Gateway
✅ Is the IGW attached to the VPC?
✅ Is the NAT Gateway in a public subnet?
✅ Does the NAT Gateway have an Elastic IP?
3. Security Groups
✅ Are inbound rules allowing the required traffic?
✅ Are you specifying the correct protocol and port?
✅ Is the source specified correctly (IP, CIDR, or Security Group)?
4. Network ACLs
✅ Are both inbound and outbound rules configured?
✅ Is traffic being explicitly denied?
✅ Are ephemeral ports allowed for return traffic?
5. Instance/Resource Level
✅ Does the instance have a public IP (if in public subnet)?
✅ Is the application/service running and listening on the correct port?
✅ Are OS-level firewalls (iptables, Windows Firewall) configured?
6. DNS and Connectivity
✅ Can you resolve DNS names?
✅ Are you using the correct endpoint/hostname?
✅ Is the VPC DNS resolution enabled?
Debugging Tools
VPC Flow Logs: Capture IP traffic information
VPC Reachability Analyzer: Test connectivity between resources
Network Access Analyzer: Identify unintended network access
AWS CLI/Console: Verify configurations
ping/telnet/nc: Test connectivity from instances
Cost Considerations
Understanding AWS networking costs helps optimize your architecture.
Resource: AWS Networking Costs Blog
Key Cost Factors
1. Data Transfer Costs
Within the same AZ: Usually free
Between AZs in same region: ~$0.01/GB each way
Between regions: ~$0.02/GB
To internet: Starts at $0.09/GB (decreases with volume)
From internet: Free
2. NAT Gateway Costs
Hourly charge: ~$0.045/hour
Data processing: ~$0.045/GB processed
Can become expensive with high traffic volumes
3. Load Balancer Costs
ALB hourly charge: ~$0.0225/hour
LCU (Load Balancer Capacity Units): Based on traffic processed
4. VPC Endpoints (Optional)
Interface endpoints: ~$0.01/hour per AZ + data processing
Gateway endpoints (S3, DynamoDB): Free
Cost Optimization Tips
Use VPC endpoints to avoid NAT Gateway charges for AWS services
Keep resources in the same AZ when possible
Use CloudFront CDN to reduce data transfer costs
Consider single NAT Gateway for non-production environments
Monitor and analyze traffic patterns with VPC Flow Logs
Use AWS Cost Explorer to identify expensive data transfer paths
Bastion Host (Jump Host)
What it is: A hardened EC2 instance in a public subnet used as a secure entry point to access servers in private subnets.
Why it exists: You don’t want to expose your private servers directly to the internet. Instead, you SSH into the bastion, and from there, SSH into private instances.
Typical design:
Bastion in public subnet, with:
a security group allowing SSH only from specific IPs (your office / home)
tight IAM + auditing
Private instances' security groups allow SSH only from the bastion SG.
Modern alternative: AWS SSM Session Manager (more secure, no inbound ports, no Bastion needed).
Summary of concepts


Quick Reference Architecture
Typical Production VPC Setup
Security Group Chain
Route Table Configuration
Example Scenario
A web application running on an EC2 instance that allows you to query a database running on RDS.
Here's roughly what it would look like:
Creating a VPC

1 VPC with two AZs with 1 Public and 1 Private Subnet in each.
EC2 and RDS deployed in the Private Subnets
And NAT Gateway deployed in the Public Subnets
1 ALB to manage and route traffic to EC2 and RDS
Here's configuration you would do for your subnets:
Subnet Name
CIDR Block
AZ
Usage
Public Subnet 1
10.0.1.0/24
AZ 1
Public subnet
Private Subnet 1
10.0.2.0/24
AZ 1
Private subnet
Public Subnet 2
10.0.3.0/24
AZ 2
Public subnet
Private Subnet 2
10.0.4.0/24
AZ 2
Private subnet

Note that there's no internet connectivity for now, and no Application Load Balancer. If you deploy any resources into a Public Subnet, they will not be accessible via the internet and will not be able to establish connections to other resources on the internet either. That is because VPC with Subnets alone create an isolated network with no traffic in or out.
In fact, both the EC2 instance and RDS should be in private subnets and wouldn't need direct connectivity with the Internet. But there are 2 considerations to keep in mind:
The first is that the applications running on the EC2 do need to occasionally download updates from resources on the Internet for things like application upgrades and patching.
And the second consideration is that you would still need a way to submit requests to the application running on the EC2 Instance through the load balancer so that you can query your data on RDS.
Internet Gateway and NAT Gateway
We need to add an Internet Gateway as the "door" to our network. Internet gateways allow resources in your public subnets to connect with the Internet. They support both inbound and outbound traffic.
Creating and attaching an Internet Gateway is however only 1 step towards allowing to-/inbound connections to our public subnets. You also need to configure routes in the Route Table and Network Security Rules.
We will be attaching an Internet gateway to allow traffic to flow to and from the public subnets. How will this help if our resources are in the private subnets?
Taking into account the 2 considerations we mentioned earlier, our EC2 instance needs to be able to make outgoing connections from the VPC in order to download updates. On top of that, we need the ability to submit requests to the application from the internet. The NAT gateway and ALB can help us meet those requirements.
With a NAT gateway in place, your EC2 Instances in the private subnet can download updates and patches from the Internet without exposing them directly to the public Internet.
The next requirement is allowing external users to submit requests to our application. The ALB distributes incoming traffic across multiple back end targets (e.g. EC2 instances) across two AZs. It will be the entry point for external users. This way, ALB will handle the load and ensure the app remains responsive and its resources (EC2) are private.

In the Management Console or via any other method, create and attach and Internet Gateway to your VPC. Create NAT gateways for each public subnet and attach an Elastic IP.
Configuring a Route Table
Route tables are essentials for directing network traffic within your VPC.
Each subnet can be associated with a Route table which contains a set of rules/routes that determine where network traffic is directed.

When you create a VPC, AWS automatically creates a Default Route Table. This default route table allows internal communication within the VPC, meaning resources in different subnets can communicate with each other. However, it doesn't include routes for internet connectivity. This is where you need to customize your Route tables to meet your specific requirements. Without these routes your subnets won't know how to direct traffic either to the internet or within the VPC itself.
For public subnets, you'll configure the route table to direct all internet bound traffic to the Internet Gateway. This allows resources in the public subnet to access the internet.
For private subnets, you'll direct internet bound traffic to the NAT Gateway in the public subnet. This allows resources in the private subnet to make outbound connections to the internet while preventing inbound connections from the internet.
Network ACLs and Security Groups
In our scenario, the ALB will send internet traffic to the EC2 instances which would then create connections with the RDS instances for queries. You can configure networking rules to allow only the network traffic you want to reach these instances. By default, no traffic is allowed to reach these instances, even with the route tables in place. To change that, you first need to understand Security Groups (SGs) and Network Access Control Lists (NACLs or Network ACLs).
Think of Security Groups as instance-level virtual firewalls, controlling both inbound and outbound traffic.
By default, Security Groups deny all inbound traffic and allow all outbound traffic.

This statefulness simplifies the network management, because you don't have to create matching outbound rules for every inbound rule.
Resources that are placed in VPCs such as EC2 instances, ALB, and RDS databases use Security Groups. All can use different security rules and the rules for Security Groups can reference other Security Groups.
In our example, we have an ALB that would need to accept traffic for HTTP on port 80 and HTTPS on port 443 from the internet. Then, we have an EC2 instance hosting a web server, so you need to allow HTTP and HTPS traffic coming from the ALB. So, you could reference these security groups used by the load balancer.

We also have RDS database instances which would need to allow TCP on port 3306 (which is commonly used for MySQL) coming from the securty group used by EC2 instances. This is called Security Group Chaining.
Now, let's talk about Network ACLs which provide an additional layer of security at the Subnet level. Unlike security groups which are stateful, NACLs are stateless. This means you need to define both inbound and outbound rules explicitly. They offer more granular control over the traffic and can be particularly useful for implementing security policies at the subnet level.
By default, Network ACLs allow all inbound and outbound traffic, but you can modify these rules to meet your specific requirements.
Here's how our infrastructure ended up looking:

Last updated