TOPICS
Guides

Basic SSH Security

This tutorial introduces various methods you can use to better secure your server from unauthorized SSH logins after its initial installation.

SSH: login rate limiting and IP whitelisting

We can very easily set up rate limiting on SSH logins and restrict SSH access to certain IP addresses or ranges.

For login rate limiting, simply install the fail2ban package; on Debian/Ubuntu:

sudo apt-get install fail2ban

fail2ban will monitor failed SSH login attempts and add an iptables firewall rule to drop connections from the IP address after a few failures. This makes it very hard to perform brute force denial of service attacks targeting SSH.

For IP whitelisting, we will use the /etc/hosts.allow and /etc/hosts.deny files, which contain lists of services, along with IP addresses authorized to access those services. Since we want to implement a whitelist, we'll first block SSH connections by default in /etc/hosts.deny:

echo 'sshd: ALL' >> /etc/hosts.deny

Now, edit /etc/hosts.allow and include IP addresses that you want to be able to login from. IP prefixes, CIDR blocks, and hostnames are all supported. You can use multiple lines or commas to allow multiple sources. So the file may look something like this:

# Allow specific IP addresses
sshd: 1.2.3.4
sshd: 5.6.7.8, 6.7.8.9

# Allow 9.9.9.X and the range 10.10.10.0 to 10.10.11.255
sshd: 9.9.9.
sshd: 10.10.10.0/255.255.254.0

# Allow hostnames ending in .example.com
# sshd will first look for PTR (rDNS) record, and then validate the forward DNS record
sshd: .example.com

Updates to /etc/hosts.allow should take effect immediately. So at this point, you should test logging in from various locations and make sure your rules are working!

SSH: public key authentication

Password authentication is discouraged primarily because passwords have less entropy than randomly generated keys, and are therefore easier to brute force. Using public key authentication and disabling password authentication makes brute force attacks (almost) impossible.

Generate keypair

You'll first need to generate a pair of public/private keys on your own device. Execute the ssh-keygen command to do so. It will first prompt you for the directory to install the keys in; accepting the default is recommended (just press enter without typing anything else).

ssh-keygen will also ask you to protect your private key with a passphrase. Using this option is strongly recommended as it will encrypt the private key file so that it is only readable if the passphrase is known; this means that even if your computer is compromised, an attacker may still have a hard time decrypting the private key. You can alternatively hit enter a couple times to not set a passphrase.

Install public key on the server

Now that you have a keypair, you need to let your server know that it should accept connections based on your public key. To do this, run the ssh-copy-id command on your computer:

ssh-copy-id ubuntu@example.com

You will notice that the /home/[USERNAME]/.ssh/authorized_keys on the server will be populated with your public key. If you don't wish to run ssh-copy-id, you can also install your public key manually by copying the contents of /home/[USERNAME]/.ssh/id_rsa.pub on your computer and putting that into the authorized_keys file (which may need to be created).

Note: on Luna Node Dynamic, you can add your public key to the panel from the "SSH Keys" tab. Then, select the public key when provisioning a virtual machine to have the key automatically inserted on the administrative user.

Disable password authentication

Edit /etc/ssh/sshd_config on the server and look for this line:

#PasswordAuthentication yes

Change it to:

PasswordAuthentication no

If you didn't find any line containing "PasswordAuthentication", then just insert the PasswordAuthentication no line at the bottom of the file. Finally, reload the SSH daemon for the changes to take effect:

service ssh reload

SSH: monitor SSH logins

We can set up SSH to get e-mails when there's a new login attempt. Edit (or create) /etc/ssh/sshrc and add the following contents to the bottom (the file might not exist already):

IP=`echo $SSH_CONNECTION | cut -d " " -f 1`
echo "SSH login notification: $USER from $ip" | sendemail -q -u "SSH login notification: $USER from $ip" -f "noreply@example.com" -t "you@example.com" -s smtp.example.com &

Note: you may need to sudo apt-get install sendemail first.

The command above requires a mail server at smtp.example.com, and also to have the SSH server be authorized to relay mail via the mail server. You can adjust the sendemail command to send via a mail service like Gmail if desired:

sendemail -q -u "SSH login notification: $USER from $ip" -f "yourusername@gmail.com" -t "yourusername@gmail.com" -s smtp.gmail.com -o tls=yes -xu yourusername -xp yourpassword