最近,老是发现有很多暴力破解SSH密码的入侵者,虽然服务器密码设置的很复杂,但是对于这类骚扰者,还是及时屏蔽的好。如下有三个工具,原理很简单,就是分析/var/log/secure日志,找出IP,将其屏蔽。

  1. DenyHosts
    DenyHosts是Python语言写的一个程序,它会分析sshd的日志文件(默认是/var/log/secure),当发现重复的攻击时就会记录IP到/etc/hosts.deny文件,启用tcp_wrappers,从而达到自动屏IP的功能。 通过http://denyhosts.sourceforge.net可以下载DenyHosts的程序,可以直接下载rpm包来安装,也可以通过src.rpm包重新编译并安装等,通过这种方式默认是安装在/usr/share/denyhosts目录下。
    我是通过yum直接安装的:yum install denyhosts.noarch, 可以通过修改/etc/denyhosts.conf来更改配置。启动服务:/etc/init.d/denyhosts start

    详细信息,查看源码。

  2. Perl脚本
    #!/usr/bin/perl 
    
    # 及时封锁使用"暴入法" 入侵的使用者(SSH) 
    # 技术支援: http://www.vixual.net/ 
    
    #==相关参数== 
    
    #记录ssh 连线的LOG 档,预设: /var/log/secure 
    $log_file = "/var/log/secure"; 
    
    #于多久的时间内尝试登入(秒),预设: 1 小时 
    $time_range = 1 * 60 * 60; 
    
    #于$time_range 所设定的时间内,尝试登入失败多少次立即封锁IP,预设: 10 次 
    $drop_count = 10; 
    
    #寄件通知,预设收件者: root@localhost 
    $mail = 'root@localhost'; 
    
    #寄件程式的位置 
    $sendmail = "/usr/sbin/sendmail"; 
    
    #==== 
    
    use Time::Local; 
    
    $ip = $ARGV[0]; 
    $daemon = $ARGV[1]; 
    $count = 0; 
    
    %month = ( 
    Jan => 0, 
    Feb => 1, 
    Mar => 2, 
    Apr => 3, 
    May => 4, 
    Jun => 5, 
    Jul => 6, 
    Aug => 7, 
    Sep => 8, 
    Oct => 9, 
    Nov => 10, 
    Dec => 11 
    ); 
    
    $time = time(); 
    ($second,$minute,$hour,$day,$month,$year) = localtime($time); 
    
    #取得登入失败的 log 
    @list = `cat $log_file | grep "sshd.*Failed password.* $ip "`; 
    for(my $i = $#list; $i >= 0; $i--){ 
    #取得 log 的时间 
    my($log_month,$log_day,$log_time) = split(/ +/,$list[$i]); 
    my($log_hour,$log_minute,$log_second) = split(/:/,$log_time); 
    #前一年的记录 
    if($log_month > $month){ 
    $log_year = $year - 1; 
    }else{ 
    $log_year = $year; 
    } 
    #将时间转为秒数 
    $log_time = timelocal($log_second,$log_minute,$log_hour,$log_day,$month{$log_month},$log_year); 
    if($time < $log_time + $time_range ){ 
    $count++; 
    }else{ 
    last; 
    } 
    } 
    
    if($count > $drop_count){ 
    #封锁 IP 
    `iptables -A INPUT -p tcp -s $ip --dport 22 -j DROP`; 
    if($mail){ 
    #寄件通知 
    $hostname = `hostname`; 
    $month++; 
    $year += 1900; 
    chomp($hostname); 
    open(MAIL, "| $sendmail -t") || die "Can't open $sendmail !\n"; 
    print MAIL qq|To: $mail\n|; 
    print MAIL qq|Subject: [$hostname]封锁$ip\n|; 
    print MAIL qq|Content-Transfer-Encoding: 8bit\n|; 
    print MAIL qq|Content-type: text/plain\; charset=Big5\n\n|; 
    print MAIL "\n时间: $year-$month-$day $hour:$minute:$second\n----\n使用者\"$ip\" 尝试以SSH 登入伺服器,共失败$ count 次,已于防火墙封锁该IP。\n\n"; 
    print MAIL @list; 
    close(MAIL); 
    } 
    } 
    
    exit; 
  3. Bash shell
    
    #! /bin/bash
    # 获取前 1 分钟内的 secure 记录,统计 ssh 认证失败的 IP 和其 失败次数
    SCANNER=`grep "\`date \"+ %e %H:%M\" -d \"-1min\"\`" /var/log/secure|awk '/Failed/{print $(NF-3)}'|sort|uniq -c|awk '{print $1"="$2;}'`
    for i in $SCANNER
    do
          # 取认证失败次数
          NUM=`echo $i|awk -F= '{print $1}'`
          # 取其 IP 地址
          IP=`echo $i|awk -F= '{print $2}'`
          # 若其在失败次数超过 5 次且之前没有被阻断过,那么添加一条策略将其阻断,并记录日志
          if [ $NUM -gt 5 ] && [ -z "`iptables -vnL INPUT|grep $IP`" ]
          then
                  iptables -I INPUT -s $IP -j DROP
                  echo "`date` $IP($NUM)" >> /var/log/scanner.log
          fi
    done
    
    

发表评论

电子邮件地址不会被公开。 必填项已用*标注