Just as any host on the Internet, your EC2 instances are vulnerable to attack. While the EC2 firewall is a very powerful tool for securing your instance from unwanted network traffic, if used incorrectly you may still leave your instance vulnerable to attack. These attacks can come in many forms, e.g.:

  • Intrusion attempts: exploiting bad passwords on your system
  • Port Scanning: detecting what services you are running and then trying to exploit those
  • Denial of Service Attacks: inundating your server with junk requests or partial connections

Any one of these could result in disruption to your service, at best, or total loss of control of your instance or deletion of your data, at worst. Very often, intruders also go on to use your instance as a launch-pad for further attacks against other systems on the Internet, to send spam or to host illegal download sites.

These are some of the most important steps to take in order to mitigate risks.

Note: This is not intended to be an exhaustive security guide nor are there any implicit or explicit guarantees that these steps will ensure absolute system security.

Lock it Down: Close All Unecessary Ports

In our Getting Started guide we discuss the use of the ec2-authorize command. For the purposes of keeping things simple, that particular example suggests opening certain ports, eg ssh (TCP port 22) to the world, thus:

PROMPT>  ec2-authorize default -p 22
PERMISSION     default  ALLOWS  tcp     22      22      FROM    CIDR

Whilst this makes it easy for you to reach your instance from anywhere in the world, it makes it equally for anyone else to reach your instance. A more prudent approach is to restrict the access to port 22, in particular, to a set of hosts or networks that you trust.

For instance, let’s assume that your corporate firewall has the IP address and your corporation has been assigned that network as a /20, ie ( you could easily restrict ssh access to hosts only on your corporate network thus:

PROMPT>  ec2-authorize default -p 22 -s
PERMISSION     default  ALLOWS  tcp     22      22      FROM    CIDR

making it impossible for anyone on another network to even connect to your ssh server (the ec2-authorize command instructs the firewall (integrated into every EC2 instance) to drop packets not sourced on an approved network.) To make things even more secure, let’s say all traffic only comes from your firewall, we could restrict it to just one host:

PROMPT> ec2-revoke default -p 22 -s
PERMISSION              default ALLOWS  tcp     22      22      FROM    CIDR1.2.3.0/20

PROMPT>  ec2-authorize default -p 22 -s
PERMISSION     default  ALLOWS  tcp     22      22      FROM    CIDR

which is even more secure. If your network changes, you can always remove this rule and replace it with the new firewall address.

This technique should be used to secure any service port for TCP, UDP and ICMP traffic. Open only those ports that mustbe open for your service to operate.

Ditch Those Passwords: Use ssh Keys

In the Get Started guide we also show how to use keys to allow root login without passwords by using the ec2-add-keypair command to generate an RSA key and add it to your key-ring. This key is included when you launch your instance with the “-k” option and ensures that you can log in as root on your new instance.

However, we find that many users are then going on to create additional users for their instances and secure these accounts with passwords. Very often, these passwords are not very secure and are trivially cracked by intruders. They can also be taken with the employee when he or she leaves your organization.

A far better and certainly more secure mechanism is to use ssh keys for all users, in a similar way to the secure root login method described in the guide. Because the bundled commands only work for the root user, we’ll now describe some steps for adding ssh keys for all additional user accounts.

We’ll work on the assumption that you have access to a UNIX system of some description, although OpenSSH is available on many platforms. In addition, if you do not have a command-line based ssh client, most GUI clients, such as PuTTY work fine and there is a PuTTY Chapter a part of our standard docs.

For generating ssh keys for regular user accounts, we’d recommend that each user in your organization generate their own key. Have them provide their public key to your system administrator who may then add the key of any authorized use to the account(s) for which they need access on your ec2 instances.

Disable Password-based Login

Log in to your instance as root and edit the ssh daemon configuration file:

# vi /etc/ssh/sshd_config

Find the line

PasswordAuthentication yes

and change it to

PasswordAuthentication no

Note:Caution: whenever making changes to your sshd.config file, be certain that you have an active shell session in case you’ve made a fatal syntax error. After restarting sshd, log in from another session to test it before terminating your active terminal session

Save the file and restart sshd:

# /etc/init.d/sshd restart

You will now only be able to log in with an ssh key.

A few other measures could include giving “sudo” access to a select set of Administrative users and removing root login entirely as well as explicitly specifying the only users who may login. Such a list should exclude other “system” accounts that do not need login capabilities. Once logged in with your regular account, you can always su the “su” or “sudo” commands to gain privilege to these accounts:

# vi /etc/ssh/sshd_config

Find the line

PermitRootLogin yes

and add the AllowUsers entry and change PermitRootLogin to

PermitRootLogin no
AllowUsers john sally

Again, be sure that you have an active login, save the file and restart sshd:

# /etc/init.d/sshd restart

Key Generation and Distribution

In the Getting Started guide we showed how to generate the initial keypair for the root user. This is how to create similar keypairs for all users who need access to your instances.

In the example below (to be run on your local machine, not your EC2 instance) replace “user” with the actual user’s login, name or some other unique identifier.

ssh-keygen -b 1024 -f user -t dsa

This will create 2 files:

  • user (private key)
  • (public key)

Copy all the public key files that you generated to a temporary place on your instance:

scp -i root *.pub

User Account Creation

Log in to the instance as root. For each user you are creating, add the user to your instance with the

# useradd -c "firstname lastname" user

For simplicity’s sake, use the same “user” name as you did for key generation. Now we need to place the key into their ssh authorized keys file (again, replacing “user” with the username you chose earlier)

# cd ~user
# mkdir .ssh
# chmod 700 .ssh
# chown user:user .ssh
# cat /tmp/ >> .ssh/authorized_keys
# chmod 600 .ssh/authorized_keys
# chown user:user .ssh/authorized_keys

Logging In

Ensure that your users all have their appropriate private keys (generated earlier) and that they are in the users’ “.ssh” directory of the local machine. Each user can now log in to any instance that has them added as a user and a copy of their public key in the .ssh/authorized_keys file in their home directory on the EC2 instance:

ssh -i ~/.ssh/user -l user

For use with PuTTy, please read this chapter.

Bundle Up

Naturally, these keys and user entries now exist on the current running instance and when you have added all your users, you should bundle and register the new AMI as described in Getting Started so that any new instances you launch from the AMI will already have all the appropriate accounts set up.

Naturally, this may be tedious for situations with many user accounts or many instances, so you could equally provide a scripted solution that keeps track of active users by synchronizing with a persistent store such as S3.

Cleaning Up

Remember to delete keys from the authorized_keys file on your instances when someone leaves your organization or no longer requires access. This can easily be achieved with the

# userdel user

command. Beware, this will delete all data in the user’s home directory.

It’s All About Need to Know: Who, Why and What

Operate your system on a strictly “need to know” basis:

  • Provide access only to those users who have a business need to be on your systems.
  • Give them only as much access and privelege as they need to perform their specific tasks.
  • provide temporary escalated priveleges such as sudo for users who need to perform occasional specialty tasks. These commands leave an audit trail.
  • Have a procedure to revoke access when it is no longer needed.

Keeping Current: Regular Updates

Because the Linux world is highly dynamic and supported by a large and active community, there are always new versions, patches and upgrades to many components of a system. Many of these upgrades are in response to security vulnerabilities and it is vitally important to always stay current.

Due to the fact that EC2 provides a set of base AMIs that have been created at some time in the past, it’s important to integrate the latest changes when initiating a new AMI for the first time as many patches may have been released since the original bundling of the AMI.

When you rebundle this AMI as your own, it will incorporate all the changes, but it’s still important to establish a periodic check for all your running instances to collect any new changes.

The easiest tool to maintain your versions is something like the yum tool. Log in to your instance as root and simply run:

# yum update

Other distributions may offer similar tools, eg Debian and Ubuntu may use

# apt-get update