<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ruth kyalo</title>
    <description>The latest articles on DEV Community by Ruth kyalo (@ruthk).</description>
    <link>https://dev.to/ruthk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1197344%2F559405b6-cb2f-4d8c-9c6f-bbff4fe8f345.png</url>
      <title>DEV Community: Ruth kyalo</title>
      <link>https://dev.to/ruthk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ruthk"/>
    <language>en</language>
    <item>
      <title>Connecting Public and Private EC2 Instances to the Internet on AWS</title>
      <dc:creator>Ruth kyalo</dc:creator>
      <pubDate>Tue, 26 Aug 2025 15:53:58 +0000</pubDate>
      <link>https://dev.to/ruthk/connecting-public-and-private-ec2-instances-to-the-internet-on-aws-2hej</link>
      <guid>https://dev.to/ruthk/connecting-public-and-private-ec2-instances-to-the-internet-on-aws-2hej</guid>
      <description>&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before getting started, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; An &lt;strong&gt;AWS account&lt;/strong&gt; with sufficient permissions (VPC, EC2, NAT Gateway, Internet Gateway).
&lt;/li&gt;
&lt;li&gt; An &lt;strong&gt;SSH client&lt;/strong&gt; (e.g., PuTTY on Windows or terminal on macOS/Linux).
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. VPC Basics for Our Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Virtual Private Cloud (VPC)
&lt;/h3&gt;

&lt;p&gt;A VPC is your isolated network inside AWS. When you create a VPC, you must specify an IPv4 CIDR block. &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-sizing-ipv4" rel="noopener noreferrer"&gt;Allowed block size ranges from /16 (65,536 IPs) to /28 (16 IPs).&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Subnets
&lt;/h2&gt;

&lt;p&gt;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.&lt;br&gt;&lt;br&gt;
In every subnet, AWS reserves 5 IPs that cannot be used, if your subnet is 192.168.2.0/25 (128 IPs: .0–.127):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;192.168.2.0 → Network address (subnet identifier)&lt;/li&gt;
&lt;li&gt;192.168.2.1 → VPC router (always the first usable IP)&lt;/li&gt;
&lt;li&gt;192.168.2.2 → Reserved for Amazon DNS (if DNS is enabled in the VPC)&lt;/li&gt;
&lt;li&gt;192.168.2.3 → Reserved for future use&lt;/li&gt;
&lt;li&gt;192.168.2.127 → Broadcast address (reserved, not usable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That leaves you with usable IPs from 192.168.2.4 to 192.168.2.126 → a total of 123 usable IPs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every subnet must be associated with a route table, which controls how traffic is forwarded.&lt;/strong&gt;To calculate the subnets you are going to use, to can use this online-based &lt;a href="https://www.solarwinds.com/free-tools/advanced-subnet-calculator" rel="noopener noreferrer"&gt;subnet calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Public vs Private Subnets&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Public Subnet&lt;/strong&gt; A subnet whose route table has a route to an Internet Gateway (IGW).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use case: Resources that must be directly reachable from the internet.&lt;/li&gt;
&lt;li&gt;Examples: Bastion hosts, public-facing load balancers, or web servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Private Subnet&lt;/strong&gt; A subnet without a direct route to the IGW. Instead, it may use a NAT Gateway/Instance for outbound-only internet access.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use case: Resources that should not be reachable from the internet, but still need outbound access.&lt;/li&gt;
&lt;li&gt;Examples: Application servers, databases, or internal services.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Route Tables
&lt;/h2&gt;

&lt;p&gt;A route table is a set of rules that determine how network traffic is routed from your subnet.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Destination&lt;/em&gt;→ 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).&lt;br&gt;&lt;br&gt;
&lt;em&gt;Target&lt;/em&gt; → the “next hop” that forwards the traffic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local (VPC internal routing)&lt;/li&gt;
&lt;li&gt;Internet Gateway (IGW) → to the internet&lt;/li&gt;
&lt;li&gt;NAT Gateway → for private subnet outbound internet&lt;/li&gt;
&lt;li&gt;VPC Peering connection → to another VPC&lt;/li&gt;
&lt;li&gt;VPN / Virtual Private Gateway (VGW) or Transit Gateway (TGW) → to on-prem&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Gateways
&lt;/h2&gt;

&lt;p&gt;Gateways connect your VPC to other networks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Internet Gateway (IGW)&lt;/strong&gt; → Allows public subnets to connect to the internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAT Gateway or NAT Instance&lt;/strong&gt; → Allows private subnets to reach the internet outbound only.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;NAT Instance:&lt;/strong&gt; EC2 instance you manage yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAT Gateway:&lt;/strong&gt; 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.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Elastic IP (EIP)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
An Elastic IP is a static, public IPv4 address in AWS.EIPs can be associated with EC2 instances, network interfaces, or AWS resources.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Why it’s important:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static Public Address → Doesn’t change when instances stop/start.&lt;/li&gt;
&lt;li&gt;High Availability → Can be reassigned to another instance in the same region.&lt;/li&gt;
&lt;li&gt;Required for NAT Gateway → NAT needs a stable outbound IP.&lt;/li&gt;
&lt;li&gt;Firewall Whitelisting → External systems can safely whitelist your static&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Security Controls
&lt;/h2&gt;

&lt;p&gt;Security Groups (SGs) → Instance-level firewall.&lt;br&gt;&lt;br&gt;
Network ACLs (NACLs) → Subnet-level firewall.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Step-by-Step Setup
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Create the VPC, Subnets, and Internet Gateway
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. Create a VPC
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Log in to your &lt;strong&gt;AWS Management Console&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Select a &lt;strong&gt;Region&lt;/strong&gt; (e.g., &lt;code&gt;us-east-1&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;In the search bar at the top, type &lt;strong&gt;VPC&lt;/strong&gt; and open the service.
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create VPC&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;VPC only&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Enter a name (e.g., &lt;code&gt;MyDemoVPC&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;IPv4 CIDR block&lt;/strong&gt; to &lt;code&gt;192.168.0.0/20&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Leave other options as default and click &lt;strong&gt;Create VPC&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  2. Create Subnets
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;On your VPC dashboard select &lt;strong&gt;Subnets&lt;/strong&gt; on the left menu and choose &lt;strong&gt;Create subnet&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Choose the VPC you just created.
&lt;/li&gt;
&lt;li&gt;Provide subnet name: &lt;strong&gt;public-subnet&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select an &lt;strong&gt;Availability Zone&lt;/strong&gt; (e.g., &lt;code&gt;us-east-1a&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;IPv4 subnet CIDR block → &lt;code&gt;192.168.2.0/25&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;Add new subnet&lt;/strong&gt; to add the private subnet:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;strong&gt;private-subnet&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IPv4 subnet CIDR block → &lt;code&gt;192.168.2.128/25&lt;/code&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Create subnet&lt;/strong&gt;.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to the &lt;strong&gt;public subnet&lt;/strong&gt;, select it → Actions → &lt;strong&gt;Edit subnet &lt;br&gt;
settings&lt;/strong&gt;.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtbgjzk19fg0tcrcdczf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtbgjzk19fg0tcrcdczf.png" alt="Editing subnet settings" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;strong&gt;Auto-assign public IP&lt;/strong&gt; and save.
&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  3. Create and Attach an Internet Gateway (IGW)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In the VPC dashboard, go to &lt;strong&gt;Internet Gateways → Create internet gateway&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Enter a name (e.g., &lt;code&gt;MyDemoIGW&lt;/code&gt;) and click &lt;strong&gt;Create&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Select the newly created IGW (it will show as &lt;em&gt;detached&lt;/em&gt;) → &lt;strong&gt;Actions → Attach to VPC&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Choose your VPC (&lt;code&gt;MyDemoVPC&lt;/code&gt;) and confirm.
&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  4. Update Route Table for the Public Subnet
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In the VPC dashboard, go to &lt;strong&gt;Route Tables&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Find the route table associated with your VPC (not the default route table).
&lt;/li&gt;
&lt;li&gt;Rename it (e.g., &lt;code&gt;main-RT&lt;/code&gt;) and save.
&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Subnet Associations&lt;/strong&gt; tab, confirm subnets explicitly associated.
&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Routes&lt;/strong&gt; tab, click &lt;strong&gt;Edit routes&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6m19anzwz6msbguo5w0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6m19anzwz6msbguo5w0.png" alt="Editing routes" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and add:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Destination:&lt;/strong&gt; &lt;code&gt;0.0.0.0/0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target:&lt;/strong&gt; Internet Gateway (&lt;code&gt;MyDemoIGW&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save changes.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Subnet associations → Edit subnet associations → Select your public subnet → Save&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fep4o6r1qxwpno90ixymu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fep4o6r1qxwpno90ixymu.png" alt="Subnet Association" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  Step 2: Create a NAT Gateway for the Private Subnet
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;NAT Gateways&lt;/strong&gt; in the VPC dashboard → &lt;strong&gt;Create NAT Gateway&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Name it: &lt;code&gt;MyDemoNATGateway&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Place it in the &lt;strong&gt;public subnet&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Connectivity type → &lt;strong&gt;Public&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Allocate and attach an &lt;strong&gt;Elastic IP&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create NAT Gateway&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  Step 3: Update Route Table for the Private Subnet
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Route Tables → Create route table&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Name it &lt;code&gt;private-RT&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Select your VPC and create.
&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Subnet Associations → Edit subnet associations → Select private subnet → Save&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Routes → Edit routes → Add route&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Destination:&lt;/strong&gt; &lt;code&gt;0.0.0.0/0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target:&lt;/strong&gt; NAT Gateway (&lt;code&gt;MyDemoNATGateway&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Save changes.
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Step 4: Create a Key Pair
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;EC2 Dashboard → Key Pairs → Create key pair&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;mydemokey&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Private key format: &lt;code&gt;.ppk&lt;/code&gt; (for PuTTY). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9ugyfjpkzgn89xkmqrb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9ugyfjpkzgn89xkmqrb.png" alt="key creation" width="800" height="300"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create key pair (private key will be downloaded automatically).
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Step 5: Launch EC2 Instances
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Public EC2
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;EC2 Dashboard → Instances → Launch instance&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;public-ec2&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Instance type: &lt;code&gt;t2.micro&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Select your &lt;strong&gt;key pair&lt;/strong&gt; (&lt;code&gt;mydemokey&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Network settings:

&lt;ul&gt;
&lt;li&gt;VPC: &lt;code&gt;MyDemoVPC&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Subnet: &lt;strong&gt;public-subnet&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enable auto-assign public IP. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Firewall (security group): 
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmh74vxnb72tl1yeovlq.png" alt="Security Groups" width="800" height="300"&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;public-sg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Inbound rule: &lt;strong&gt;SSH&lt;/strong&gt; (source type: My IP).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Leave other options as default&lt;/li&gt;
&lt;li&gt;Launch instance. &lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Private EC2
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Repeat the steps above.
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;private-ec2&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Subnet: &lt;strong&gt;private-subnet&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Disable auto-assign public IP.
&lt;/li&gt;
&lt;li&gt;Firewall (security group):

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;private-sg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Inbound rule: &lt;strong&gt;SSH&lt;/strong&gt; (source Type: custom, source: &lt;code&gt;public-sg&lt;/code&gt;).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Launch instance.
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  SSH into Private EC2 via Public EC2
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start Pageant&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search &lt;strong&gt;Pageant&lt;/strong&gt; on your machine and open it. Once it’s opened, you’ll see it in the taskbar.
&lt;/li&gt;
&lt;li&gt;Right-click on it → &lt;strong&gt;Add Key&lt;/strong&gt; → Select your private key.
&lt;/li&gt;
&lt;li&gt;Save the session so you don’t have to redo this step.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Get EC2 Connection Details&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the &lt;strong&gt;AWS EC2 Dashboard&lt;/strong&gt; → Select your &lt;strong&gt;public instance&lt;/strong&gt; → Click &lt;strong&gt;Connect&lt;/strong&gt; → Choose &lt;strong&gt;SSH Client&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;You will see the &lt;strong&gt;username&lt;/strong&gt; of the EC2 instance and its &lt;strong&gt;public IP&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Note both, since you will need them in the next step.
&lt;/li&gt;
&lt;li&gt;Repeat the same process for your &lt;strong&gt;private instance&lt;/strong&gt; (make sure you select the correct instance to get its details).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55y5gbwsd0nbx9xctaod.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55y5gbwsd0nbx9xctaod.png" alt="instance username and Ip address" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure PuTTY&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for &lt;strong&gt;PuTTY&lt;/strong&gt; on your machine.
&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Hostname&lt;/strong&gt;, provide the public IP of your EC2 instance: &lt;code&gt;public-ip&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlbivaixauczw5pq1dwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlbivaixauczw5pq1dwb.png" alt="configuring putty" width="468" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable Agent Forwarding&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Connection → SSH → Auth → Tick Allow agent forwarding&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Open&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fps83hfu68b6zwex26ie6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fps83hfu68b6zwex26ie6.png" alt="Enable Agent Forwarding" width="436" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect to Public EC2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PuTTY will prompt you to enter the &lt;strong&gt;username&lt;/strong&gt; (case-sensitive, usually &lt;code&gt;ec2-user&lt;/code&gt;).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmyyzktp69f4tx662tue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmyyzktp69f4tx662tue.png" alt="providing username" width="643" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSH from Public EC2 to Private EC2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From the &lt;strong&gt;public EC2&lt;/strong&gt;, SSH into the &lt;strong&gt;private EC2&lt;/strong&gt; using:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ssh ec2-user@&amp;lt;private-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Verify Login to Private EC2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After authentication, your terminal should display the username and private IP of the private EC2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdphqnp60772799cwmsd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdphqnp60772799cwmsd.png" alt="testing internet connection from private instance" width="647" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test internet connectivity from the &lt;strong&gt;private EC2&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://google.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;You should get back the &lt;strong&gt;HTTP headers information&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5j8i6n96qo2himjugtqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5j8i6n96qo2himjugtqe.png" alt="Http headers" width="653" height="414"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Understanding the Test
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;curl -I https://google.com&lt;/code&gt; is the correct way to test if your &lt;strong&gt;NAT Gateway&lt;/strong&gt; works.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; If you get headers back → outbound + return path are working.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;curl&lt;/code&gt; → command-line tool for making network requests (HTTP, HTTPS, FTP, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-I&lt;/code&gt; (capital i) → fetches only the HTTP headers, not the full page body (faster, good for testing connectivity).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;https://google.com&lt;/code&gt; → the URL you are requesting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Breaking the NAT Gateway
&lt;/h3&gt;

&lt;p&gt;To simulate failure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the &lt;strong&gt;AWS Console → Search for NAT Gateway → Select the NAT you want to delete → Actions → Delete&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Test again from the private EC2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://google.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, it will &lt;strong&gt;fail to return headers&lt;/strong&gt;, confirming that the NAT Gateway is required for private instances to access the internet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion and Cleanup
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Reminder:&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;Thanks for following along! 🚀&lt;br&gt;&lt;br&gt;
If you found this helpful, share it with others or drop your thoughts/questions in the comments.  &lt;/p&gt;

</description>
      <category>vpc</category>
      <category>aws</category>
      <category>networking</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
