Mar 17

[原]流量监控脚本 v1.1 晴

linuxing , 15:14 , 编程 » 示例 , 评论(1) , 引用(0) , 阅读(24820) , Via 本站原创 | |
    昨天,介绍了如何在网关上利用iptables实现监控各客户端IP流量的原理,并且提供了一个简单的监控脚本。今天,我继续修改完善该脚本,工作的目标是:希望可定时运行该脚本,当发现超出限定流量的客户端时,暂时终止其IP。

一、想法
我想实现的是:
引用
1、通过crontab来定时重复运行ipflow.pl脚本;
2、当发现超出限定流量的客户端时,用iptables暂时禁用对应的IP若干秒;
3、考虑到crontab运行的时间和禁止用户的时间可能不相同,采用两个脚本;
4、禁止用户的脚本需要等待若干秒,应放在后台运行。

二、脚本
1、ipflow.pl脚本
改动原ipflow.pl脚本,内容如下:

#!/usr/bin/perl -w
# Date:2009-03-12
# Author:HyphenWang
# Version:1.1
use strict;
my $IPTABLES_CMD="/sbin/iptables -v -n -x -L FORWARD";
my $BANIP_CMD="/root/banip.sh"; #定义禁止客户端IP的脚本路径
my $SEC="3"; #定义监控时收集数据的间隔时间,取平均值
my $ZERO="0"; #定义是否输出没有流量的客户端信息
my $BANIP="1"; #定义是否启用禁止IP的功能
my $BANSEC="60"; #定义禁止时间
my $limit_input_rate=150; #定义限定的下载流量
my $limit_output_rate=20; #定义限定的上传流量
my @exclude_ip=qw(30 153 155 200 221); #定义排除列表,表中的IP被排除在禁用范围外
my (%first_input,%first_output);
my (%second_input,%second_output);
my (%ban_ip,$input_rate,$output_rate);

#定义收集流量的函数
sub get_ipflow {
  my ($ip_input,$ip_output)=@_;
  for my $line (`$IPTABLES_CMD`) {
    my @columns = split(/\s+/,$line);
    $ip_input->{$columns[-1]}=$columns[2] if ($columns[3] eq "ACCEPT" and $columns[-1] =~ m/192\.168\.228\.\d+/);
    $ip_output->{$columns[-2]}=$columns[2] if ($columns[3] eq "ACCEPT" and $columns[-2] =~ m/192\.168\.228\.\d+/);
    $ban_ip{$columns[-1]}=1 if ($columns[3] eq "DROP" and $columns[-1] =~ m/192\.168\.228\.\d+/);
    $ban_ip{$columns[-2]}=1 if ($columns[3] eq "DROP" and $columns[-2] =~ m/192\.168\.228\.\d+/);
  }
}
get_ipflow(\%first_input,\%first_output);
sleep $SEC;
get_ipflow(\%second_input,\%second_output);

#开始输出
print "Now is ".localtime()."\n";
print "-"x53,"\n";
print "IP Address\t\tIn Flow Rate\tOut Flow Rate\n";
for my $ip (keys %first_input) {
  if ($ZERO != 1) {
    if (defined $second_input{$ip} and defined $second_output{$ip} and int(($second_input{$ip}-$first_input{$ip})/1024/$SEC) == 0) {
      next;
    }
  }
  if (defined $second_input{$ip} and defined $second_output{$ip}) {
    $input_rate = ($second_input{$ip}-$first_input{$ip})/1024/$SEC;
    $output_rate = ($second_output{$ip}-$first_output{$ip})/1024/$SEC;
    printf ("%s\t\t%.f KByte/s\t%.f KByte/s\n",$ip,$input_rate,$output_rate);
    #禁用超出流量的IP
    if ($BANIP == 1 and $input_rate >= $limit_input_rate and ! grep ("192.168.228.$_" eq $ip,@exclude_ip)) {
      #传递给禁用脚本,并放到后台运行,而不会影响当前脚本的继续运行
      system ("$BANIP_CMD INPUT $ip $BANSEC &");
      #被禁用的IP当然需要在最后的Banned IP Address栏显示出来
      $ban_ip{$ip}=1;
    }
    if ($BANIP == 1 and $output_rate >= $limit_output_rate and ! grep ("192.168.228.$_" eq $ip,@exclude_ip)) {
      system ("$BANIP_CMD OUTPUT $ip $BANSEC &");
      $ban_ip{$ip}=1;
    }
  }
}
print "-"x53,"\n";
print "Banned IP Address:\n";
for (keys %ban_ip) {
  print "$_\n";
}

2、banip.sh脚本
这个脚本是用于接收来自ipflow.pl的信息,然后禁用对应的IP的:

#!/bin/bash
SEC="$3";
IPTABLES="/sbin/iptables"
case $1 in
"INPUT")
  $IPTABLES -I FORWARD -d $2 -j DROP
;;
"OUTPUT")
  $IPTABLES -I FORWARD -s $2 -j DROP
;;
esac
sleep $SEC;
case $1 in
"INPUT")
  $IPTABLES -D FORWARD -d $2 -j DROP
;;
"OUTPUT")
  $IPTABLES -D FORWARD -s $2 -j DROP
;;
esac
exit 0

※ 虽然我这里定义了下载和上传使用不同的命令,实际上效果是相同的——禁用那一个方向,所有流量都不能通过。我这样写,仅是为了今后统计客户端信息而考虑。
另外,正如之前所说的,不通过网关nat转发的流量是不会计算在FORWARD表中,而是在INPUT/OUTPUT表。所以,这脚本不会影响直接访问网关的流量。

本地下载:

三、定时运行
把脚本写入crontab中,让其自动运行:
引用
# crontab -l
*/1 * * * * /root/ipflow.pl
Tags:
sxq5858
2009/08/22 08:45
你好,运行这个ipflow.pl,怎么没有数据呢,,我是centos 5.3


[root@route home]# ./ipflow.pl
Now is Sat Aug 22 08:43:05 2009
-----------------------------------------------------
IP Address              In Flow Rate    Out Flow Rate
-----------------------------------------------------
linuxing 回复于 2009/08/24 18:03
这个脚本使用的前提是,需要配合iptables配置的。我当初先这个脚本,是用在网关上,若用于本机,这需要根据实际情况修改iptables的设定。请看文章开头和前几篇的日志。
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]