If you run an SSH server on a machine with an internetfacing network connection, it will receive hundreds or thousands of failed login attempts every single day.
This may seem phenomenal, but if you don't believe me, look in the log files.
But apart from feeling vaguely nervous, what are you supposed to do about them? Here, we'll look at six ways to make your SSH logins more secure.
1. Choose strong passwords
As a first line of defence, strong passwords are vital. Educate yourself (and your end users, if there are any) about what makes a strong password. There's plenty of help online, but in essence you need to use passwords that are long, contain a mix of characters, punctuation and symbols, and avoid words taken straight from the dictionary.
If you have a population of users to cater for that are free to set their own passwords, consider using PAM modules such as pam_cracklib or pam_ passwdqc to enforce password strength.
2. Disable direct root login
There is a parameter called PermitRootLogin in the sshd config file that, if set to no, prevents direct root logins on the machine. This makes it harder for an attacker, because he will have to guess both an initial username and password, then crack the root password as well.
This defence is raised by default in Ubuntu, although for a different reason – the root password is locked. However, there's a small amount of inconvenience to endure for this on the client side, because you'll have to log in under a regular account first and then switch user to root to use a root login on your server.
3. Disable password-based logins
Although SSH supports several authentication mechanisms, only two are usually enabled by default – password authentication and RSA public/private key authentication. By setting PasswordAuthentication to no in the config file you'll force sshd to use RSA.
Before you do that, though, you'll need to copy your public key on to the server. This is easy enough: if you don't already have a public/private key pair, just run ssh-keygen to generate one (and set a passphrase) then use ssh-copy-id to copy the public key into your authorized_ keys file on the server.
This is a really strong solution, but you'll have to carry your private key around if you routinely log in from many different computers.
4. Run SSH on a non-standard port
You can change the port that sshd listens to by adjusting the Port parameter in the server's config file. Change it to a 'random' high port number. You will, of course, need to specify this port when you log in, for example:
$ ssh -p 22505 email@example.com
Alternatively, you can configure this on a per-host basis in the SSH config file (/etc/ssh/ssh_config).
Security purists would wish me to point out that you can't achieve total safety through obscurity. If you were determined to break in to my machine, you could easily find the port that sshd is using with an nmap port scan. But most scripted brute-force attacks on SSH will only use port 22.
I would guess (and it is just a guess) that moving SSH away from port 22 will reduce the number of break-in attempts by at least 90%. Does this make the machine secure? Not in an absolute sense. Does it reduce the risks? Yes. Nevertheless, this is probably the weakest suggestion of the lot.
5. Ban persistent offenders
I recently came across a program called fail2ban, which locks out login attempts from sites that make repeated invalid login attempts. The idea behind the program is fairly simple. It peers into your log files from time to time, (using some fancy regular expression footwork) identifies the lines that report failed login attempts and extracts the IP address of the machine that made them.
After a threshold number of failed attempts has been reached, which you can configure, fail2ban adjusts the Iptables firewall rules to block the offending IP address entirely. This ban can be permanent, or revoked after a specified time.
6. Rate-limit the connections
The idea here is to limit the rate at which any one IP address can establish new SSH connections. If this limit is exceeded, blacklist the IP address (on the assumption that it's an attacker) and subsequently DROP all connections from that IP for an hour or so. All of this can be accomplished using the Iptables recent module.
Note that this solution works entirely at the IP layer and does not distinguish successful SSH logins from failures – it simply limits the rate of attempts. There's a good discussion of this technique here.
Article continues below