Everything you need to know about Bastion host in AWS infrastructure.
In this article, we will touch base below points in context to bastion host:
- What is a bastion host?
- What is the role of bastion host in AWS infrastructure?
- How to deploy and configure a bastion host?
Lets start with the introduction to bastion host.
What is bastion host?
A bastion host is a Windows or Linux machine sitting in the Public subnet of your AWS infrastructure. It’s a machine that is used to securely access the rest of the infrastructure for administration purposes. Since you don’t want to expose everything in your infra to the internet, the bastion host will do that heavy lifting and hence securing the infrastructure.
As this host is exposed to the internet it is recommended to implement a strong system hardening on this machine. Secure this machine at OS level with all available hardening techniques since this machine is a gateway to your whole infrastructure.
What is the role of bastion host in AWS infrastructure?
As explained above, the bastion host will be used to access the rest of the infrastructure. for administrative tasks. Sometimes, cloud newbies treat bastion host as a way of accessing instances in the private subnet only. But that’s not it. One should block access (SSH or RDP) to instances in the public subnet as well and allow them only through the bastion host.
This way one can secure administrative level access to instances in public and private subnets. And this is the recommended practice. Your all instances no matter they are in which subnet should be accessible via bastion host only.
In a nutshell, bastion hosts used to secure administrative access to instances in private and public subnets.
How to deploy bastion and configure host?
For this exercise, we will deploy Linux bastion host in the same architecture which we used while creating our last custom VPC. In the case of the Windows environment, SSH can be replaced with RDP, and Linux bastion can be replaced with a Windows machine. Bastion host deployment and configuration can be summarised as –
- Deploy EC2 instance in the public subnet (that’s your bastion host)
- Create a new security group which allows SSH traffic from bastion to destination public and private subnets
- Attach security group to instances
Lets dive into it.
For step 1, I deployed Amazon Linux 2 EC2 instance. You can even use customized AMI which has all hardening already done, logging enabled for a bastion, etc things. But for this exercise, I will be using normal Amazon Linux AMI. The SG created along with this launch should allow SSH traffic from 0.0.0.0/0. Let’s tag this SG as bastion-sg
Now, it’s time to create a custom security group to allow bastion traffic to instances. Custom SG is handy so that you can attach it instances while launching and you don’t need to manually edit instances security groups to allow bastion traffic. On other hand, in this SG we are allowing traffic from SG of bastion host. So even in future IP of bastion host gets changed (or even bastion host gets replaced) we don’t have to edit any SG settings anywhere. The only thing you need to keep in mind that, you need to deploy a new bastion host with the existing bastion SG.
- Log in to EC2 console
- On the left navigation plane, click on Security Groups
- Now on the security groups page, click on the Create security group button
- You will be presented with the below screen :
You need to fill in below details-
- Security group name: For identification
- Description
- VPC: Select your VPC from the dropdown.
- Inbound rules: Allow SSH from SG of bastion host (bastion-sg from step 1)
- Outbound rule: Keep it default. Allow all traffic.
- Tags: optional.
This SG (allow-bastion-traffic-sg) to be attached with instances launched in public/private instances. Make sure you remove the existing default SG attached to them which allows SSH traffic from 0.0.0.0/0 OR edit an inbound rule in the existing SGs which allows this.
It confirms that SSH traffic to all instances in your VPC will be allowed only from the bastion host.
At this stage, bastion host SG should have below inbound rule:
And instances in VPC (any subnet) should have below inbound rule where the source is bastion-sg (SG of bastion host):
We are all set! It’s time to test. Below are 2 instances for testing. Once is the bastion and another is launched in the private subnet. This could work with an instance in the public subnet as well but they will be having public IP allocated as well so to avoid confusion I took an instance from the private subnet.
I logged in to the bastion host using its public IP. Remember, we deployed bastion host in public subnet hence it will get public IP on launch. And since public IP reachable over the internet, I can directly putty to public IP of bastion host.
Once I am in the bastion host, I tried to ssh to the private IP of an instance launched in the private subnet. Since instance is launched in a private subnet, it won’t be allocated with the public IP so it’s not reachable over the internet. So I have to use a bastion host to get into it and it worked!
Note: I used PuTTY SSH agent forwarding here so I did not have to supply the SSH key in command when connecting to the private instance.
In such a way you can secure administrative access to your instances in VPC (inside public and private subnet) by using bastion hosts.