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 125.5.112.165 not allowed because not listed in AllowUsers
    sshd[15398]: User ftp from 222.169.11.13 not allowed because not listed in AllowUsers

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

    #!/bin/bash
    
    # always exclude these IPs
    exclude_ips='192.168.60.1|192.168.60.10'
    
    file_log='/var/log/secure'
    file_host_deny='/etc/hosts.deny'
    
    tmp_list='/tmp/ips.for.restriction'
    
    if [[ -e $tmp_list ]]
    then
        rm $tmp_list
    fi
    
    # set the separator to new lines only
    IFS=$'\n'
    
    # 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"; }' )
    do
        if [[ $ip ]]
        then
            echo "ALL: $ip" >> $tmp_list
        fi
    done
    
    # 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🙂

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

    1. tar Post author

      that could work, but unfortunately, we have a lot of scripts using ssh with it’s default port, so it’s not an option for us.

      Reply
    1. tar Post author

      Thanks! We’re planning a transition to use ssh keys instead of passwords, hopefully that will harden our boxes better.

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s