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.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
echo 'sshd: ALL' >> /etc/hosts.deny
/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: 126.96.36.199 sshd: 188.8.131.52, 184.108.40.206 # 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
/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.
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:
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
/etc/ssh/sshd_config on the server and look for this line:
Change it to:
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 "email@example.com" -t "firstname.lastname@example.org" -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 "email@example.com" -t "firstname.lastname@example.org" -s smtp.gmail.com -o tls=yes -xu yourusername -xp yourpassword