AWS Bastion Host / Jump Box
Tags: aws, networking
Published: 2022-02-07 02:45:13

As systems administrators, we should keep updating the infrastructure applying security patches, installing the new versions of the operation system, and setting up applications correctly to strengthen the security of cloud technologic resources and achieve AWS Shared Responsibility Model. For doing these activities on EC2 instances and RDS databases are necessary to access securely.


In this post, we are going to see how to establish the connection with EC2 instances and RDS databases that are on private subnetworks (without access from the internet) through Bastion Host or Jump Box and using **OpenSSH** and **[MySQL Workbench](https://www.mysql.com/products/workbench/)** tools. We will use the virtual private cloud (VPC) and subnetworks created on the post **[AWS Networking from scratch](https://dev.to/aws-builders/aws-networking-from-scratch-8dm)** to protect the infrastructure by creating private and safe environments with network topologies and access control inbound and outbound communications to EC2 or databases RDS.


We start to create an EC2 Bastion Host instance, then provision EC2 and RDS instances on a private subnetwork and establish a connection to these instances through Bastion Hots. Let’s start:
&nbsp;



## Create Bastion Host.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/be3qv3za0xhugthd86sm.png)


It is an EC2 instance deployed on VPC and public subnet (with access from the internet) for the connection with EC2 instance and RDS databases on VPC and private subnet (without access from the internet) through SSH (Secure Shell) and TCP/IP communication protocols. The steps to create a Bastion Host are:
&nbsp;


- 
Use EC2 instance wizard. Choose AMI (Amazon Machine Image), for this example we use Amazon Linux 2 AMI.




![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3mfc3mae4x35mk9qvky.png)
&nbsp;


- 
Choose VPC and public subnet on EC2 instance detail configuration.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mju96vfx0k0aovdxyzeb.png)

In the Post **[AWS Network from scratch](https://dev.to/aws-builders/aws-networking-from-scratch-8dm)** we created the **publicSubnet1A** subnet with CIDR **192.168.0.0/27** and VPC **192.168.0.0/24**, the route table and network access control list (NACL) allows internal and external communications.
&nbsp;


- 
Create a Security Group (Firewall) with the inbound rule to enable SSH connection through TCP/IP protocol and port 22 from our local machine IP address.




![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3a25al4eu8fzsoldgofv.png)
&nbsp;


- 
Create keys (public and private) for SSH authentication.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qalns7z74x783j8kwxni.png)
&nbsp;


- 
Review instance launch details and launch it.
&nbsp;




&nbsp;
&nbsp;
## Create an EC2 instance on a private Subnet.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btwt9rjo7fgzm5db4h9r.png)

An EC2 instance is private when it is deployed on a subnet with communication restrictions from the internet. The steps to create an EC2 instance and deploy it on the private subnet are:
&nbsp;


- 
Use EC2 instance wizard. Choose AMI (Amazon Machine Image), for this example we use Amazon Linux 2 AMI.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3mfc3mae4x35mk9qvky.png)
&nbsp;


- 
Choose VPC and private subnet on EC2 instance detail configuration.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0wrzuzmlcu2zryp0p7h.png)


In the Post **[AWS Network from scratch](https://dev.to/aws-builders/aws-networking-from-scratch-8dm)**, we created the **privateSubnet1A** subnet with CIDR **192.168.0.32/27** and VPC **192.168.0.0/24**, the route table, and network access control list (NACL) allows only internal communications.
&nbsp;


- 
Create a Security Group (Firewall) with the inbound rule to enable SSH connection through TCP/IP protocol and port 22 from the security group of Bastion Host.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8b7shfb8s3tf7y3gkqic.png)
&nbsp;


- 
Create keys (public and private) for SSH authentication. These keys should be different from the Bastions Host keys to increase the security and reduce the risk to access many infrastructure resources when a third party gets access to the key.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ou72ox9uri90q0g4khpv.png)
&nbsp;


- 
Review instance launch details and launch it.



&nbsp;
&nbsp;
## Create an RDS Database on a private Subnet.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3omde3ta0viofk55r94.png)

An RDS Database instance is private when it is deployed on a private subnet with communication restrictions from the internet. The steps to create an RDS database and deploy it on the private subnet are:
&nbsp;

- 
Create a Subnet Group with VPC and at least two Subnetworks in two different availability zones in the AWS region:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thvvld218kvnfnxzmhbg.png)


In the Post **[AWS Network from scratch](https://dev.to/aws-builders/aws-networking-from-scratch-8dm)**, we created the **privateSubnet1A** subnet with CIDR **192.168.0.32/27** on the availability zone **us-east-2a** and VPC **192.168.0.0/24**, the route table, and network access control list (NACL) allows only internal communications. On the availability zone **us-east-2b** we have the subnet **publicSubnet1B** with CIDR **192.168.0.64/27** in the same VPC.
&nbsp;



- 
Create a Security Group (Firewall) with the inbound rule to enable MYSQL/Aurora connection through TCP/IP protocol and port 3306 from the security group of Bastion Host.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3djjpyrc53d3l62y9otw.png)
&nbsp;


- 
Use the RDS database, instance wizard. Choose the database engine, for this example we use MySQL:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lv6t29myqah4a8a8n12t.png)
&nbsp;



- 
Enter database instance identity and create database access credentials, Master username, and Master password:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvjzja717gkyr2wdjmqq.png)
&nbsp;



- 
Set up database connection properties, enter the values to VPC, Subnet Group (**Created in step 1**), enable public restrictions, security group (**Created in step 2**), choose availability zone where the private subnet is present (**us-east-2**) and port:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcjqyzoe1c2uvkgj9xyo.png)
&nbsp;



- 
Enter database name:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0atss3lhbucf1nl0j4h.png)
&nbsp;


- 
Create a database.


&nbsp;
&nbsp;
## SSH Connection to Bastion Host


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0b4gm5paox0x1vcynk3.png)


For SSH connection to Bastion Host from our local machine, we can use SSH clients like OpenSSH, Putty, MobaXterm, WinSCP, and others. We need the public IP address or DNS of the EC2 instance (Bastion Host), the default user name of AMI used to create the EC2 instance, and a private SSH key. The steps to establish the connection are:
&nbsp;


- 
Find the public IP address or DNS in the EC2 instance details section:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngrll9yj3j9x31p4aot0.png)
&nbsp;


- 
Search the default user name of the AMI used to create the EC2 instance. The default user name of the Amazon Linux AMI is **ec2-user**.
&nbsp;


- 
From our local machine and using the OpenSSH command line, execute the command `ssh-add -k` to add Bastion Host private key (.pem) to **ssh-agent**:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8awqij7vdoazt4gm65fo.png)

On Windows, run the OpenSSH Authentication Agent service first to execute the command ssh-add.
&nbsp;


- 
Execute the command `ssh {user-name}@{public IP address}` with the user name and public IP address of EC2 instance to establish ssh connection:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzk1p5ss7dex3qnqisub.png)


&nbsp;
&nbsp;
## SSH connection to EC2 private instance



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8cgwqc8m0i9e26be1j9u.png)

With Bastion Host connection ready, we can execute the below steps from our local machine and with **OpenSSH** client to connect with EC2 private instance:
&nbsp;


- 
Find the private IP address on the EC2 instance details section:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ki20y9sz334kma8huc7h.png)
&nbsp;


- 
Search the default user name of the AMI used to create the EC2 instance. The default user name of the Amazon Linux AMI is **ec2-user**.
&nbsp;


- 
From our local machine and using the OpenSSH command line, execute the command `ssh-add -k` to add EC2 private instance private key (.pem) to ssh-agent:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uhjgx63rdyjpaatxtffu.png)

On Windows, run the OpenSSH Authentication Agent service first to execute the command ssh-add.
&nbsp;


- 
Execute the command `ssh – J {user-name}@{public IP address} {user-name}@{private IP address}`, with the Bastion Host user name and public IP address, and EC2 private instance user name and local IP address to establish SSH connection:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kym5tmk9djmm1qqnroyr.png)


&nbsp;
&nbsp;
## RDS private database connection


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n59k81f769ittfajcvdf.png)

The steps to establish a connection with a private database using **MySQL Workbench** client from our local machine are:
&nbsp;


- 
Find the end-point and connection port of the database on RDS instance details.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hiujhs11nhuaxbzevfpf.png)
&nbsp;



- 
Open MySQL Workbench wizard to set up TCP/IP connection over SSH. Enter the following fields:
&nbsp;


a. **SSH Hostname:** Bastion Host public IP address or DNS with port 22.

b. **SSH Username:** The default user name of the AMI used to create the EC2 instance. The default user name of the Amazon Linux AMI is ec2-user.

c. **SSH Key File:** Bastion Host Private key (.pem) for SSH authentication.

d. **MySQL Hostname:** End-point database connection (point 1).

e. **Username:** Database username.

f. **Password:** Database password.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4yotbp60brclc9z9ymab.png)
&nbsp;


- 
Test connection



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87iakqr8y9flv92p2558.png)


&nbsp;
&nbsp;
## Conclusion


In this post, we learned the steps to establish a connection with EC2 and RDS private instances through Bastion Host. We used the **OpenSSH** and **Workbench** tools to connect with the EC2 instance and RDS database.
&nbsp;


##References

**[How can I use an SSH tunnel and MySQL Workbench to connect to a private Amazon RDS MySQL DB instance that uses a public EC2 instance?](https://aws.amazon.com/premiumsupport/knowledge-center/rds-mysql-ssh-workbench-connect-ec2/)**
&nbsp;

**[SSH to remote hosts though a proxy or bastion with ProxyJump](https://www.redhat.com/sysadmin/ssh-proxy-bastion-proxyjump)**