How to SSH tunnel through AWS Systems Manager to access private VPC resources

Agaile Victor

How awesome is to access either a MongoDB or MySQL deployed in a VPC network locally using MongoDB Compass or MySQL Workbench ?

Yah! you heard me correctly.

At this point you might think that, how is it possible to tunnel to another resource within VPC directly from your local machine?

Log story short, Yes its possible with the help of AWS Systems Manager Session Manager.

I am working on an interesting project which involves lots of integrations where AWS Lambda functions and a document database (MongoDB) are deployed in two separate VPC networks. We are using VPC peering to establish connection between the lambda functions and MongoDB. It is a tiring job for the developers to connect through the Bastion Host or Jumpbox to query something from the Database. Mentioned below is the diagram for a better understanding of the scenario.

Before talking about the solution let’s have a look at the AWS Systems Manager Session Manager in a nutshell. Thanks to AWS for the wonderful documentation.

What is AWS Systems Manager Session Manager?

Session Manager is a fully managed AWS Systems Manager capability that lets you manage your Amazon Elastic Compute Cloud (Amazon EC2) instances, on-premises instances, and virtual machines (VMs) through an interactive one-click browser-based shell or through the AWS Command Line Interface (AWS CLI). This capability means that Session Manager tunnels real SSH connections, allowing you to tunnel to another resource within your VPC directly from your local machine. A managed instance that you create acts as a bastion host, or gateway, to your AWS resources. So, what are the benefits of having this configuration:

Increased Security: This configuration works with only one Amazon Elastic Compute Cloud (Amazon EC2) instance (the bastion host) with outbound port 443 connecting to Systems Manager infrastructure. This allows you to use Session Manager without any inbound connections. The local resource needs to allow inbound traffic only from the instance acting as bastion host. Therefore, there is no need to open any inbound rule publicly.

Ease of use: You can access resources in your private VPC directly from your local machine.

Enough talk, lets start working

In order to perform SSH operations from your local host to the remote cloud asset, you will need to perform the following setup steps.

In this tutorial we assume that Systems Manager Agent is installed and configured on your EC2 instance and created the user with necessary permissions. Also make sure you have the private key to perform the SSH.

We will focus on changing the SSH config which will do the magic for us.

Install latest AWS CLI:

An updated command line interface is required on your local host in order to use these new Session Manager features.

Install the Session Manager Plugin:

This plugin allows the AWS cli to launch Session Manager sessions with your local SSH client.

Update local host SSH config:

The tricky portion of this setup involves altering your local host SSH configuration in order to proxy commands through the AWS session manager for any aws ec2 instance-i.

For Linux:

You will typically find your SSH config file at ~/.ssh/config
Add the following to the SSH config file:

# SSH over Session Manager

host i-* mi-*

ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

For Windows:

You will typically find your SSH config file at C:\Users\username.ssh\config though the .ssh directory will not exist until ssh has been used.
Add the following to the SSH config file:

# SSH over Session Manager

host i-* mi-*

ProxyCommand C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p"

Once these steps are complete, you can now initiate SSH and SCP connections to your cloud instance directly from your local machine. Obtain the instance-id of the target instance, yes its the instance-id not the hostname. SSH can be performed as normal using the instance-id as the hostname.

Now we can create a tunnel from your local machine to access a MongoDB database running on a private EC2 instance using the SSM host as a bastion host.

From a local machine (for example, your laptop), run the SSH command to connect to instance1, using Session Manager-based SSH. This command establishes a tunnel to port 27017 on instance2, and presents it in your local machine on port 9999

ssh -i /path/key-pair_instance1.pem [email protected] -L

In the aforementioned example, port 9999 is an available port on the local machine. From the local machine, access the database using the available port used in our example, 9999.

Now open the MongoDB Compass and create a new connection with below mentioned connection string.

mongodb://username:[email protected]:9999/databasename

These connections are secured by IAM access and generate cloudtrail events for logging and monitoring. While immutable infrastructure is a desired goal for multiple reasons. Many will find themselves with a need to access or alter systems running live. The AWS Systems Manager Session Manager allows this capability without the need for additional firewall ingress or bastion hosts.

Agaile Victor

A Full Stack Software engineer in Kuala Lumpur, Malaysia with a passion of writing code to solve complex issues.

You may also like...

%d bloggers like this: