As with any host on the Internet, EC2 instances are vulnerable to attack. EC2 firewalls offer a very powerful means of securing an instance from unwanted network traffic, but some applications require you to relax your firewall settings--potentially exposing your instance to attacks, 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
Attacks against your instance could result in disruption to your service, or even total loss of control of your instance and deletion (or exposure) of your data. Also, an intruder who has take control of your instance may use it as a launch-pad for further attacks against other systems on the Internet (like sending spam or hosting illegal download sites).
This articles presents a few very basic steps that can help to mitigate risks to your AWS EC2 instance.
Please 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.
Keep your ports closed.
In computer networking, a port is an application-specific or process-specific communications endpoint in a computer's host operating system.
AWS security groups can help you to launch an instance with only a limited number of open ports. An AWS EC2 instance's security group options are usually set at the time you launch your instance, with the default behavior being to create a new security group each time.
The AWS Management Console provides a fairly user-friendly way of handling ports.
Ports can also be controlled using the AWS CLI with the ec2-authorize command.
Good practice is to keep things simple: open only those ports that you know you need. For my purposes, TCP port 80 (standard port for web traffic) and TCP port 22 (standard port for ssh) usually suffice.
To open port 22 using the
PROMPT> ec2-authorize default -p 22 PERMISSION default ALLOWS tcp 22 22 FROM CIDR 0.0.0.0/0
Port 22 is actually a bit of a liability. I use ssh to reach my instance, and as I often travel to odd spots across the world, keeping 22 broadly open is necessary for my purposes. If you work only from your home or office (and have a static IP), a more prudent approach would be to restrict access a set of hosts or networks that you trust. For instance, assuming that your corporate firewall has the IP address 184.108.40.206 and your corporation has been assigned that network as a /20, i.e. 220.127.116.11/20 (18.104.22.168 - 22.214.171.124) you might restrict ssh access to hosts thus:
PROMPT> ec2-authorize default -p 22 -s 126.96.36.199/20 PERMISSION default ALLOWS tcp 22 22 FROM CIDR 188.8.131.52/20
Such a restriction makes it impossible for anyone on another network to connect to your ssh server. That is, your
ec2-authorize command instructs the firewall to drop packets not sourced on your approved network. This technique can be used to secure any service port for TCP, UDP and ICMP traffic.
If you'd like an even greater measure of security, you may restrict your port access to just one host. To do this (assuming you were using the previous firewall settings) you'd first revoke access from your original network range:
PROMPT> ec2-revoke default -p 22 -s 184.108.40.206/20 PERMISSION default ALLOWS tcp 22 22 FROM CIDR220.127.116.11/20
Then re-authorized the specific range you use, e.g.:
PROMPT> ec2-authorize default -p 22 -s 18.104.22.168/32 PERMISSION default ALLOWS tcp 22 22 FROM CIDR 22.214.171.124/32
If your network changes, you'd again need to remove this rule and replace it with the new firewall address.
Disable password-based login in favor of access via a secure shell (ssh).
Secure Shell (SSH) is a cryptographic network protocol for secure data communication, remote command-line login, remote command execution, and other secure network services between two networked computers. It connects a server and a client via a secure channel over an insecure network or unsecured network, such as the Internet.
[A brief aside: The best-known application of the protocol is for access to shell accounts on Unix-like operating systems, but it can also be used in a similar fashion for accounts on Windows.]
SSH keys are a far more secure mechanism for server access than are passwords (which can be trivially cracked by intruders). To manage your AWS instance via SSH, you'll need some form of ssh daemon or UNIX-like operating systems(http://en.wikipedia.org/wiki/Operating_system) is OpenSSH.
[Note: OpenSSH can be run on Windows platforms, though such often involves using cygwin; also, if you do not wish to use a command-line based SSH client, there are GUI alternatives such as PuTTY.]
To disable password-based access, first generate your RSA (Rivest-Shamir-Adleman) keypair and add to it to your AWS key-ring. You can do this either using the
ec2-add-keypair command to, or via the AWS console. [You will be prompted by default to create and download an RSA keypair at the time that you launch a new instance when using the AWS console.] You can also do this manually (ideally from your local machine) by running the following commands:
ssh-keygen -t rsa -C username
[Remember to “username” with the actual user name; this name will appaer as an identified at the end of your *.pub key.]
After issuing this command, you'll be prompted on where to save the keypair and what to name it. Place it somewhere you'll remember (probably
~/.ssh/) and give it a memorable name (especially if you'll be using using multiple SSH keys, otherwise the defauly is
id_rsa). You'll then be prompted to enter a key password (which I usually leave blank for convenience). When the command completes, you'll have 2 files (your key pair):
user (private key)
user.pub (public key)
You'll then need to add the public key to your user's
/.ssh/authorized_keys file. To achieve this, first you'll need to copy you public key file to a temporary place on your instance:
# scp -i root *.pub ec2-your-instance-name.compute.amazonaws.com:/tmp
Then, on the server, you can run the following commands to add the public key to your target user's account:
# cd ~user # mkdir .ssh # chmod 700 .ssh # chown user:user .ssh # cat /tmp/user.pub >> .ssh/authorized_keys # chmod 600 .ssh/authorized_keys # chown user:user .ssh/authorized_keys
The next step is to edit the server's SSH daemon configuration file, which is located at
[Caution: whenever making changes to your
sshd.config file, be certain to maintain 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.]
Disabling password log-in as accomplished by changing the line:
For the changes to take effect, save the file and restart
You will now only be able to log in with an ssh key.
[A brief aside: Good practice is for any user who you will allow to access your AWS instance to generate their own
ssh key pair (comprised of private and public) and to provide you (or the server admin) with a copy of the public key.]
Still further measures of security can be gained by giving
sudo access to select Administrative users and then disabling 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.] To do this, again edit
Find the line:
Change this line to disable root log in add an
AllowUsers entry to specify those users who you wish to allow accss:
PermitRootLogin no AllowUsers aaron someotheradmin1 someotheradmin2
Again, save the file and restart sshd:
# /etc/init.d/sshd restart
Update your system regularly.
Linux is highly dynamic. There are always new versions, patches and upgrades—many of which are issued in response to security vulnerabilities. It is vitally important to always keep your system current and up-to-date.
When deploying any EC2 instance, please keep in mind that base AMIs may have been created relatively far back in the past; it’s important to integrate the latest changes when initiating a new AMI. After deploying the instances, it’s similarly important to establish a periodic check to collect and deploy new changes. Your distribution will have a specific package manager, such as
aptitude for Ubuntu, or
pacman for ArchLinux. Be sure to run your update command regularly, e.g:
# yum update (RedHat)
# apt-get update (Ubuntu)
# pacman -Syu (ArchLinux)
This article is adapted from an early version of 'AWS: Tips for Securing Your EC2 Instance'. The content of this page has changed over time; a few articles on the web maintain content that is closer to the original. The closest one I have found to date is 'Fan0o's Blog: Tips for Securing Your EC2 Instance'. The supplimentary information I added derives from both personal experience and from the online articles hyperlinked here. The Wikipedia artile I referenced on
ssh cites some of the information concerning ssh protocols to an artcle by the Network Working Group of the IETF from January 2006 entitled The Secure Shell (SSH) Authentication Protocol, ID# RFC 4252.