Remember to mitigate brute-force SSH attacks

SSH is the ubiquitous way of working with networked computers. And it is beyond belief, how many people try to break into systems via ssh. You haven’t taken actions to turn ssh attacks into a game of diminishing returns? Its about time to change that.

Brute-forcing Secure shell access is an attractive undertaking for some people, because they could potentially take over an entire network, distribute malware and/or misuse resources for other malicious activities.

Here is a short introduction to counter-measures that have proven effective for me in the past:

  1. Rate-limit request bursts
  2. Implement strict access rules
  3. Remember evil hosts and deny subsequent access

Also, it is a good idea to put ssh to another port number. You could then drop packets on port 22 altogether, or setup a honeypot, instead.

Rate-limit requests

The --recent iptables extension is extremely useful to keep track of requests to the ssh daemon and block excessive requests.

$ iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH --rsource  --mask
$ iptables -A INPUT -p tcp -m tcp --dport 22 -m recent --update --seconds 60 --hitcount 10 --rttl --mask --name SSH --rsource -j DROP

This firewall rule permits at most 10 new connections from a C-Class IP subnet within a one minute time frame. Note: Change --dport 22 if ssh listens on another port.

Its worthwhile to experiment with the time interval and hit counter. You can check suspects by looking at /proc/net/xt_recent/SSH. You’ll be amazed by how fast the list entries pile up.

Careful: While this first line of defense can be very effective, it is also very easy to quickly exclude one self from access. These firewall rules do not know whether or not an otherwise legit user has been blocked.

Apply restrictive access control

The ssh daemon ships with sensible defaults already, but there are some settings we’ll want to enforce:

Its debatable, if disabling root access increases security. I’d like to think of it as an additional security measure, not as the only one. To only permit specific users or groups remote access goes hand in hand.

Disabling any form of password authentication is a huge win. The only possible way of successfully authenticating is by means of a valid public key. Managing access by user or group this way is straight forward and transparent. If in doubt, here is an excellent primer on ssh public key authentication.

Lastly, any authentication failure will be logged immediately, which comes in handy once we use a log-analyzer in the next step.

Open up your favorite editor on the host in /etc/ssh/sshd_config:

# ... other settings

PermitRootLogin no
# obviously, you should modify the next 2 lines
AllowUsers bob alice
AllowGroups devs admins
MaxAuthTries 2
PermitEmptyPasswords no
PasswordAuthentication no
ChallengeResponseAuthentication no
# Disable unless using Kerberos / GSSAPI, enable if you need these services
GSSAPIAuthentication no
KerberosAuthentication no

# ... other settings, cont.

Above settings will only permit user ‘alice’ and ‘bob’, or users from the groups ‘devs’ and ‘admin’, to login by providing a known public key.

Careful: Make sure you can connect with your public key, before restarting SSH. Otherwise you have locked yourself out and must fallback to having physical access to the machine in question.

SSH has many more interesting access control options. Kudos for reading what man sshd_config has to offer!

Block known bad hosts

DenyHosts is a Python script that analyzes sshd server log messages to determine which hosts are attempting to hack into your system. By default, it will add known bad hosts to the /etc/hosts.deny file and prevent further access.

Another option is fail2ban which goes a step further and can be configured to monitor different service log files and update firewall rules to reject ip addresses.

I personally prefer DenyHosts. Its easy to setup, comes with good defaults, and has a nice synchronization feature with which its possible to up- or download lists of suspicious hosts.

All countermeasures outlined above will only limit the attack surface, not eliminate the threat entirely. Nonetheless, most automated attempts can be countered and some attackers may even give up.

If anything, hopefully, this post helped elevate your awareness level. Securing a system for the event of a breach is an entirely different topic.