🎉 We are launching a new weekly show: Hot off the Cloud

🎉 We are launching a new weekly show

Connect to your EC2 instance using SSH the modern way

Andreas Wittig – 01 Feb 2022

Did you know that establishing an SSH connection with an EC2 instance is possible without configuring a key pair and allowing inbound traffic on port 22? How is that possible? The secret is a combination of EC2 Instance Connect and Systems Manager (SSM). When following this article, connecting with an EC2 instance is as simple as typing ssh i-059499e6abc8fbe6b into your terminal.

How to set up Jenkins on AWS?

First of all, the following video demonstrates how to establish an SSH connection with an EC2 instance by using EC2 Instance Connect and Systems Manager.

The following diagram explains the approach in more detail.

  • The user sends her public key to EC2 Instance Connect using the AWS CLI.
  • EC2 Instance connect pushes the key to the EC2 instance. The key remains for 60 seconds.
  • An SSM agent running on the EC2 instance establishes a bidirectional channel with the SSM backend.
  • The user establishes an SSH connection through a Websocket between Terminal and SSM.
  • Authentication and authorization for the user and the SSM agent is IAM’s job.

Establishing an SSH connection with an EC2 instance by using EC2 Instance Connect and Systems Manager

How do you make this approach happen on your local machine and EC2 instances?

  • Make sure the SSM agent is running on your EC2 instances - which is already the case for Amazon Linux and Amazon Linux 2.
  • Double check that the SSM agent running on your machines can connect with the SSM API through an internet gateway, NAT gateway, or VPC endpoint.
  • Attach an IAM role - granting the SSM agent access to the SSM API - to each EC2 instance to
  • Install the AWS CLI and the session manager plugin on your local machine.
  • Configure your SSH client to use EC2 Instance Connect and Systems Manager to establish a tunnel for SSH connections.

Are you confused about the different options to connect by using EC2 Instance Connect and Systems Manager? Check out Petri’s comparision: EC2 Instance Connect vs. SSM Session Manager


Looking for a new challenge?

  • tecRacer

    Cloud Consultant • AWS Migrations

    tecRacer • Premier AWS Consulting Partner • Germany, Austria, Portugal, and Switzerland
    Assessment Transformation Change Management
  • DEMICON

    Senior Lead Full Stack Developer

    DEMICON • AWS Advanced Consulting Partner • Remote
    AWS JavaScript/TypeScript Angular React

IAM role required by SSM agent

As mentioned before, the SSM agent is running on most EC2 instances already. That’s because the agent is bundled into Amazon Linux, Amazon Linux 2, SUSE Linux Enterprise Server (12 and 15), and Ubuntu Server (16.04, 18.04, and 20.04) by default.

Learn how to Manually install SSM Agent on EC2 instances for Linux from the AWS documentation.

However, the SSM agent requires an IAM role attached to the EC2 instance granting access to the SSM API. That’s not a default, so you probably need to create a new IAM role or add a policy to existing roles.

You can either use the predefined policy AmazonSSMManagedInstanceCore (arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore) managed by AWS. Or create your own managed or in-line policy with the following contents.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:*",
"ec2messages:*",
"ssm:UpdateInstanceInformation"
],
"Resource": "*"
}
]
}

Install the AWS CLI and session manager plugin

You will use the AWS Command Line Interface (CLI) to push your public key via EC2 Instance Connect and establish a tunnel for your SSH connection with the EC2 instance.

Therefore, make sure to install the AWS CLI on your local machine. Besides that, you need to install the session manager plugin.

I prefer brew to install the AWS CLI and the session manager plugin on macOS.

brew install awscli session-manager-plugin

Configuring your SSH client

Next, you need to configure your SSH client. To do so, edit the ~/.ssh/config file on your local machine. Please add the following snippet configuring connections for all hosts, starting with i- at the end of the file. Do not forget to replace $PRIVATE_KEY and $PUBLIC_KEY with the path to your private and public key.

# SSH over Session Manager
host i-*
IdentityFile $PRIVATE_KEY
User ec2-user
ProxyCommand sh -c "aws ec2-instance-connect send-ssh-public-key --instance-id %h --instance-os-user %r --ssh-public-key 'file://$PUBLIC_KEY' --availability-zone '$(aws ec2 describe-instances --instance-ids %h --query 'Reservations[0].Instances[0].Placement.AvailabilityZone' --output text)' && aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

For me, the snippet looks as follows.

# SSH over Session Manager
host i-*
IdentityFile ~/.ssh/id_ed25519
User ec2-user
ProxyCommand sh -c "aws ec2-instance-connect send-ssh-public-key --instance-id %h --instance-os-user %r --ssh-public-key 'file://~/.ssh/id_ed25519.pub' --availability-zone '$(aws ec2 describe-instances --instance-ids %h --query 'Reservations[0].Instances[0].Placement.AvailabilityZone' --output text)' && aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

The ProxyCommand contains a one-liner that I’d like to explain in more detail.

First, we need to find out the availability zone the instance is running in. The command aws ec2 describe-instances returns the necessary information. Please note that %h will be replaced with the host, for example, i-059499e6abc8fbe6b.

aws ec2 describe-instances --instance-ids %h --query 'Reservations[0].Instances[0].Placement.AvailabilityZone' --output text

Next, you need to push your public key to the EC2 instance. That’s why you need to execute the aws ssm start-session command.

aws ec2-instance-connect send-ssh-public-key --instance-id %h --instance-os-user %r --ssh-public-key 'file://~/.ssh/id_ed25519.pub' --availability-zone '$(...)'

Last but not least, you need to establish the SSH session through a WebSocket connection. That’s the job of the aws ssm start-session command.

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

Connect to your EC2 instance using SSH

You are ready to connect with your EC2 instance using SSH. All you need to do is type ssh followed by an EC2 instance ID into your terminal.

ssh i-059499e6abc8fbe6b

By the way, you can even copy files with scp.

ssh example.txt i-059499e6abc8fbe6b:/tmp/

That’s it. I hope you enjoy this approach to connect to your EC2 instances using SSH as much as I do.

Did you run into any issues while following my instructions? Do you love the approach to connect with your EC2 instances? Please let me know!

Become a cloudonaut supporter

Andreas Wittig

Andreas Wittig ( Email, Twitter, or LinkedIn )

We launched the cloudonaut blog in 2015. Since then, we have published 360 articles, 49 podcast episodes, and 48 videos. It's all free and means a lot of work in our spare time. We enjoy sharing our AWS knowledge with you.

Please support us

Have you learned something new by reading, listening, or watching our content? With your help, we can spend enough time to keep publishing great content in the future. Learn more

$
Amount must be a multriply of 5. E.g, 5, 10, 15.

Thanks to Alan Leech, Alex DeBrie, ANTHONY RAITI, Christopher Hipwell, Jaap-Jan Frans, Jason Yorty, Jeff Finley, Jens Gehring, jhoadley, Johannes Grumböck, Johannes Konings, John Culkin, Jonas Mellquist, Juraj Martinka, Kamil Oboril, Ken Snyder, Markus Ellers, Ross Mohan, Ross Mohan, sam onaga, Satyendra Sharma, Shawn Tolidano, Simon Devlin, Thorsten Hoeger, Todd Valentine, Victor Grenu, and all anonymous supporters for your help! We also want to thank all supporters who purchased a cloudonaut t-shirt.