Skip to content

Instantly share code, notes, and snippets.

@elgalu
Forked from Maks3w/_AWS_SSM_SSH_Tunnel.md
Created October 19, 2021 11:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elgalu/2b1150bee7ace8778cb4b44c92e99fd1 to your computer and use it in GitHub Desktop.
Save elgalu/2b1150bee7ace8778cb4b44c92e99fd1 to your computer and use it in GitHub Desktop.

Both things have been introduced recently, and let you access even private ec2 instances

  1. Without VPN
  2. No open SSH port
  3. Authentication / Authorization is fully delegated to IAM
# Assumes valid AWS Credentials in ENV
# Important. Always set the username
ssh ec2-user@i-002afb820244e392f

What this will do (through the aws-proxy script below):

  • Generate a single use ssh key
  • Push the generated publich key to AWS for the given user of the provided ec2 instance id
  • Create a tunnel through Session Manager
  • Establish an SSH session

The host has to be configured to run:

  • SSM Agent
  • ec2-instance-connect

Locally, you'll have to have a recent version of the AWS cli and the SSM plugin

#!/usr/bin/env bash
set -o nounset
set -o errexit
ONE_TIME_KEY_FILE_NAME=$1
ONE_TIME_PUB_FILE_NAME="${ONE_TIME_KEY_FILE_NAME}.pub"
USER=$2
HOSTNAME=$3
echo "Generating Ephemeral SSH key ..." >&2
yes | ssh-keygen -t rsa -b 2048 -f "${ONE_TIME_KEY_FILE_NAME}" -N ''
echo "Pushing SSH public key to EC2 instance ..." >&2
INSTANCE_AZ=$(aws ec2 describe-instances --instance-ids "${HOSTNAME}" --query 'Reservations[*].Instances[*].Placement.AvailabilityZone' --output text)
aws ec2-instance-connect send-ssh-public-key \
--availability-zone "${INSTANCE_AZ}" \
--instance-id "${HOSTNAME}" \
--instance-os-user "${USER}" \
--ssh-public-key "file://${ONE_TIME_PUB_FILE_NAME}"
echo "Connecting using SSM tunnel ..." >&2
# SSH over Session Manager and EC2 Instance Connect
# Example with User from command line
Match host i-*,mi-* exec "aws-proxy /tmp/aws-proxy.%h.%r %r %h"
# USER MUST BE ALWAYS SET IN COMMAND ARGUMENTS
# %r (user) is used earlier. Unless you opt for replace %r with your own fixed value (see the same example below)
# User ec2-user
IdentityFile /tmp/aws-proxy.%h.%r
ProxyCommand aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p
# Remove ephemeral key
PermitLocalCommand yes
LocalCommand rm /tmp/aws-proxy.%h.%r*
# Example with a fixed User (note there are many places where is needed to set)
Match host i-*,mi-* exec "aws-proxy /tmp/aws-proxy.%h.ec2-user ec2-user %h"
# Example with all (for simplicity) %r replaced with "ec2-user" (5 occurrences)
User ec2-user
IdentityFile /tmp/aws-proxy.%h.ec2-user
ProxyCommand aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p
# Remove ephemeral key
PermitLocalCommand yes
LocalCommand rm /tmp/aws-proxy.%h.ec2-user*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment