Tag Archives: ssh

How-To: Thwart brute force SSH attacks in CentOS/RHEL 5

UPDATE:  This was a good exercise but I decided to replace the script with denyhosts: http://denyhosts.sourceforge.net/. In CentOS, just intall the EPEL repo first, then you can install it via yum.

This is one of the problems that my team encountered when we opened up a firewall for SSH connections. Brute force SSH attacks using botnets are just everywhere! And if you’re not careful, it’s quite a headache if one of your servers was compromised.

Lot of tips can be found in the Internet and this is the approach that I came up with based on numerous sites that I’ve read.

  1. strong passwords
    DUH! This is obvious but most people ignore it. Don’t be lazy.
  2. disable root access through SSH
    Most of the time, direct root access is not needed. Disabling it is highly recommended.

    • open /etc/ssh/sshd_config
    • enable and set this SSH config to no: PermitRootLogin no
    • restart SSH: service sshd restart
  3. limit users who can log-in through SSH
    Users who can use the SSH service can be specified. Botnets often use user names that were added by an application, so listing the users can lessen the vulnerability.

    • open /etc/ssh/sshd_config
    • enable and list the users with this SSH config: AllowUsers user1 user2 user3
    • restart SSH: service sshd restart
  4. use a script to automatically block malicious IPs
    Utilizing SSH daemon’s log file (in CentOS/RHEL, it’s in /var/log/secure), a simple script can be written that can automatically block malicious IPs using tcp_wrapper’s host.deny
    If AllowUsers is enabled, the SSH daemon will log invalid attempts in this format:
    sshd[8207]: User apache from not allowed because not listed in AllowUsers
    sshd[15398]: User ftp from not allowed because not listed in AllowUsers

    SSH also logs invalid attempts in this format:sshd[6419]: Failed password for invalid user zabbix from port 50962 ssh2Based on the information above, I came up with this script:

    # always exclude these IPs
    if [[ -e $tmp_list ]]
        rm $tmp_list
    # set the separator to new lines only
    # REGEX filter
    filter="^$(date +%b\\s*%e).+(not listed in AllowUsers|\
    Failed password.+invalid user)"
    for ip in $( pcregrep  $filter $file_log \
      | perl -ne 'if (m/from\s+([^\s]+)\s+(not|port)/) { print $1,"\n"; }' )
        if [[ $ip ]]
            echo "ALL: $ip" >> $tmp_list
    # reset
    unset IFS
    cat $file_host_deny >> $tmp_list
    sort -u $tmp_list  | pcregrep -v $exclude_ips > $file_host_deny

    I deployed the script in root’s crontab and set it to run every minute 🙂

There, of course YMMV. Always test deployments and I’m pretty sure there are a lot of other tools available 🙂