Restrict remote login to users that really need it
Why:
Less users mean less targets, obviously. Specially, root never needs SSH access. Note that disabling login by setting the login shell to /bin/false prevents only a subset of the attacks handled by this solution.
How:
Use the AllowUsers and/or AllowGroups directives. Users not covered by either directive are not allowed to log in via SSH.
Example:
AllowUsers user1 user2 user3 AllowGroups group1 group2 PermitRootLogin no
Disable password authentication
Why:
Password based authentication is inherently less secure than the public-key alternative. You can find an easy to follow comparison at Rongchaua’s blog.
How:
- If you don’t have a GPG SSH[3] key yet, you’ll have to create one. See this GPG Quick Start guide On Unix-based systems ssh-keygen will create your SSH keypair after you answer a few simple questions[1], or see this guide for PuTTY on Windows.
- Once you have the private and public keys, paste the public key into the file $HOME/.ssh/authorized_keys on the server. OpenSSH is quite picky about the permissions of files, so make sure that only you can access it (“chmod 0600 $HOME/.ssh/authorized_keys“ should be good enough).
- Make sure you can log in without entering your login password. If you disable password authentication without setting this up correctly, you can lock yourself out of the system.
- Disable password login and other unsecure login methods:
ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no
Force the usage of SSH-2
Why:
The older protocol, SSH-1 is less secure, and all modern clients support the new protocol. Using only SSH-2 in sshd is also the default in modern servers[1].
How:
Protocol 2
Use a non-standard port
Why:
Running the SSH daemon on a random port requires little effort, for a little security through obscurity decreasing the number of attackers a bit[1].
Why not:
A decent port scan will usually still find the service. It might not be worth the effort; decide for yourself.
How:
The port number should probably be below 1024, because binding to these ports require root privileges, thus reducing the risk of port hijacking. Make sure you choose a port not already associated with an application (eg. by checking that it’s not in the nmap-services file).[1]
port $PORT
You can then log in via the command-line client using the -p switch:
$ ssh -p $PORT user@host
Take this a few steps further, and we get port knocking. It’s a technique not universally accepted as a useful solution in production environments. Setting up port knocking is out of the scope of this article, but there are plenty of resources out there.
Monitoring tools
The steps outlined above make it harder for an attacker to gain access to your system. It should be noted that this is far from being a complete guide on setting up a secure server; there are whole books dedicated to the topic for a reason.
Anyway, when a bad guy manages to access your system, you want to know about it, fast. Finding out about the problem from a request to stop brute-forcing another server does not qualify as fast.
fail2ban ”scans log files like /var/log/pwdfail or /var/log/apache/error_log and bans IP that makes too many password failures. It updates firewall rules to reject the IP address.” This will stop brute-force attacks, but not DDoS attacks. Dealing with denial of service attacks is still not a completely solved issue; see this article for some of the problems and solutions.
ossec is “an Open Source Host-based Intrusion Detection System. It performs log analysis, file integrity checking, policy monitoring, rootkit detection, real-time alerting and active response.” Chances are it will pick up the side-effects of most intrusions. Be sure to configure at least the notification address where alert emails are delivered, even if you leave other options on their default.