LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2773|回复: 0

proftpd log 文件实时分析,动态封禁/解封

[复制链接]
发表于 2003-12-25 09:10:20 | 显示全部楼层 |阅读模式
请问下面这段程序怎实现?能告诉我实现的步骤吗?谢谢。
# proftpd log 文件实时分析,动态封禁/解封
# 用法:
#       tail -f /var/log/proftpd | /usr/bin/proftpdeny.pl
#
#
use Time::HiRes qw(gettimeofday);

# 封禁时间,以秒为单位
$DENY_PERIOD=600;            
# 对最近多久的日志进行统计
$EVAL_PERIOD=60;

# 在 EVAL_PERIOD 中的最多连接次数
$DENY_TIMES=5;

# 数组,记录 IP/最后登陆时间/重试次数
%BADLIST = ();
%DENIED_IP = ();

init_iptables();

while (<STDIN>){
        chomp $_;
        $line = $_;

        $badip = get_bad_ip($line) ;

        if (! $badip ) {              
         next;
        }

#print STDERR "badip: $badip\n";

        # 删除 BADLIST 中的过期 IP
        refresh_bad_ip();

        # 添加multi login的ip到BADLIST
        add_bad_ip( $badip );

        # 把平均每秒连接次数 > $DENY_RETRY_TIMES_PER_SEC 的 IP 封掉
        check_bad_ip();

        # 将封禁时间 > $DENY_PERIOD 的ip解封
        undeny_bad_ip();
}

exit(0);

##############################
sub get_bad_ip                        
{
        local( $line );
        $line = $_[0];
        return undef if ( ! $line );

        if ( $line =~ /ftp\.zixia\.net \((\d+\.\d+\.\d+\.\d+)\[[^\]]+\]\) -
Connection refused \(max clients per host \d+\)\./ ) {
                return $1;
        } else {
                return undef;
        }
}

sub add_bad_ip
{
        local ( $badip );
        $badip = $_[0];
        die "add_bad_ip() take no param err" unless $badip;

        ($seconds, $microseconds) = gettimeofday;

        $BADLIST{$badip}{$seconds . '.' . $microseconds} = 1;  
#print STDERR "add_bad_ip: $badip, $seconds\n";
}

sub refresh_bad_ip
{
        foreach $ip ( keys %BADLIST ){
                foreach $secmic ( keys %{$BADLIST{$ip}} ){
                        if ( $secmic =~ /^(\d+)\.(\d+)$/ ){
                                $seconds = $1;

                                if ( time - $seconds > $EVAL_PERIOD ){
                                        delete $BADLIST{$ip}{$secmic} ;
#print STDERR "refresh_bad_ip: delete badlist $ip $secmic\n";
                                }
                        }
                }
                $num = keys %{$BADLIST{$ip}};
                if ( 0==$num ) {
                        delete $BADLIST{$ip};
                }
        }                                          
}

sub check_bad_ip
{
        foreach $ip ( keys %BADLIST ){
                $login_num = keys ( %{$BADLIST{$ip}} );

#print STDERR "check_bad_ip: ip $ip has $login_num times login attampts..\n";


                if ( $login_num > $DENY_TIMES ) {
                        deny_bad_ip ( $ip ) ;
                        delete $BADLIST{$ip};
                }
        }
}

sub deny_bad_ip
{
        local $ip;
        $ip = $_[0];
                        
    die "deny_bad_ip no ip err" unless $ip;

        foreach ( keys %DENIED_IP ){
                return if ( /^$ip$/ )
        }

        $cmd = "iptables -A ftpDeny -p tcp -s $ip -j REJECT --reject-with
tcp-reset";
#print STDERR "sys cmd: $cmd\n";
        system ( $cmd );
        $DENIED_IP{$ip} = time;

        $date = `date`;#把当前日期赋值给$date
        chomp $date;#截去\n,这里也可以这样,chomp($date);
        system ( "printf \"%s %-16s denied.\n\" \"$date\" $ip >>/var/log/proft
pd.deny" )
}

sub undeny_bad_ip
{
        foreach $ip ( keys %DENIED_IP ){
                if ( time - $DENIED_IP{$ip} > $DENY_PERIOD ) {  
$line_number = `iptables -nL ftpDeny --line-number |
grep $ip | awk {'print \$1'}`;
                        chomp $line_number;
                        $cmd = "iptables -D ftpDeny $line_number";

                        system ( $cmd );
                        delete $DENIED_IP{$ip};

                        $date = `date`; #把当前日期赋值给$date
                        chomp $date; #截去\n
                        system ( "printf \"%s %-16s undenied.\n\" \"$date\"
$ip >>/var/log/proftpd.deny" )

                }
        }
}

sub init_iptables
{
        $cmd1 = "iptables -F ftpDeny > /dev/null 2>&1";
        $cmd2 = "iptables -X ftpDeny > /dev/null 2>&1";
        $cmd3 = "iptables -N ftpDeny > /dev/null 2>&1";     
        $cmd4 = "iptables -I INPUT -p tcp --dport 59000:60000 -j ftpDeny";
        $cmd5 = "iptables -I INPUT -p tcp --dport 20:21 -j ftpDeny";

        $exist = `iptables -nL INPUT | grep ftpDeny | wc -l | awk {'print \$1'}`;


        system( $cmd1 );
        system( $cmd2 );
        system( $cmd3 );

        if ( 0==$exist ) {
                system( $cmd4 ) ;
                system( $cmd5 ) ;
        }
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表