EC2 Instances in Public and Private Subnets
Topics: EC2, VPC, Networking, Bastion Host, Jump Server, RDP, Security Groups, NAT Gateway
Overview
This lab demonstrates deploying EC2 instances in a secure two-tier network architecture. You'll launch a Windows web server in a public subnet (accessible from the internet) and a Windows database server in a private subnet (isolated from direct internet access). This architecture pattern is fundamental for production environments where frontend servers need public accessibility while backend databases must remain fully isolated.
You'll configure security groups to control network access, use the public instance as a bastion host (jump server) to access the private instance, and verify that NAT Gateway enables private instances to access the internet for updates while blocking all inbound connections.
Key Concepts
| Concept | Description |
|---|---|
| Bastion Host (Jump Server) | EC2 instance in public subnet used as secure gateway to access private subnet instances; only entry point to private resources |
| Public Subnet | Subnet with route to Internet Gateway allowing instances to receive public IPs and accept inbound internet connections |
| Private Subnet | Subnet without public IP assignment or direct internet access; outbound traffic routed through NAT Gateway for security |
| Security Group (Instance-Level) | Stateful virtual firewall controlling inbound/outbound traffic for EC2 instances based on protocol, port, and source |
| Security Group Chaining | Referencing one security group as source in another's rules; enables secure communication between tiers without exposing public IPs |
| Remote Desktop Protocol (RDP) | Microsoft protocol for remote GUI access to Windows instances over TCP port 3389 |
| NAT Gateway Functionality | Enables private subnet instances to initiate outbound internet connections while blocking all inbound initiated traffic |
| Private IP vs Public IP | Private IPs (e.g., 10.0.x.x) for internal VPC communication; public IPs for internet-accessible resources |
| Multi-Hop RDP | Connecting to private instance by first RDP to bastion (public instance), then RDP again from bastion to private instance |
| Network Isolation | Security practice of separating different application tiers (web, app, database) into distinct subnets with controlled routing |
Prerequisites
- Completed Lab 10 (Custom VPC Configuration with public/private subnets, IGW, NAT Gateway)
- Existing VPC with:
- Public subnet with route to Internet Gateway
- Private subnet with route to NAT Gateway
- Both subnets in different Availability Zones
- Windows computer with Remote Desktop Connection (mstsc) client
.pemkey pair file from previous EC2 labs (or create new one)- Basic understanding of Windows Remote Desktop and network security
- IAM permissions for EC2 instance launch and security group management
Architecture Overview
Click to expand Architecture Diagram
Phase 1: Launch Windows Instance in Public Subnet
Sign in to AWS Management Console.
Navigate to EC2 service → Click Launch Instance.
Configure instance details:
- Name:
WebInstance(or descriptive name likePublicWebServer) - Application and OS Images (AMI):
- Select Windows tab
- Choose Microsoft Windows Server 2022 Base
- Ensure "Free tier eligible" is displayed
- Name:
Choose instance type:
- Instance type:
t3.micro
- Instance type:
Configure key pair:
- Key pair (login): Select existing key pair or create new
- Key pair type: RSA
- Download and save the
.pemfile securely
Key Pair Requirement
You need the .pem key pair file to decrypt the Windows Administrator password. Without it, you cannot log in to the instance.
Configure Network Settings:
- Click Edit under Network settings
- VPC: Select
MyWebAppVPC(your custom VPC from Lab 10) - Subnet: Select
PublicSubnet(must be the public subnet) - Auto-assign Public IP: Enable
- Critical for internet accessibility
- If disabled, instance won't be reachable from internet
Configure Security Group for Web Instance:
- Firewall (security groups): Create security group
- Security group name:
WebInstance-SG - Description: "Allow RDP from anywhere for lab purposes"
- Inbound security group rules:
- Rule 1:
- Type: RDP
- Protocol: TCP
- Port: 3389
- Source: 0.0.0.0/0 (Anywhere)
- Description: "RDP access for remote management"
- Rule 1:
Configure Storage, Review configuration in Summary panel.
Click Launch instance.
Wait for instance to be ready:
- Instance state: Running
- Status checks: 2/2 checks passed (takes 3-5 minutes for Windows)
- Note the Public IPv4 address and Private IPv4 address
Windows Boot Time
Windows instances take longer to boot than Linux (3-5 minutes for status checks). The instance must complete initialization and Windows configuration before it's ready for RDP connection.
Phase 2: Launch Windows Instance in Private Subnet
In EC2 console, click Launch Instance again.
- Name:
DBInstance(or descriptive name likePrivateDatabaseServer) - AMI: Microsoft Windows Server 2022 Base or 2019 Base (same as public instance)
- Instance type:
t3.micro
- Name:
Configure key pair:
- Key pair: Select the same key pair used for WebInstance
- Using same key pair simplifies password decryption
- Alternatively, use different key pair if managing separately
- Key pair: Select the same key pair used for WebInstance
Configure Network Settings:
- Click Edit under Network settings
- VPC: Select
MyWebAppVPC(same VPC) - Subnet: Select
PrivateSubnet(must be the private subnet) - Auto-assign Public IP: Disable
No Public IP for Private Instances
Private subnet instances must have disabled "auto-assign public IP". This is a fundamental security practice ensuring databases and backend services are never directly exposed to the internet, preventing unauthorized access attempts.
- Configure Security Group for DB Instance:
- Firewall (security groups): Create security group
- Security group name:
DBInstance-SG - Description: "Allow RDP only from WebInstance security group"
- Inbound security group rules:
- Rule 1:
- Type: RDP
- Protocol: TCP
- Port: 3389
- Source: Custom
- In source field, type
WebInstance-SGand select it from dropdown - Description: "RDP from WebInstance only"
- Rule 1:
Security Group Chaining
By referencing WebInstance-SG as the source instead of an IP address, we create dynamic security. Any instance with WebInstance-SG can connect, even if IP addresses change. This is more maintainable than hardcoding IP addresses and follows AWS best practices.
Configure Storage:
Review configuration:
- Verify subnet is
PrivateSubnet - Verify no public IP assignment
- Verify security group references
WebInstance-SG
- Verify subnet is
Click Launch instance.
Wait for instance to be ready:
- Instance state: Running
- Status checks: 2/2 checks passed
- Note the Private IPv4 address (no public IP shown)
- Instance name shows
DBInstance
Private Instance Isolation
The DBInstance is now fully isolated from direct internet access. It has no public IP and cannot accept connections from the internet. The only way to access it is through the WebInstance (bastion host) on the local VPC network.
Phase 3: Connect to Public Windows Instance
Retrieve Windows Administrator Password
In EC2 console, select
WebInstance.Click Connect button at the top.
Click the RDP client tab.
Retrieve password by Decrypting:
Note the Public IP address displayed on the Connect page.
Connect Using Remote Desktop
On your Windows computer, press
Windows + R.Type
mstscand press Enter (opens Remote Desktop Connection).In the Remote Desktop Connection dialog:
- Computer: Paste the Public IP of
WebInstance(e.g.,54.123.45.67) - Click Connect
- Computer: Paste the Public IP of
Windows Security credential prompt appears:
- Username:
Administrator(default Windows admin account) - Password: Paste the decrypted password you copied earlier
- Username:
Certificate warning appears (common for self-signed certs):
- Warning: "The identity of the remote computer cannot be verified"
- Check "Don't ask me again for connections to this computer"
Remote Desktop session opens, you're now inside the
WebInstance.
First Login
First login may take 30-60 seconds as Windows configures the Administrator profile. Be patient and don't close the connection prematurely.
Phase 4: Connect to Private Windows Instance via Bastion
You cannot connect directly to DBInstance from your laptop because it has no public IP. You must connect from within WebInstance using its private IP address.
Before connecting, you need to decrypt DBInstance password:
Same Key Pair
If you used the same key pair for both instances, the passwords will be different (AWS generates unique passwords per instance). Decrypt and save both passwords separately.
Remote Desktop from WebInstance to DBInstance
While logged into
WebInstance(your RDP session from Phase 3):- Inside the remote Windows desktop, press
Windows + R - Type
mstscand press Enter - This opens Remote Desktop Connection inside WebInstance
- Inside the remote Windows desktop, press
In the Remote Desktop Connection dialog (inside WebInstance):
- Computer: Enter the Private IP address of
DBInstance(e.g.,10.0.2.15)- Find this in EC2 console under
DBInstancedetails - Must be private IP (10.0.x.x), not public (it has none)
- Find this in EC2 console under
- Click Connect
- Computer: Enter the Private IP address of
Credential prompt appears:
- Username:
Administrator - Password: Paste the
DBInstancedecrypted password
- Username:
Certificate warning appears:
- Click Yes to accept
Nested RDP session opens, you're now inside the private Windows instance.
Multi-Hop Connection
You now have two RDP sessions:
- Your laptop →
WebInstance(public IP, over internet) WebInstance→DBInstance(private IP, over VPC network)
This is called "bastion host" or "jump box" pattern. WebInstance acts as the secure gateway to private resources.
Phase 5: Test NAT Gateway Connectivity
From WebInstance (Public Subnet)
While logged into
WebInstance(outer RDP session):- Open a web browser (Microsoft Edge or Internet Explorer)
- Navigate to
https://www.google.comorhttps://www.aws.amazon.com - Website loads successfully
Check internet connectivity icon:
- System tray (bottom-right) shows internet connection icon
- No yellow triangle or "No internet" message
Result: Internet access works through Internet Gateway (direct route).
From DBInstance (Private Subnet)
While logged into
DBInstance(nested RDP session):- Open a web browser
- Navigate to
https://www.google.com - Website loads successfully
Check network status:
- System tray shows internet connection icon
- Status: "Internet Access"
Test that DBInstance is not accessible from the internet.
Result: Internet access works through NAT Gateway (outbound-only route).
NAT Gateway Function
Even though DBInstance has no public IP and cannot accept inbound connections from the internet, it can initiate outbound connections to the internet through the NAT Gateway. This allows it to download Windows updates, access AWS service APIs, or connect to external databases while remaining completely isolated from inbound internet traffic.
Troubleshooting No Internet
If DBInstance cannot access the internet:
- Verify NAT Gateway is in "Available" state (VPC → NAT Gateways)
- Check Private Route Table has route
0.0.0.0/0→ NAT Gateway ID - Verify
PrivateSubnetis associated with Private Route Table - Check security group allows outbound traffic (default: allow all outbound)
- Wait 2-3 minutes for routing changes to propagate
Validation
Verify successful completion:
Instance Launch:
WebInstancerunning inPublicSubnetwith public and private IPs assignedDBInstancerunning inPrivateSubnetwith private IP only (no public IP)- Both instances show 2/2 status checks passed
- Both instances in "Running" state
Security Group Configuration:
WebInstance-SGallows RDP (3389) from 0.0.0.0/0DBInstance-SGallows RDP (3389) fromWebInstance-SGonlyDBInstance-SGdoes NOT allow traffic from 0.0.0.0/0- Both security groups allow all outbound traffic (default)
Network Connectivity:
- RDP to
WebInstancefrom your laptop using public IP: Success - RDP to
DBInstancedirectly from your laptop: Fails (no public IP) - RDP to
DBInstancefromWebInstanceusing private IP: Success WebInstanceinternet access through IGW: SuccessDBInstanceinternet access through NAT Gateway: Success
Security Isolation:
DBInstancecannot accept inbound connections from internet: VerifiedDBInstancecan initiate outbound connections to internet: Verified- Bastion host pattern working: Verified
Cost Considerations
Cost Considerations
EC2 Instances (t2.micro/t3.micro Windows):
- Free Tier: 750 hours/month for first 12 months (Linux and Windows combined)
- Windows instances: Count against same free tier hours as Linux
- After Free Tier: ~$0.0116/hour per instance = ~$8.35/month each (us-east-1)
- 2 instances running: ~$16.70/month
EBS Storage (30 GB per instance, gp3):
- Free Tier: 30 GB total for first 12 months
- 2 instances = 60 GB total: 30 GB covered by free tier, 30 GB charged
- Overage cost: 30 GB × $0.08/GB-month = $2.40/month
NAT Gateway:
- Hourly: ~$0.045/hour = ~$32.40/month
- Data processing: $0.045/GB processed
- Total for lab: If running 1 hour = $0.045 + minimal data charges
Data Transfer:
- RDP sessions: Minimal data usage (<100 MB for 1-hour session)
- Inbound: Free
- Outbound: Covered by 100 GB free tier/month
Total Estimated Cost (1 hour lab):
- 2× Windows instances: 2× $0.0116 = $0.0232
- NAT Gateway: $0.045
- Data transfer: ~$0 (within free tier)
- Total: ~$0.07 for 1-hour lab
- If left running 24/7 for 30 days: ~$51/month
Stop vs Terminate
Stopping instances (Instance state → Stop) halts compute charges but continues EBS storage charges (~$2.40/month for 60 GB). Terminating instances completely removes them and stops all charges. For labs, always terminate when done.
NAT Gateway Charges
NAT Gateway charges continue even if no instances are running. Always delete NAT Gateway after completing labs to avoid $32.40/month charges.
Cleanup
Cleanup
To avoid ongoing charges, delete resources in this order:
1. Terminate EC2 Instances
Navigate to EC2 → Instances.
Select
WebInstance:- Click Instance state → Terminate instance
- Confirm termination (type
terminateif prompted)
Select
DBInstance:- Click Instance state → Terminate instance
- Confirm termination
Wait for instance state to change to "Terminated" (2-3 minutes).
2. Delete Security Groups (Optional)
Navigate to EC2 → Security Groups.
Select
WebInstance-SG:- Click Actions → Delete security groups
- Confirm deletion
Select
DBInstance-SG:- Click Actions → Delete security groups
- If error "has dependent object," wait 2-3 minutes for instance network interfaces to fully detach
- Retry deletion
3. Delete NAT Gateway (If Not Already Done in Lab 10)
Navigate to VPC → NAT Gateways.
Select NAT Gateway → Actions → Delete NAT gateway.
Type
deleteto confirm → Click Delete.Wait for state to change to "Deleted."
4. Release Elastic IP (If NAT Gateway Deleted)
Navigate to VPC → Elastic IPs.
Select Elastic IP (shows "Disassociated" status).
Click Actions → Release Elastic IP addresses.
Click Release.
Verification
- Both instances show "Terminated" state in EC2 console
- Security groups deleted or only default security group remains
- No unexpected charges in Billing dashboard (check after 24 hours)
- NAT Gateway deleted (if applicable)
- Elastic IP released (if applicable)
Result
You have successfully deployed and secured a two-tier EC2 architecture demonstrating real-world cloud security practices. The public Windows web server is accessible from the internet while the private Windows database server remains completely isolated, accessible only through the bastion host.
You configured security group chaining to allow controlled access between tiers, verified that NAT Gateway enables private instances to access the internet for updates while blocking inbound connections, and implemented the bastion host pattern for secure remote management of private resources.
Viva Questions
What is a bastion host, and why is it important for cloud security?
Explain how security group chaining works and why it's better than hardcoding IP addresses.
Why can a private subnet instance access the internet through NAT Gateway but the internet cannot access it?
What would happen if you enabled "Auto-assign Public IP" on the private subnet?
Describe the complete network path when you RDP from your laptop to DBInstance through WebInstance.
