1. Introduction
When setting up AWS infrastructure, private EC2 instances don’t have direct internet access by design. However, they often need outbound connectivity for updates and patches. To enable this securely, AWS uses a networking model with public and private subnets, a NAT gateway or instance, and route tables. Public instances connect directly through an Internet Gateway (IGW), while private instances route traffic through a NAT in the public subnet. This blog explains how to design and connect both public and private EC2 instances to the internet step by step.
Prerequisites
Before getting started, make sure you have the following:
- An AWS account with sufficient permissions (VPC, EC2, NAT Gateway, Internet Gateway).
- An SSH client (e.g., PuTTY on Windows or terminal on macOS/Linux).
2. VPC Basics for Our Setup
Virtual Private Cloud (VPC)
A VPC is your isolated network inside AWS. When you create a VPC, you must specify an IPv4 CIDR block. Allowed block size ranges from /16 (65,536 IPs) to /28 (16 IPs).
Subnets
Subnets are smaller networks carved out of your VPC’s IP range.A subnet must be fully contained in one Availability Zone (AZ) — it cannot span across multiple AZs.
In every subnet, AWS reserves 5 IPs that cannot be used, if your subnet is 192.168.2.0/25 (128 IPs: .0–.127):
- 192.168.2.0 → Network address (subnet identifier)
- 192.168.2.1 → VPC router (always the first usable IP)
- 192.168.2.2 → Reserved for Amazon DNS (if DNS is enabled in the VPC)
- 192.168.2.3 → Reserved for future use
- 192.168.2.127 → Broadcast address (reserved, not usable)
That leaves you with usable IPs from 192.168.2.4 to 192.168.2.126 → a total of 123 usable IPs.
Every subnet must be associated with a route table, which controls how traffic is forwarded.To calculate the subnets you are going to use, to can use this online-based subnet calculator
Public vs Private Subnets
Public Subnet A subnet whose route table has a route to an Internet Gateway (IGW).
- Use case: Resources that must be directly reachable from the internet.
- Examples: Bastion hosts, public-facing load balancers, or web servers.
Private Subnet A subnet without a direct route to the IGW. Instead, it may use a NAT Gateway/Instance for outbound-only internet access.
- Use case: Resources that should not be reachable from the internet, but still need outbound access.
- Examples: Application servers, databases, or internal services.
Route Tables
A route table is a set of rules that determine how network traffic is routed from your subnet.
Destination→ where the traffic is going.Example: 10.0.0.0/16 (local VPC traffic), 0.0.0.0/0 (all IPv4 internet traffic), ::/0 (all IPv6 traffic).
Target → the “next hop” that forwards the traffic.
- Local (VPC internal routing)
- Internet Gateway (IGW) → to the internet
- NAT Gateway → for private subnet outbound internet
- VPC Peering connection → to another VPC
- VPN / Virtual Private Gateway (VGW) or Transit Gateway (TGW) → to on-prem
Gateways
Gateways connect your VPC to other networks.
- Internet Gateway (IGW) → Allows public subnets to connect to the internet.
- NAT Gateway or NAT Instance → Allows private subnets to reach the internet outbound only.
- NAT Instance: EC2 instance you manage yourself.
- NAT Gateway: Fully managed by AWS (preferred).Requires an Elastic IP (EIP) for outbound traffic. Must be launched in a public subnet (so it can reach the internet via IGW).NAT is stateful, meaning it keeps track of the state of active connections. If a device initiates a connection, the return traffic is automatically allowed, even if there’s no explicit inbound rule.
Elastic IP (EIP)
An Elastic IP is a static, public IPv4 address in AWS.EIPs can be associated with EC2 instances, network interfaces, or AWS resources.
Why it’s important:
- Static Public Address → Doesn’t change when instances stop/start.
- High Availability → Can be reassigned to another instance in the same region.
- Required for NAT Gateway → NAT needs a stable outbound IP.
- Firewall Whitelisting → External systems can safely whitelist your static
Security Controls
Security Groups (SGs) → Instance-level firewall.
Network ACLs (NACLs) → Subnet-level firewall.
3. Step-by-Step Setup
Step 1: Create the VPC, Subnets, and Internet Gateway
1. Create a VPC
- Log in to your AWS Management Console.
- Select a Region (e.g.,
us-east-1
). - In the search bar at the top, type VPC and open the service.
- Click Create VPC.
- Choose VPC only.
- Enter a name (e.g.,
MyDemoVPC
). - Set the IPv4 CIDR block to
192.168.0.0/20
. - Leave other options as default and click Create VPC.
2. Create Subnets
- On your VPC dashboard select Subnets on the left menu and choose Create subnet.
- Choose the VPC you just created.
- Provide subnet name: public-subnet
- Select an Availability Zone (e.g.,
us-east-1a
). - IPv4 subnet CIDR block →
192.168.2.0/25
Click Add new subnet to add the private subnet:
- Name: private-subnet
IPv4 subnet CIDR block →
192.168.2.128/25
Click Create subnet.
Go to the public subnet, select it → Actions → Edit subnet
settings.
- Enable Auto-assign public IP and save.
3. Create and Attach an Internet Gateway (IGW)
- In the VPC dashboard, go to Internet Gateways → Create internet gateway.
- Enter a name (e.g.,
MyDemoIGW
) and click Create. - Select the newly created IGW (it will show as detached) → Actions → Attach to VPC.
- Choose your VPC (
MyDemoVPC
) and confirm.
4. Update Route Table for the Public Subnet
- In the VPC dashboard, go to Route Tables.
- Find the route table associated with your VPC (not the default route table).
- Rename it (e.g.,
main-RT
) and save. - On the Subnet Associations tab, confirm subnets explicitly associated.
- On the Routes tab, click Edit routes
and add:
-
Destination:
0.0.0.0/0
-
Target: Internet Gateway (
MyDemoIGW
)
Save changes.
- Go to Subnet associations → Edit subnet associations → Select your public subnet → Save.
Step 2: Create a NAT Gateway for the Private Subnet
- Go to NAT Gateways in the VPC dashboard → Create NAT Gateway.
- Name it:
MyDemoNATGateway
. - Place it in the public subnet.
- Connectivity type → Public.
- Allocate and attach an Elastic IP.
- Click Create NAT Gateway.
Step 3: Update Route Table for the Private Subnet
- Go to Route Tables → Create route table.
- Name it
private-RT
. - Select your VPC and create.
- Under Subnet Associations → Edit subnet associations → Select private subnet → Save.
- Under Routes → Edit routes → Add route:
-
Destination:
0.0.0.0/0
-
Target: NAT Gateway (
MyDemoNATGateway
)
-
Destination:
- Save changes.
Step 4: Create a Key Pair
- Go to EC2 Dashboard → Key Pairs → Create key pair.
- Name:
mydemokey
. - Private key format:
.ppk
(for PuTTY).
- Create key pair (private key will be downloaded automatically).
Step 5: Launch EC2 Instances
Public EC2
- Go to EC2 Dashboard → Instances → Launch instance.
- Name:
public-ec2
. - Instance type:
t2.micro
. - Select your key pair (
mydemokey
). - Network settings:
- VPC:
MyDemoVPC
- Subnet: public-subnet
- Enable auto-assign public IP.
- VPC:
- Firewall (security group):
- Name:
public-sg
- Inbound rule: SSH (source type: My IP).
- Name:
- Leave other options as default
- Launch instance.
Private EC2
- Repeat the steps above.
- Name:
private-ec2
. - Subnet: private-subnet.
- Disable auto-assign public IP.
- Firewall (security group):
- Name:
private-sg
- Inbound rule: SSH (source Type: custom, source:
public-sg
).
- Name:
- Launch instance.
SSH into Private EC2 via Public EC2
-
Start Pageant
- Search Pageant on your machine and open it. Once it’s opened, you’ll see it in the taskbar.
- Right-click on it → Add Key → Select your private key.
- Save the session so you don’t have to redo this step.
-
Get EC2 Connection Details
- In the AWS EC2 Dashboard → Select your public instance → Click Connect → Choose SSH Client.
- You will see the username of the EC2 instance and its public IP.
- Note both, since you will need them in the next step.
- Repeat the same process for your private instance (make sure you select the correct instance to get its details).
Configure PuTTY
- Search for PuTTY on your machine.
- Under Hostname, provide the public IP of your EC2 instance:
public-ip
.
Enable Agent Forwarding
- Go to Connection → SSH → Auth → Tick Allow agent forwarding.
- Click Open.
Connect to Public EC2
- PuTTY will prompt you to enter the username (case-sensitive, usually
ec2-user
).
SSH from Public EC2 to Private EC2
- From the public EC2, SSH into the private EC2 using:
ssh ec2-user@<private-ip>
Verify Login to Private EC2
- After authentication, your terminal should display the username and private IP of the private EC2.
- Test internet connectivity from the private EC2:
curl -I https://google.com
- You should get back the HTTP headers information.
Understanding the Test
-
curl -I https://google.com
is the correct way to test if your NAT Gateway works.- If you get headers back → outbound + return path are working.
-
curl
→ command-line tool for making network requests (HTTP, HTTPS, FTP, etc.). -
-I
(capital i) → fetches only the HTTP headers, not the full page body (faster, good for testing connectivity). -
https://google.com
→ the URL you are requesting.
Breaking the NAT Gateway
To simulate failure:
- In the AWS Console → Search for NAT Gateway → Select the NAT you want to delete → Actions → Delete.
Test again from the private EC2:
curl -I https://google.com
This time, it will fail to return headers, confirming that the NAT Gateway is required for private instances to access the internet.
Conclusion and Cleanup
In this blog, we walked through how to design a VPC with both public and private subnets, set up an Internet Gateway and NAT Gateway, launch EC2 instances, and securely connect to a private EC2 via a public bastion host. We also tested outbound connectivity and simulated NAT Gateway failure.
Important Reminder: Don’t forget to clean up your resources (EC2 instances, NAT Gateway, Elastic IP, and VPC) after testing to avoid unexpected AWS charges. NAT Gateways, in particular, can incur ongoing costs if left running.
Thanks for following along! 🚀
If you found this helpful, share it with others or drop your thoughts/questions in the comments.
Top comments (0)