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