On-demand Opening of SSH Ports on AWS

Image of BBEdit running on a MacBook Pro with the article's script loaded
Scripting helps automate mundane things and make your life wonderful.

While other cloud providers usually force you to leave SSH open or restrict access with your own firewalls, AWS has the major advantage of security groups1. You can stop any traffic dead in its tracks before your server has to deal with it.

You can configure Security Groups in a few ways:

  • Through the AWS web interface.
  • With the AWS CLI command line interface.
  • Not at all.

Some people just leave their SSH port open, or restrict it to their static IP. The former being less secure than needed and the latter less flexible than wanted.

Pre-requisite: Install the AWS CLI

The AWS-CLI has information on how to install the CLI, with most Linux distros having packages for it for an easy install. On macOS, you can go the Homebrew route.

If you haven’t already done so, install Homebrew. Homebrew is a package manager for all the stuff your Mac lacks—usually not much compared to Windows, but still a lot for a developer to be sad. Using Homebrew and its Python will cause less conflicts on your system.

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Make sure you know what this command does, refer to the Homebrew website.

Now we install Python and the AWS CLI.

$ brew install python
$ pip install --upgrade --user awscli

Scripting

I’m using a script to connect to my AWS instances. The script will open an SSH port in the associated Security Group, connect me via SSH, and when the connection ends or disconnects, remove that rule again, closing the instance off.

Here’s the script connect-aws.sh:

#!/bin/bash

# -----------------------------------------------------------
# connect-aws.sh
# -----------------------------------------------------------

# Variables

instancehost="yourinstance.example.com"
sshuser="admin"
sshport="22"
sshidentity="~/.ssh/your-private-key.key"
securitygroup="sg-1234abcd"
region="eu-central-1"

# Execution

ip=`curl -s https://api.ipify.org`

echo "Current IP address: $ip"
echo "Instance Host: $instancehost"
echo "AWS Security Group ID: $securitygroup"
echo "Adding IP $ip to AWS Security Group $securitygroup in region $region ..."

aws ec2 authorize-security-group-ingress --protocol tcp --port $sshport --cidr $ip/32 --group-id $securitygroup --region $region

echo "Connecting via SSH to $instancehost ..."

ssh $instancehost -l $sshuser -p $sshport -i $sshidentity

echo "SSH connection closed. Removing IP $ip from AWS Security Group $securitygroup ..."

aws ec2 revoke-security-group-ingress --protocol tcp --port $sshport --cidr $ip/32 --group-id $securitygroup --region $region

echo "Done."

You only need to modify the # Variables:

instancehost: Hostname or IP address of your AWS instance.
sshuser: The local user name you’re using to login via SSH.
sshport: The SSH port, default is 22.
sshidentity: The path to the private key used for connecting to your AWS instance.
securitygroup: The Security Group identifier.
region: Your AWS region (since you can have instances in multiple regions).

Note: To get the current IP address programmatically, I’m using the amazing service by https://www.ipify.org. By default, it will simply output your current IP address as plain text. They have more options, so please have a look at their site. Their traffic is encrypted.

Make the script executable:

$ chmod u+x connect-aws.sh

Now, simply execute the script to open a SSH shell to your instance:

$ ./connect-aws.sh

Feel free to reach out if you have any questions.

  1. AWS Security Groups are virtual firewalls, not only giving you fine-grained control over external access to your instances, but also isolating your instances from each other if needed. Great great great. ↩︎