AWS VPC and EC2 Hands-on Lab: Building a Secure Network


In the world of cloud computing, Amazon Web Services (AWS) offers unparalleled flexibility and power. At the heart of building a robust and secure infrastructure on AWS lie two fundamental services: Amazon Virtual Private Cloud (VPC) ๐ and Amazon Elastic Compute Cloud (EC2) ๐ป.
Understanding the Core Components ๐งฉ
Before diving into the practical steps, let's briefly understand what VPC and EC2 are and why they're crucial:
1. Amazon Virtual Private Cloud (VPC) ๐ก๏ธ
Imagine having your own private data center, but in the cloud. That's essentially what a VPC provides. It's a logically isolated section of the AWS cloud where you can launch AWS resources into a virtual network that you define. You get complete control over:
IP Address Ranges (CIDR Blocks): You specify the private IP address space for your VPC. ๐ข
Subnets: You divide your VPC into smaller segments called subnets. These can be:
Public Subnets: For resources that need direct internet access (e.g., web servers, bastion hosts). ๐
Private Subnets: For resources that should not be directly accessible from the internet (e.g., databases, application servers). ๐
Route Tables: These act like traffic cops, defining rules for how network traffic flows within your VPC and to/from the internet. ๐ฆ
Internet Gateway (IGW): A horizontally scaled, redundant, and highly available VPC component that allows communication between instances in your VPC and the internet. ๐ก
NAT Gateway (Network Address Translation Gateway): Enables instances in a private subnet to initiate outbound connections to the internet (e.g., for software updates) while preventing inbound connections from the internet. It resides in a public subnet. ๐ค
Security Groups: Instance-level virtual firewalls that control inbound and outbound traffic for your EC2 instances. ๐ฅ
Network Access Control Lists (NACLs): Subnet-level stateless firewalls that provide an additional layer of security. ๐
2. Amazon Elastic Compute Cloud (EC2) โ๏ธ
EC2 provides resizable compute capacity in the cloud in the form of virtual servers, known as instances. You can launch instances with various operating systems (like Amazon Linux, Ubuntu, Windows) and configure them to run your applications. EC2 instances are always launched within a VPC. ๐ฅ๏ธ
Our Hands-on Journey: Building a Secure Web Environment ๐ ๏ธ
Our lab focused on setting up a common and secure architecture: a public-facing web server and a private internal web server, with access to the private server secured via a bastion host.
Step 1: Laying the Network Foundation (VPC and Subnets) ๐๏ธ
We started by creating a custom VPC named MyCustomVPC
with an IP range of 10.0.0.0/16
. This large block was then segmented into:
MyPublicSubnet
(10.0.1.0/24
): Where public-facing resources reside. ๐MyPrivateSubnet
(10.0.2.0/24
): For internal, protected resources. ๐คซ
Both subnets were placed in the same Availability Zone for simplicity in this demo.
Step 2: Enabling Connectivity (Gateways and Route Tables) ๐
Connectivity is key!
An Internet Gateway (
MyVPC-IGW
) was created and attached toMyCustomVPC
. This is the bridge to the internet. ๐A Public Route Table (
MyPublicRT
) was configured to send all internet-bound traffic (0.0.0.0/0
) fromMyPublicSubnet
toMyVPC-IGW
. โก๏ธA NAT Gateway (
MyVPC-NATGateway
) was provisioned withinMyPublicSubnet
and assigned an Elastic IP. This allows our private instances to get out to the internet for updates without being directly exposed. ๐ชA Private Route Table (
MyPrivateRT
) was set up to direct all internet-bound traffic fromMyPrivateSubnet
throughMyVPC-NATGateway
. โฉ๏ธ
Step 3: Securing Your Servers (Security Groups and Key Pair) ๐๐
Security is paramount in the cloud. We defined two Security Groups:
WebServerSG
: Allowed inbound HTTP (port 80) and HTTPS (port 443) traffic from anywhere (0.0.0.0/0
), and SSH (port 22) from within our VPC's CIDR block (10.0.0.0/16
). This was attached to both our public and private web servers. ๐๐ก๏ธBastionHostSG
: A more restrictive group, allowing inbound SSH (port 22) only from our specific local public IP address. This was attached to our public instance. ๐ปโก๏ธ๐
A MyVPCKeyPair.pem
was generated to securely SSH into our instances. ๐
Step 4: Launching Your Virtual Servers (EC2 Instances) ๐
With the network and security in place, we launched our EC2 instances:
PublicWebServer-Bastion
: Launched inMyPublicSubnet
with "Auto-assign public IP" enabled (later replaced with a static Elastic IP for persistence). This instance serves as our public web server and our secure jump box (bastion host). User data scripts installed Apache and a simple "Hello from Public Web Server!" page. ๐๐PrivateWebServer
: Launched inMyPrivateSubnet
with "Auto-assign public IP" disabled. This instance hosts our private web server, accessible only from within our VPC. User data scripts also installed Apache and a "Hello from Private Web Server!" page. ๐คซ๐ป
An Elastic IP was then allocated and associated with PublicWebServer-Bastion
to ensure its public IP address remained constant, even after stopping and starting the instance. ๐
Step 5: Accessing Your Cloud Resources ๐ช
Finally, we demonstrated access:
Public Web Server Access: By navigating to the Elastic IP of
PublicWebServer-Bastion
in a web browser, we could see its "Hello" page, confirming public internet accessibility. โBastion Host SSH Access: We securely SSH'd into
PublicWebServer-Bastion
from our local machine using our private key and the instance's Elastic IP, leveraging theBastionHostSG
rules. ๐โก๏ธ๐ปPrivate Web Server Access (via Bastion Host): The crucial step for security. We used SSH tunneling (or connected from the bastion host itself) to reach
PrivateWebServer
using its private IP address. Acurl
command from the bastion host to the private web server's private IP successfully retrieved its "Hello" page. This proved that the private instance was isolated from the internet but reachable from authorized internal resources. ๐ต๏ธโโ๏ธโก๏ธ๐คซ
Prerequisites
An active AWS account.
Basic understanding of networking concepts (IP addresses, subnets, routing).
A terminal or SSH client on your local machine.
Part 1: Create the VPC and Subnets
First, we'll create our custom VPC and divide it into a public and a private subnet.
Step 1.1: Create Your Custom VPC
Log in to the AWS Management Console.
Navigate to the VPC service (you can search for "VPC" in the search bar).
In the left navigation pane, click on Your VPCs.
Click the Create VPC button.
Choose VPC only.
Configure the VPC:
Name tag:
MyCustomVPC
IPv4 CIDR block:
10.0.0.0/16
(This gives you 65,536 private IP addresses for your VPC).IPv6 CIDR block: No IPv6 CIDR block.
Tenancy: Default
Click Create VPC.
Step 1.2: Create a Public Subnet
This subnet will host resources that need direct internet access, like your web server or a bastion host.
In the left navigation pane, click on Subnets.
Click the Create subnet button.
Configure the public subnet:
VPC ID: Select
MyCustomVPC
(the VPC you just created).Subnet name:
MyPublicSubnet
Availability Zone: Choose any Availability Zone (e.g.,
us-east-1a
). It's good practice to spread resources across AZs for high availability, but for this demo, one is sufficient.IPv4 CIDR block:
10.0.1.0/24
(This allocates 256 IPs within your VPC for this subnet).
Click Create subnet.
Step 1.3: Create a Private Subnet
This subnet will host resources that should not have direct internet access, such as databases or internal application servers.
Click the Create subnet button again.
Configure the private subnet:
VPC ID: Select
MyCustomVPC
.Subnet name:
MyPrivateSubnet
Availability Zone: Choose the same Availability Zone as your public subnet for simplicity in this demo (e.g.,
us-east-1a
).IPv4 CIDR block:
10.0.2.0/24
(Another 256 IPs for this subnet).
Click Create subnet.
Part 2: Configure Network Components
Now, we'll set up the components that enable internet connectivity for our public subnet and outbound internet access for our private subnet.
Step 2.1: Create an Internet Gateway (IGW)
The Internet Gateway allows communication between your VPC and the internet.
In the left navigation pane, click on Internet gateways.
Click the Create internet gateway button.
Name tag:
MyVPC-IGW
Click Create internet gateway.
Once created, select
MyVPC-IGW
and click Actions > Attach to VPC.Select
MyCustomVPC
from the dropdown and click Attach internet gateway.
Step 2.2: Create a Public Route Table
This route table will direct internet-bound traffic from MyPublicSubnet
to the Internet Gateway.
In the left navigation pane, click on Route tables.
Click the Create route table button.
Configure the public route table:
Name tag:
MyPublicRT
VPC: Select
MyCustomVPC
.
Click Create route table.
Select
MyPublicRT
.Click on the Routes tab, then click Edit routes.
Click Add route.
Destination:
0.0.0.0/0
(This means "all internet traffic").Target: Select Internet Gateway and then choose
MyVPC-IGW
.
Click Save changes.
Now, associate this route table with your public subnet. Click on the Subnet associations tab, then click Edit subnet associations.
Select the checkbox next to
MyPublicSubnet
.Click Save associations.
Step 2.3: Create a NAT Gateway
A NAT Gateway allows instances in your private subnet to initiate outbound connections to the internet (e.g., for software updates) without being directly accessible from the internet.
In the left navigation pane, click on NAT gateways.
Click the Create NAT gateway button.
Configure the NAT Gateway:
Name tag:
MyVPC-NATGateway
Subnet: Select
MyPublicSubnet
(the NAT Gateway must reside in a public subnet).Connectivity type: Public
Elastic IP allocation ID: Click Allocate Elastic IP to create a new Elastic IP address for the NAT Gateway.
Click Create NAT gateway.
- Note: It takes a few minutes for the NAT Gateway to become available. Wait for its status to change from "Pending" to "Available".
Step 2.4: Create a Private Route Table
This route table will direct internet-bound traffic from MyPrivateSubnet
through the NAT Gateway.
In the left navigation pane, click on Route tables.
Click the Create route table button.
Configure the private route table:
Name tag:
MyPrivateRT
VPC: Select
MyCustomVPC
.
Click Create route table.
Select
MyPrivateRT
.Click on the Routes tab, then click Edit routes.
Click Add route.
Destination:
0.0.0.0/0
Target: Select NAT Gateway and then choose
MyVPC-NATGateway
.
Click Save changes.
Associate this route table with your private subnet. Click on the Subnet associations tab, then click Edit subnet associations.
Select the checkbox next to
MyPrivateSubnet
.Click Save associations.
Part 3: Launch EC2 Instances
Now we'll launch our EC2 instances: one in the public subnet (which will act as our bastion host and public web server) and one in the private subnet (our private web server).
Step 3.1: Create Security Groups
Security Groups act as virtual firewalls for your instances.
Navigate to the EC2 service.
In the left navigation pane, under Network & Security, click on Security Groups.
Click Create security group.
Security Group 1: Web Server SG
Security group name:
WebServerSG
Description: Allow HTTP/HTTPS traffic
VPC: Select
MyCustomVPC
.Inbound rules:
Click Add rule.
- Type: HTTP, Source:
0.0.0.0/0
(Allow HTTP from anywhere)
- Type: HTTP, Source:
Click Add rule.
- Type: HTTPS, Source:
0.0.0.0/0
(Allow HTTPS from anywhere)
- Type: HTTPS, Source:
Click Add rule.
- Type: SSH, Source:
10.0.0.0/16
(Allow SSH from within your VPC for internal communication)
- Type: SSH, Source:
Outbound rules: All traffic (default)
Click Create security group.
Security Group 2: Bastion Host SG
Security group name:
BastionHostSG
Description: Allow SSH from your IP only
VPC: Select
MyCustomVPC
.Inbound rules:
Click Add rule.
- Type: SSH, Source:
My IP
(This automatically detects your public IP address. If it doesn't, you can find your public IP by searching "what is my ip" on Google and entering it manually with/32
at the end, e.g.,X.X.X.X/32
).
- Type: SSH, Source:
Outbound rules: All traffic (default)
Click Create security group.
Step 3.2: Create a Key Pair
You'll need a key pair to SSH into your EC2 instances.
In the EC2 dashboard, under Network & Security, click on Key Pairs.
Click Create key pair.
Key pair name:
MyVPCKeyPair
Key pair type: RSA
Private key file format:
.pem
(for OpenSSH)Click Create key pair.
Important: Your private key file (
MyVPCKeyPair.pem
) will be downloaded automatically. Keep it secure and do not share it. You'll need it to connect to your instances.
Step 3.3: Launch Public EC2 Instance (Bastion Host & Public Web Server)
This instance will be in your public subnet and will have a public IP address. It will serve as both your public web server and a "bastion host" to access your private instance.
In the EC2 dashboard, click on Instances in the left navigation pane.
Click Launch instances.
Name:
PublicWebServer-Bastion
Application and OS Images (Amazon Machine Image - AMI): Select
Amazon Linux 2023 AMI
(or Amazon Linux 2 AMI).Instance type:
t2.micro
(Free tier eligible).Key pair (login): Choose
MyVPCKeyPair
.Network settings:
Click Edit.
VPC: Select
MyCustomVPC
.Subnet: Select
MyPublicSubnet
.Auto-assign public IP: Enable (This is crucial for public access).
Firewall (security groups): Select Select existing security group(s).
Choose
BastionHostSG
(for SSH access from your IP)Choose
WebServerSG
(for HTTP/HTTPS access)
Configure storage: Leave as default (8 GiB gp2).
Advanced details (User data): This script will install Apache and start a simple web server when the instance launches.
```plaintext #!/bin/bash sudo yum update -y sudo yum install -y httpd sudo systemctl start httpd sudo systemctl enable httpd echo "
Hello from Public Web Server in MyCustomVPC!
" | sudo tee /var/www/html/index.html
10. Click **Launch instance**.
### Step 3.4: Launch Private EC2 Instance (Private Web Server)
This instance will be in your private subnet and will *not* have a public IP address.
1. In the EC2 dashboard, click **Launch instances** again.
2. **Name:** `PrivateWebServer`
3. **Application and OS Images (Amazon Machine Image - AMI):** Select `Amazon Linux 2023 AMI` (or Amazon Linux 2 AMI).
4. **Instance type:** `t2.micro` (Free tier eligible).
5. **Key pair (login):** Choose `MyVPCKeyPair`.
6. **Network settings:**
* Click **Edit**.
* **VPC:** Select `MyCustomVPC`.
* **Subnet:** Select `MyPrivateSubnet`.
* **Auto-assign public IP:** **Disable** (Crucial for a private instance).
* **Firewall (security groups):** Select **Select existing security group(s)**.
* Choose `WebServerSG` (to allow internal HTTP/HTTPS traffic from other instances in the VPC).
7. **Configure storage:** Leave as default.
8. **Advanced details (User data):** This script will install Apache and start a simple web server.
```plaintext
#!/bin/bash
sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
echo "<h1>Hello from Private Web Server in MyCustomVPC!</h1>" | sudo tee /var/www/html/index.html
- Click Launch instance.
Step 3.5: Allocate and Associate an Elastic IP (Optional but Recommended for Public EC2)
An Elastic IP (EIP) is a static public IP address that you can associate with your EC2 instance. Unlike a regular public IP, an EIP doesn't change when you stop and start your instance, making it ideal for public-facing servers.
In the EC2 dashboard, under Network & Security, click on Elastic IPs.
Click Allocate Elastic IP address.
Click Allocate.
Select the newly allocated Elastic IP.
Click Actions > Associate Elastic IP address.
Resource type: Instance
Instance: Select
PublicWebServer-Bastion
.Private IP address: Select the private IP address of your
PublicWebServer-Bastion
instance (it should be pre-selected).Click Associate.
Part 4: Accessing EC2 Instances
Now that everything is set up, let's test access to our instances.
Step 4.1: Access the Public Web Server
In the EC2 dashboard, go to Instances.
Select
PublicWebServer-Bastion
.Copy its Elastic IP address (or Public IPv4 address if you skipped the EIP step).
Paste this IP address into your web browser. You should see:
Hello from Public Web Server in MyCustomVPC!
Step 4.2: Access the Public EC2 Instance (Bastion Host) via SSH
Open your terminal or SSH client on your local machine.
Navigate to the directory where you saved
MyVPCKeyPair.pem
.Change the permissions of your private key file:
```plaintext chmod 400 MyVPCKeyPair.pem
4. Connect to your `PublicWebServer-Bastion` instance using its Elastic IP:
```plaintext
ssh -i MyVPCKeyPair.pem ec2-user@<Public_EC2_Elastic_IP>
Replace
<Public_EC2_Elastic_IP>
with the actual Elastic IP of yourPublicWebServer-Bastion
instance.Type
yes
if prompted to confirm the host's authenticity.You should now be logged into your public EC2 instance. This instance is now acting as your bastion host.
Step 4.3: Access the Private EC2 Instance via the Bastion Host (SSH Tunneling)
You cannot directly SSH into your private EC2 instance from the internet because it has no public IP. You must first connect to your bastion host, and then from the bastion host, connect to your private instance.
From your local machine, you can use SSH Agent Forwarding or a single SSH command to tunnel through the bastion. Let's use a single command for simplicity:
```plaintext ssh -i MyVPCKeyPair.pem -o ProxyCommand="ssh -W %h:%p -i MyVPCKeyPair.pem ec2-user@" ec2-user@
* Replace `<Public_EC2_Elastic_IP>` with the Elastic IP of your `PublicWebServer-Bastion` instance.
* Replace `<Private_EC2_Private_IP>` with the **private IP address** of your `PrivateWebServer` instance. You can find this in the EC2 console under the instance details.
* **Explanation of the command:**
* `ssh -i MyVPCKeyPair.pem`: Uses your local key to authenticate.
* `-o ProxyCommand="ssh -W %h:%p -i MyVPCKeyPair.pem ec2-user@<Public_EC2_Elastic_IP>"`: This is the magic part. It tells your local SSH client to first establish an SSH connection to the bastion host (`ec2-user@<Public_EC2_Elastic_IP>`) using your key. Then, it forwards the traffic (`-W %h:%p`) from your local machine through this established connection to the target private IP (`%h`) and port (`%p`).
* `ec2-user@<Private_EC2_Private_IP>`: This is the final target for your SSH connection, the private EC2 instance.
2. You should now be logged into your `PrivateWebServer` instance. This demonstrates that you can securely access private resources within your VPC using a bastion host.
### Step 4.4: Access the Private Web Server (from Bastion Host)
While connected to your `PublicWebServer-Bastion` instance via SSH, you can now access the web server running on your `PrivateWebServer` instance.
1. From the SSH session on your `PublicWebServer-Bastion` (your bastion host), use `curl` to access the private web server:
```plaintext
curl http://<Private_EC2_Private_IP>
- Replace
<Private_EC2_Private_IP>
with the actual private IP address of yourPrivateWebServer
instance.
- You should see the output:
<h1>Hello from Private Web Server in MyCustomVPC!</h1>
This confirms that:
Your private EC2 instance is running a web server.
The
WebServerSG
on the private instance is allowing HTTP traffic from the bastion host (which is within the10.0.0.0/16
CIDR block allowed byWebServerSG
's SSH rule, and HTTP is explicitly allowed from anywhere, which includes internal VPC traffic).The private subnet's route table is correctly configured to allow internal communication.
Cleanup (Important!)
To avoid incurring charges, remember to terminate your EC2 instances, release your Elastic IP, and delete your NAT Gateway, Internet Gateway, route tables, security groups, subnets, and VPC.
Terminate EC2 Instances:
Go to EC2 > Instances.
Select both
PublicWebServer-Bastion
andPrivateWebServer
.Click Instance state > Terminate instance.
Release Elastic IP:
Go to EC2 > Elastic IPs.
Select the Elastic IP you allocated.
Click Actions > Release Elastic IP addresses.
Delete NAT Gateway:
Go to VPC > NAT gateways.
Select
MyVPC-NATGateway
.Click Actions > Delete NAT gateway. (Wait for it to be deleted).
Delete Internet Gateway:
Go to VPC > Internet gateways.
Select
MyVPC-IGW
.Click Actions > Detach from VPC.
Once detached, click Actions > Delete internet gateway.
Delete Route Tables:
Go to VPC > Route tables.
Select
MyPublicRT
andMyPrivateRT
.Click Actions > Delete route table. (You cannot delete the default route table).
Delete Security Groups:
Go to EC2 > Security Groups.
Select
WebServerSG
andBastionHostSG
.Click Actions > Delete security groups.
Delete Subnets:
Go to VPC > Subnets.
Select
MyPublicSubnet
andMyPrivateSubnet
.Click Actions > Delete subnet.
Delete VPC:
Go to VPC > Your VPCs.
Select
MyCustomVPC
.Click Actions > Delete VPC.
Subscribe to my newsletter
Read articles from Poonam Vetal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Poonam Vetal
Poonam Vetal
I am student from Pune institute of computer technology !๐