Set up Jumphost/Bastion to access private subnets from Internet
Published on August 04, 2023 by Dai Tran
aws ec2 jumphost bastion blog intra-vpc routing
6 min READ
Create the VPC with the following settings:
DNS hostnames
: Enabled
DNS resolution
: Enabled
Main network ACL
: VPC-NACL
IPv4 CIDR
: 172.16.0.0/16
This NACL is the main NACL of the VPC and thus control all the inbound and outbound traffic to and from VPC subnets.
Type | Protocol | Port range | Source | Allow/Deny | Comment |
---|---|---|---|---|---|
HTTP | TCP(6) | 80 | 0.0.0.0/0 | Allow | To test static webpage on jumphosts |
HTTPS | TCP(6) | 443 | 0.0.0.0/0 | Allow | To test static webpage on jumphosts |
SSH | TCP(6) | 22 | 0.0.0.0/0 | Allow | To access jumphosts and EC2 instances in private subnets |
Custom TCP | TCP(6) | 1024 - 65535 | 0.0.0.0/0 | Allow | To allow returning traffic of outbound traffic from EC2 instances like sudo yum update -y |
Type | Protocol | Port range | Source | Allow/Deny | Comment |
---|---|---|---|---|---|
All traffic | All | All | 0.0.0.0/0 | Allow | Allow outbound |
Create two public subnets Public Subnet 1
and Public Subnet 2
Create two private subnets Private Subnet 1
and Private Subnet 2
Create Public RT
for the two public subnets with two routes:
0.0.0.0/0
via target Internet Gateway172.16.0.0/16
via target localPrivate RTs
one for each private subnet is created by default
Create security group sg-alb
for restricting inbound web traffic with the following rules:
Inbound
Type | Protocol | Port range | Source | Allow/Deny | Comment |
---|---|---|---|---|---|
HTTP | TCP | 80 | 0.0.0.0/0 | Allow | Allow HTTP requests to ALB |
SSH | TCP | 443 | 0.0.0.0/0 | Allow | Allow HTTPs from jumphosts |
Outbound
Not needed as security groups are stateful.
Create security group sg-ec2
for EC2 instances including the jumphost with the following rules:
Inbound
Type | Protocol | Port range | Source | Allow/Deny | Comment |
---|---|---|---|---|---|
HTTP | TCP | 80 | 0.0.0.0/0 | Allow | Allow access to static webpage on jumphost (deployed when there is no ALB) |
HTTP | TCP | 80 | sg-alb | Allow | Allow access to static webpage from ALB |
SSH | TCP | 22 | 0.0.0.0/0 | Allow | Allow SSH to jumphosts |
Outbound
Type | Protocol | Port range | Source | Allow/Deny | Comment |
---|---|---|---|---|---|
All traffic | All | All | 0.0.0.0/0 | Allow | Allow access Internet |
This machine is deployed as follows:
sg-ec2
to itConnect to Bastion using EC2 Instance Connect
or SSH client
as follows:
1. Open an SSH client
2. Locate your private key file. The key used to launch this instance is <key_pair_name>.pem
3. Run this command, if necessary, to ensure your key is not publicly viewable.
chmod 400 <key_pair_name>.pem
4. Connect to your instance using its Public DNS or IP address:
ssh -i "<key_pair_name>.pem" ec2-user@<Public IP>
5. Once the SSH session is established, open <key_pair_name>.pem on the SSH client machine, copy and paste its content to .ssh/<key_pair_name>.pem on the Bastion
These machines are deployed as follows:
sg-ec2
to itUser data
of the Advanced details
section to turn these instances into the static webservers:#!/bin/bash
sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
sudo chown -R $USER:$USER /var/wwww
echo "<h1>Hello World from $(hostname -f)</h1>" > /var/www/html/index.html
After that confirm that these instances are accessible via SSH from the Bastion. The static webpages are also accessible using the public IPs of the instances (or ALB FQDN if it’s deployed).
By default, each VPC comes with 1 route table pre-configured with a “local” route. The scope of the “local” route is only within the subnet defined for the entire VPC. For example, if your VPC was set up to have the address space of 172.16.0.0/16, your “local” route would be defined as “172.16.0.0/16”. This allows all of the resources created within the VPC to talk to each other without any additional configuration. You cannot delete the “local” route from your route table, and anytime a new route table is created within a VPC, the “local” route is included by default.
Within a VPC, route tables are assigned to individual subnets. With only 1 route table created in a VPC, all of the subnets would be assigned to that route table. You can create multiple route tables in a VPC, or you can leave the 1 default route table.
For environments that are broken apart into public and private subnets, it is best practice to have 1 route table for public subnets, and 1 route table for private subnets. In this scenario, you will need to further separate your route tables into availability zones, as well. The reason for this is: you will want systems in AZ A to use a NAT gateway and any other systems which are also within that AZ; same for systems in AZ B. This ensures that if one availability zone becomes unavailable, the systems in the other availability zone are not relying on a system that is now non-functional. The diagram below shows this configuration.