01 - Setting up a Bastion Host

ยท

9 min read

Overview

Disclaimer on operating system

  • I am using a MacOS device.
  • You may need to find equivalent commands/tools should you be using a different OS device.

This article will cover the following areas:

  • AWS VPC and Subnets on a high level
  • Walkthrough the Bastion host setup
  • Verifying that the Bastion host setup is working

Glossary

CIDR - Classless Internet Domain Routing, an IP addressing scheme that uses IP network prefix/CIDR notation, i.e. the IP address ending with a slash followed by a number. Can use the CIDR notation to compute the available number of IP addresses as well.

VPC - Virtual Private Cloud, the virtual network that is defined by you and tied to your AWS account.

Subnet - A sub-division of your VPC. It can be a public subnet (accessible via the Internet) or a private subnet (with limited access, only hosts in the same subnet can talk to each other).


Key points on VPC and Subnets

  • When you first create an AWS account, a default VPC with CIDR range of 172.31.0.0/16 is assigned to you. The default subnets created within the VPC are assigned /20 netblocks within the VPC's CIDR range (a.k.a primary CIDR block).
  • The valid CIDR IP ranges are between /16 to /28.
  • You are able to create up to 4 secondary CIDR blocks (i.e. 4 different subnets) within the VPC's CIDR range.
  • Note that 5 IP addresses in each subnet will be reserved by AWS for the following purposes
    • Routing
    • Domain Name System (DNS)
    • Network Management
  • The public subnet's Route Table would have the Internet Gateway attached to it to allow communication between the Internet and your VPC. Whereas the private subnet would have the destination to the primary CIDR block, and its target would be local i.e. being able to communicate with hosts within the VPC.
  • The default subnets in the default VPCs are public subnets.

AWS_Default_VPC_Subnet.png


Overview of Bastion Host

What is a Bastion host

Bastion host is an instance, typically located in the public subnet to provide access resources inside the private subnet. It is also commonly known as the jump host.

High-level best practices

Some best practices to note:

  • Use SSH agent forwarding in the implementation of Bastion hosts, instead of storing the private key in the Bastion Host
  • The Bastion host should only include what is essential, so packages and installations should be removed if not needed and kept to the minimum.

Setup Walkthrough

Now that we have covered the key points for the VPC and subnets, we will jump straight into the setup of the Bastion host. Below is a diagram to illustrate what we intend to setup

BastionHostSetup.png

AWS Services to Use

Below is the list of AWS services that will be used in this setup

  • Network components: VPC, Subnet, Internet Gateway, and Route Table
  • EC2 components: SSH Key Pair, Security Groups + EC2 (Linux)

Setting up the network

While we will be using the default VPC for this setup, there are still some additional configurations required for the private subnet and its route tables.

Creation of new subnet and route table will not incur additional cost.

1. Create a route table for the private subnet

You will need to first create a route table for the private subnet as the default VPC does not have a route table for it.

To create a route table,

  1. Search for VPC to navigate to the VPC Dashboard.
  2. Click Route Tables on the left navigational side panel
  3. Click the Create route table button
  4. Enter the name of the new route table
  5. Select the VPC to use for the new route table
  6. Click Create route table

routetable_steps.png

2. Create private subnet and assign route table

An additional private subnet will be added as all default subnets are public subnets.

To create the subnet,

  1. Search for VPC to navigate to the VPC Dashboard.
  2. Click Subnets on the left navigational side panel
  3. Click on the Create subnet button. (Not included in image below)
  4. Select the target VPC to use. In our case, it would be the default VPC.
  5. Please make sure you have done the following
    • Enter the subnet name
    • Select the availability zone. You can leave it as No preference if you wish to stick to the default settings.
    • Enter the IPv4 CIDR block for the subnet.
      • Please make sure the CIDR range provided is within the primary CIDR block. E.g: 172.31.x.0/20, where you should replace x with a value that will not clash with the existing subnet CIDR range.

subnet_steps.png

3. Associate the private subnet to the route table

For subnets created in the default VPC, the default route table will automatically be assigned to the newly created subnet. You will need to explicitly associate the route table created in step 1 to the newly-created subnet.

To associate the private subnet to the target route table

  1. Click on the newly created subnet. Navigate to the 'Route table' tab at the bottom of the page
  2. Click Edit route table association

routetable_assoc_steps1.png

  1. Select the newly created route table above
  2. Click Save

routetable_assoc_steps2.png

4. Create SSH Key Pair

You can skip this step if you already have an existing keypair. If not, follow the steps below to create one.

  1. Search for EC2 to navigate to the EC2 Dashboard.
  2. Navigate to Network & Security > Click Key Pairs
  3. Click Create key pair once you are in the Key pairs page. You will be redirected to the Create key pair interface.
  4. Please make sure you have done the following
    • Enter the name of the keypair.
    • Select RSA and .pem for the key pair type and private key file format.
  5. Click Create key pair after providing the necessary input.
    • A .pem file will be downloaded automatically to your local machine.

Please keep this keypair safe! If you lost this keypair, you will have to delete and recreate a new one.

keypair_steps.png

5. Create Security Group

We will need SSH access to access our EC2 instances.

  1. Search for Security Groups. Click on the one that indicate it to be 'EC2 feature'
  2. Click on the Create security group button.
  3. Please make sure you have done the following
    • Security group name
    • Description
    • VPC (Should already be the default VPC)
  4. Click Add rule
  5. In the 'Inbound rule 1', please make sure you have done the following
    • Set the Type to be SSH
    • Set the Source type to be My IP
  6. Click Save

securitygroup_steps.png


Launch EC2 instance

Disclaimer on incurring cost

  • If your account is under the 12-month AWS Free Tier program, please stick to the free tier EC2 instance type, i.e. t2.miro
  • If your account no longer under the 12-month AWS Free Tier program, you will incur the regular charges for running EC2 instances

Phew, we have done quite a bit of configuration!

We can now spin up an EC2 instance in the public subnet and private subnet respectively. We will be using them to test the Bastion Host configurations to access our resources in the private subnet.

AWS Management Console provides an intuitive interface to launch EC2 instances in a step-by-step flow. Below are the specifications you should choose:

  1. Choose AMI: Please select Amazon Linux 2 AMI (HVM)
  2. Choose Instance Type: Please select t2.micro
  3. Configure Instance: Please ensure you select the following
    • For Subnet, select the intended subnet (private/public) when you create for the respective subnet(private/public)
  4. Add Storage: Use the default; Click Next
  5. Add Tags: Please add a tag, with the key being "Name" and the value being the intended EC2 name
  6. Configure Security Group:
    • Please select the security group for SSH you have created earlier
  7. Review: Check that you have selected the right values.

Verifying EC2 Connectivity

Now that the EC2 instances are up, we can proceed with trying to connect to them.

For brevity, I will be referring to the EC2 instance in the private subnet as 'private EC2' and the EC2 instance in the public subnet as 'public EC2'.

Some values would be generic placeholders as they may be sensitive information or values that may vary for your own environment.

SSH into your instance

  • Select your EC2
  • Right-click on your EC2 > Connect
  • You can copy the command to SSH into your instance

ssh_interface.png

Connect to your EC2 instances

Activity 1

Try SSH into your private EC2.

Intended behavior

You shouldn't be able to connect to the EC2 as it resides in the private subnet. You will see the following error when attempting to SSH.

% ssh -i "<pem_filename>" ec2-user@<instance_ip_address>
ssh: connect to host <instance_ip_address> port 22: Operation timed out

Activity 2

Try SSH into your public EC2.

Intended behavior

You should be able to connect to the EC2 as it has a public address attached to it. You may be prompted to verify if you want to continue connecting, enter yes to SSH into the EC2 instance

% ssh -i "<pem_filename>" <public_dns_instance_address>
<Console output is removed for brevity>
[ec2-user@<instance_ip_address> ~]$

Troubleshooting

If you face an issue connecting, you will have to check if you have attached the right security group to the public EC2.


Accessing your EC2 in the private subnet via Bastion Host

Our EC2 in the public subnet will act as the Bastion Host to access our EC2 in the private subnet. Here's a recap of the architecture diagram for Bastion Host to access the private EC2

BastionHostSetup.png

How do we connect without adding the private key into the private EC2 instance?

As mentioned above, we will be using SSH agent forwarding to access the private EC2 via the Bastion host without storing the private key in the Bastion Host

What is an SSH Forwarding Agent

For a Linux/Unix machine, the ssh-agent is a built-in program to keep track of your private keys. This program allows us to log in without having to store the private keys in the Bastion host.

You can use the ssh-add command to add the private key into the SSH authentication agent, thus implementing a single sign-on with SSH.

% ssh-add <pem_filename>
Identity added: <pem_filename> (pem_filename)

Verifying Bastion Host Setup

  • You can now try to SSH into the public EC2 with ssh -A
  • Inside the public EC2, try to SSH into the private EC2 via its private IP address
    % ssh -A  <public_dns_instance_address>
    [ec2-user@<public_instance_ip> ~]$ ssh -A ec2-user@<private_instance_ip>
    

Conclusion

And voilร ! You are now able to access your resources in the private subnet via a Bastion Host.

In this article, we cover some pointers about the default VPC and subnets in AWS. This is followed by configurations to set up the Bastion Host to be able to access our resources in the AWS private subnet. We also briefly covered SSH forwarding agents, which is useful in keeping track of our private keys.

My Food 4 Thought

Networking has always been quite daunting for me ๐Ÿ˜ตโ€๐Ÿ’ซ From this learning experience, I got to familiarize myself with the difference in connectivity between private and public subnet, as well as at the VPC level.

Do you feel the same in understanding the intricate details of computer networks? Do drop some comments to share your views ๐Ÿ™Œ๐Ÿผ

A little onto Automation

Find the steps via AWS Management Console a little tedious and cleaning up is a hassle? You can find the article for the ready-to-use CloudFormation templates to provision for this setup through Infrastructure as Code (IaC)

Did you find this article valuable?

Support Bernice Choy by becoming a sponsor. Any amount is appreciated!

ย