• 沒有找到結果。

第四章 系統實作

4.3 心得感想

早先嘗試開始實做的時候是都使用交大 Netflow 文件所說的方式來 做,由於找不到學長可以問,許多都是自己懵懵懂懂在跌跌撞撞中一 直嘗試,差不多將交大 Netflow 文件所說的系統架起來之時,卻發生不 小心將檔案都刪除的意外,於是所有都歸零。同時間有再另外搜尋與 Netflow 相關的文章,發現在國外有個 Flow-Tools 可以拿來使用,經過 裝起來時使用之後發現 Flow-Tools 的效能比起交大 Netflow 文件所提 供的收集程式好,交大 Netflow 提供的收集程式會持續讓 CPU Loading 在 100%,早先以為是所使用的機器等級太差(Pentium-166),經過換上 Flow-Tools 之後發現 CPU Loading 大大降低,且其輸出格式也與交大 Netflow 文件使用的格式類似,於是便採用新的收集程式來做。

有了新的收集程式之後便開始重新再架過一次系統,由於早先實驗 用收集的流量資訊為逢甲大學校園網路對外骨幹中的一小部分,且其 流量大都是流出,這個缺點讓我無法確定自己的程式執行結果是否有 架設成功。在詢問系統維運組余組長之後,余組長答應使用較好的 PC(Pentium3-1G) 來 實 作 且 收 集 的 流 量 資 訊 來 源 為 校 內 工 學 院 的 Router(Cisco Catalyst 5500),從這台機器的流入流出很明顯可以看出差 異,在經過一段時間的嘗試之後,便開始參考交大 Netflow 文件裏的分

在經過一段時間的摸索與測試及改進之後,整個系統的運作算大致 上 OK,接下來所要作的就是將運算後資料作儲存及呈現,於是有了放 在資料庫裡的想法,藉由 PHP 與 MySQL 的結合讓我可以對網頁的呈 現做很大的彈性,也做出之前沒想到的功能。

後來指導老師建議應該有個圖表來表示各流量之間的關係圖會更 好。於是便開始找尋如何去使用 PHP 畫圓餅圖,發現 GD 是在 PHP 上 畫圖唯一的選擇,雖然知道 GD 在畫圖方面的能力很強,但是使用上 太過複雜。後來在 http://www.silisoftware.com/找到 phPie()這 個 php script,終於解決了困擾我許久關於如何畫圓餅圖的問題。

自從網站架構越來越完整,細部的需求也一值增加,實作期間也碰 過好幾次病毒流行,如開學病毒潮及最近的 Sasser 病毒肆虐,驗證本 系統可以對於異常行為的 IP 作有效的觀察,進而可以提供網管人員去 做處理,實在很欣慰,辛苦做的專題可以派上用場真的很高興。

參考資料

[1]Jon Orwant, Perl 5 Interactive Course, The Waite Group,Inc 1996 [2] Schwartz, Christiansen, Learning Perl, 2/e, O’REILLY 1999

[3]劉國正,林景毅,PHP4 入門實務手冊,松崗電腦圖書資料股份有限公 司,2000

[4]陳俊宏,PHP4 網站實作-深度研究篇,旗標出版股份有限公司,2000 [5]位元文化編著,PHP4+MySQL4 動態網頁入門實務,文魁資訊股份有 限公司,2002

參考網址

[1] Flow-Tools

http://www.splintered.net/sw/flow-tools/

[2] How to install and configure DBD::mysql

http://search.cpan.org/src/JWIED/DBD-mysql-2.1026/INSTALL.html

[3]交大 Netflow 文件

http://netflow.nctu.edu.tw/netflow.html

[4]如何建置 Netflow

http://www.tn.edu.tw/sammy/netflow/setup.htm

[5] NetFlow Services Solutions Guide

http://www.cisco.com/univercd/cc/td/doc/cisintwk/intsolns/netflsol/nfw hite.htm

[6] NetflowExporter Project

http://sunsite.cc.ncu.edu.tw/NetflowExporter/

[7]phPie php sript

http://www.silisoftware.com/scripts/index.php?scriptname=phPie

[8]Perl Doc

http://www.perldoc.com/

[9]PHP5 網管實驗室

http://www.perldoc.com/

[10]網站建置百寶箱

http://dob.tnc.edu.tw/

程式碼

$dbh = DBI->connect($dsn, $user, $password);

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time-86400);

$mon++;

$year+=1900;

#format date to 2-digit. Ex: 2 -> 02

$mon = sprintf("%02d",$mon);

$mday = sprintf("%02d",$mday);

#setting up path

$rawdir = "/netflow";

$flowprint = "/usr/local/netflow/bin/flow-print";

$dir = "/netflow/prog";

$outputdir = "/netflow/log";

$protfile = "$dir/protocols";

$servfile = "$dir/services";

$tablename = "ff$year$mon$mday";

@gotfilename = `ls $rawdir/ft- v05.$year-$mon-$mday.*`;

$starttime = localtime();

&init_prot($protfile);

&init_serv($servfile);

$dbh->do("DROP TABLE IF EXISTS `$tablename`");

#create tables

&createdb;

for ($i=0;$i<scalar @gotfilena me;$i++) {

$processtime = localtime();

chomp @gotfilename[$i];

printf LOG "NOW %3s %45s AT %20s\n",$i,@gotfilename[$i],$processtime;

open FLOWDATA, "$flowprint - f0 < @gotfilename[$i] |" || die $!;

while (<FLOWDATA>) { chomp;

$size /= 1048576; #(1024*1024);

&checkinout;

} }

#================

$insertdbtime = localtime();

print LOG "Start insert data to DB at $insertdbtime\n";

&insertdata;

&dailysizetotal;

#execute other perl program do "$dir/ipdeny.pl";

do "$dir/flowchart.pl";

$dbh->disconnect();

$endtime = localtime();

print LOG "start :: $starttime\n";

print LOG "end :: $endtime\n";

sub insertdata { my($i,$j);

$i = 0;

$j = 0;

$k = 0;

@sorted_hash = sort keys %iplist;

$length = scalar @sorted_hash;

$tablelistlength = scalar @tablelist;

for ($ipno;$ipno<$length;$ipno++){

for ($j=0;$j<$tablelistlength;$j++){

$tt = ${@tablefield[$j]}{@sorted_hash[$ipno]};

@value[$j] = "\"$tt\"\,";

}

chop @value[$j-1];

$dbh->do("INSERT INTO $tablename(ip\,@tablefield1) VALUES(\"@sorted_hash[$ipno]\",@value)");

}else {

sub checkinout {

if ( isInNet($src) && !isInNet($dst) ){

$iplist{$src}= "$src";

&update("FCU","OUT");

}

elsif ( !isInNet($src) && isInNet($dst) ){

$iplist{$dst}= "$dst";

&update("FCU","IN");

} }

sub update{

my($net,$io) = @_;

if ($proto == '06' || $proto == '11') { if ($service{"$sp"}) {

$port = $sp;

}

elsif ($service{"$dp"}) {

$port = $dp;

} else {

$port = "others";

} }

elsif ($proto == 01) {

$port = "icmp";

}

if ($io eq "IN"){

# my($a, $b, $c, $d) = split(/\./,"$src");

# $src = sprintf("%d.%d.%d", $a, $b, $c);

# ${$net.$io.SRC.$port.FLOWC}{"$src"} ++;

# ${$net.$io.SRC.$port.PKTSC}{"$src"} += $pkts;

# ${$net.$io.SRC.$port.SIZEC}{"$src"} += $size;

${$net.$io.DST.$port.FLOW}{"$dst"} ++;

${$net.$io.DST.$port.PKTS}{"$dst"} += $pkts;

${$net.$io.DST.$port.SIZE}{"$dst"} += $size;

${$net.$io.DST.total.FLOW}{"$dst"} ++;

${$net.$io.DST.total.PKTS}{"$dst"} += $pkts;

${$net.$io.DST.total.SIZE}{"$dst"} += $size;

} else {

# my($a, $b, $c, $d) = split(/\./,"$dst");

# $dst = sprintf("%d.%d.%d", $a, $b, $c);

${$net.$io.SRC.$port.FLOW}{"$src"} ++;

${$net.$io.SRC.$port.PKTS}{"$src"} += $pkts;

${$net.$io.SRC.$port.SIZE}{"$src"} += $size;

${$net.$io.SRC.total.FLOW}{"$src"} ++;

${$net.$io.SRC.total.PKTS}{"$src"} += $pkts;

${$net.$io.SRC.total.SIZE}{"$src"} += $size;

# ${$net.$io.DST.$port.FLOWC}{"$dst"} ++;

# ${$net.$io.DST.$port.PKTSC}{"$dst"} += $pkts;

# ${$net.$io.DST.$port.SIZEC}{"$dst"} += $size;

} }

sub init_prot { my($file) = @_;

open (FN,$file) || die $!;

while(<FN>){

my($name,$proto) = split;

$protocol{"$proto"} = $name;

} }

sub init_serv {

while (<FN>){

my($name,$port) = split;

$service{"$port"} = $name;

}

$service{"total"} = "total";

$service{"others"} = "others";

$service{"icmp"} = "icmp";

}

sub createdb {

my($net,$io,$sd,$port,$ip,$i,$j);

$i = 0;

foreach $net ("FCU"){

foreach $io ("IN","OUT"){

foreach $sd ("SRC","DST"){

foreach $port (keys(%service)) {

foreach $fps ("FLOW", "PKTS", "SIZE") {

@tablefield[$i] = sprintf("$net$io$sd$port$fps");

if (($io eq "IN" && $sd eq "DST") || ($io eq "OUT" && $sd eq "SRC")) {

@tablelist[$i] = sprintf("$net$io$fps$service{$port} DOUBLE(8,1) NOT NULL,");

@tablefield1[$i] = sprintf("$net$io$fps$service{$port} \,");

$i++;

chop @tablefield1[$i-1];

$create = sprintf("CREATE TABLE $tablename(ip char (15) NOT NULL,@tablelist)TYPE=MyISAM");

$dbh ->do($create);

}

sub dailysizetotal {

my($insize,$outsize,$totalsize);

$sth = $dbh->prepare("SELECT

sum(fcuinsizetotal),sum(fcuoutsizetotal),sum(fcuinsizetotal)+sum(fcuoutsizetotal) FROM $tablename");

$sth->execute();

while(($insize ,$outsize ,$totalsize) = $sth->fetchrow_array()) {

$dbh->do("insert into DailyTotalSize(date,insize,outsize,totalsize) values('$year$mon$mday','$insize','$outsize','$totalsize') ");

}

$dbh = DBI->connect($dsn, $user, $password);

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time-600);

$mon++;

$year+=1900;

$nowtime = (time+60*60*8)%86400;

$suffix = ($nowtime-(86400/144))/(86400/144)%6;

if ($min >= 0 && $min <= 9 ){

$suffix = 0;

}

$mon = sprintf("%02d",$mon);

$mday = sprintf("%02d",$mday);

$hour = sprintf("%02d",$hour);

$rawdir = "/netflow";

$flowprint = "/usr/local/netflow/bin/flow-print";

$dir = "/netflow/prog";

$outputdir = "/netflow/log";

$protfile = "$dir/protocols";

$servfile = "$dir/services";

$ipfile = "$dir/iplist";

$tablename = "virus";

$sth = $dbh->prepare("SELECT

`icmp`,`445`,`59a`,`87`,`codered`,`nimda`,`netsky`,`smtp`,`netbios` FROM virus_cont");

$sth->execute();

($cont_icmp,$cont_445,$cont_59a,$cont_87,$cont_codered,$cont_nimda,$cont_netsky,

$cont_smtp,$cont_netbios) = $sth->fetchrow_array();

$sth->finish();

$filename = sprintf("ft- v05.%02d-%02d-%02d.%02d%d*", $year, $mon, $mday, $hour,

$suffix);

@gotfilename = `ls $rawdir/$filename`;

open LOG, ">$outputdir/abnormal.$mon$mday$hour-$suffix" or die $!;

$starttime = localtime();

&init_prot($protfile);

&init_serv($servfile);

for ($i=0;$i<scalar @gotfilename;$i++) {

$processtime = localtime();

chomp @gotfilename[$i];

printf LOG "NOW %3s %45s AT %20s\n",$i,@gotfilename[$i],$processtime;

open FLOWDATA, "$flowprint - f0 < @gotfilename[$i] |" || die $!;

while (<FLOWDATA>) { chomp;

$sif = substr($_, 0, index($_, ' ', 0));

$src = substr($_, 5, index($_, ' ', 5) - 5);

$dif = substr($_, 22, index($_, ' ', 22) - 22);

$insertdbtime = localtime();

#$dbh->do("DROP TABLE IF EXISTS `$tablename`");

#&createtable;

#&expire;

&out;

$dbh->disconnect();

print LOG "10 min total flow count $totalflow10min\n";

$endtime = localtime();

print LOG "start :: $starttime\n";

print LOG "end :: $endtime\n";

close LOG;

my ($expired,$mon,$mday,$hour,$min,$year);

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time-3600);

$mon++;

$year+=1900;

$year = sprintf("%02d",$year%100);

$mon = sprintf("%02d",$mon);

$mday = sprintf("%02d",$mday);

$hour = sprintf("%02d",$hour);

$min = sprintf("%02d",$min);

print "$year$mon$mday$hour$min\n";

$expired = sprintf("$year$mon$mday$hour$min");

$dbh->do("delete from virus where date < \'$expired\'");

}

sub abnormal{

if (isInNet($src)) {

$flow_cont{$src}++;

$flow_cont_pkts{$src} += $pkts;

$flow_cont_size{$src} += $size;

}

if ( $proto == 01 && $sp == 0 && $dp == 800){

$abnormal_cont_icmp_flow{$src}++;

$abnormal_cont_icmp_pkts{$src} += $pkts;

$abnormal_cont_icmp_size{$src} += $size;

}

if ( $proto == '06' && $dp == '1bd') {

$abnormal_cont_445_flow{$src}++;

$abnormal_cont_445_pkts{$src} += $pkts;

$abnormal_cont_445_size{$src} += $size;

}

if ( $proto == '11' && $dp == '59a') {

$abnormal_cont_59a_flow{$src}++;

$abnormal_cont_59a_pkts{$src} += $pkts;

$abnormal_cont_59a_size{$src} += $size;

}

if ( $proto == '06' && $dp == '87' && $pkts == '1' && $size =='48') {

$abnormal_cont_87_flow{$src}++;

$abnormal_cont_87_pkts{$src} += $pkts;

$abnormal_cont_87_size{$src} += $size;

}

if ( $dp == '50' && $pkts == '3' && $size == '144') {

$abnormal_cont_codered_flow{$src}++;

$abnormal_cont_codered_pkts{$src} += $pkts;

$abnormal_cont_codered_size{$src} += $size;

}

if ( $dp == '50' ) {

$abnormal_cont_nimda_flow{$src}++;

$abnormal_cont_nimda_pkts{$src} += $pkts;

$abnormal_cont_nimda_size{$src} += $size;

}

if ( $dp == '19' && $pkts == '2' && $size == '96') {

$abnormal_cont_netsky_flow{$src}++;

$abnormal_cont_netsky_pkts{$src} += $pkts;

$abnormal_cont_netsky_size{$src} += $size;

}

if ( $dp == '19') {

$abnormal_cont_smtp_flow{$src}++;

$abnormal_cont_smtp_pkts{$src} += $pkts;

$abnormal_cont_smtp_size{$src} += $size;

}

if ( $dp == '8b' && $pkts == '1' && $size == '48') {

$abnormal_cont_netbios_flow{$src}++;

$abnormal_cont_netbios_pkts{$src} += $pkts;

$abnormal_cont_netbios_size{$src} += $size;

} }

sub out { my($src);

foreach $src(keys %flow_cont){

much\n",$src,$flow_cont{$src});

$dbh->do("INSERT INTO

$tablename(ip\,flow\,pkts\,size\,kind\,10minoutflow\,10minoutpkts\,10minoutsize)

foreach $src(keys %abnormal_cont_icmp_flow){

if ($abno rmal_cont_icmp_flow{$src} > $cont_icmp){

printf LOG ("on %18s occur %8s times icmp(dst:2048) pkts %10d,size

%5.2f\n",$src,$abnormal_cont_icmp_flow{$src},$abnormal_cont_icmp_pkts{$src},$a bnormal_cont_icmp_size{$src});

$dbh->do("INSERT INTO

$tablename(ip\,flow\,pkts\,size\,kind\,10minoutflow\,10minoutpkts\,10minoutsize)

foreach $src(keys %abnormal_cont_445_flow){

if ($abnormal_cont_445_flow{$src} > $cont_445){

printf LOG ("on %18s occur %8s times 445 port(1bd) pkts %10d,size

%5.2f\n",$src,$abnormal_cont_445_flow{$src},$abnormal_cont_445_pkts{$src},$abn ormal_cont_445_size{$src});

$dbh->do("INSERT INTO

$tablename(ip\,flow\,pkts\,size\,kind\,10minoutflow\,10minoutpkts\,10minoutsize)

foreach $src(keys %abnormal_cont_59a_flow){

if ($abnormal_cont_59a_flow{$src} > $cont_59a){

printf LOG ("on %18s occur %8s times 1434 port(59a) pkts %10d,size

%5.2f\n",$src,$abnormal_cont_59a_flow{$src},$abnormal_cont_59a_pkts{$src},$abno rmal_cont_59a_size{$src});

$dbh->do("INSERT INTO

foreach $src(keys %abnormal_cont_87_flow){

if ($abno rmal_cont_87_flow{$src} > $cont_87){

printf LOG ("on %18s occur %8s times 135 port(87) pkts %10d,size

%5.2f\n",$src,$abnormal_cont_87_flow{$src},$abnormal_cont_87_pkts{$src},$abnor mal_cont_87_size{$src});

$dbh->do("INSERT INTO

$tablename(ip\,flow\,pkts\,size\,kind\,10minoutflow\,10minoutpkts\,10minoutsize)

foreach $src(keys %abnormal_cont_codered_flow){

if ($abnormal_cont_codered_flow{$src} > $cont_codered){

printf LOG ("on %18s occur %8s times CodeRed pkts %10d,size

%5.2f\n",$src,$abnormal_cont_codered_flow{$src},$abnormal_cont_codered_pkts{$sr c},$abnormal_cont_codered_size{$src});

$dbh->do("INSERT INTO

$tablename(ip\,flow\,pkts\,size\,kind\,10minoutflow\,10minoutpkts\,10minoutsize)

foreach $src(keys %abnormal_cont_nimda_flow){

if ($abnormal_cont_nimda_flow{$src} > $cont_nimda){

printf LOG ("on %18s occur %8s times Nimda pkts %10d,size

%5.2f\n",$src,$abnormal_cont_nimda_flow{$src},$abnormal_cont_nimda_pkts{$src},

$abnormal_cont_nimda_size{$src});

VALUES(\'$src\'\,\'$abnormal_cont_nimda_flow{$src}\'\,\'$abnormal_cont_nimda_pkts {$src}\'\,\'$abnormal_cont_nimda_size{$src}\'\,\'Nimda\'\,\'$flow_cont{$src}\'\,\'$flow_

cont_pkts{$src}\'\,\'$flow_cont_size{$src}\')");

} }

foreach $src(keys %abnormal_cont_netsky_flow){

if ($abnormal_cont_netsky_flow{$src} > $cont_netsky){

printf LOG ("on %18s occur %8s times NetSky pkts %10d,size

%5.2f\n",$src,$abnormal_cont_netsky_flow{$src},$abnormal_cont_netsky_pkts{$src},

$abnormal_cont_netsky_size{$src});

$dbh->do("INSERT INTO

$tablename(ip\,flow\,pkts\,size\,kind\,10minoutflow\,10minoutpkts\,10minoutsize)

foreach $src(keys %abnormal_cont_smtp_flow){

if ($abnormal_cont_smtp_flow{$src} > $cont_smtp){

printf LOG ("on %18s occur %8s times Smtp pkts %10d,size

%5.2f\n",$src,$abnormal_cont_smtp_flow{$src},$abnormal_cont_smtp_pkts{$src},$ab normal_cont_smtp_size{$src});

$dbh->do("INSERT INTO

$tablename(ip\,flow\,pkts\,size\,kind\,10minoutflow\,10minoutpkts\,10minoutsize)

foreach $src(keys %abnormal_cont_netbios_flow){

if ($abnormal_cont_netbios_flow{$src} > $cont_netbios){

ts{$src}\'\,\'$abnormal_cont_netbios_size{$src}\'\,\'NetbiosScan\'\,\'$flow_cont{$src}\'\,

\'$flow_cont_pkts{$src}\'\,\'$flow_cont_size{$src}\')");

} } }

sub createtable {

$dbh->do("CREATE TABLE `virus` (`date` TIMESTAMP (10) DEFAULT '0', `ip`

CHAR (15) DEFAULT '0' NOT NULL, `flow` MEDIUMINT (8) UNSIGNED

DEFAULT '0' NOT NULL, `pkts` MEDIUMINT (8) UNSIGNED DEFAULT '0' NOT NULL, `size` DOUBLE (8,1) DEFAULT '0' NOT NULL, `kind` CHAR (10) DEFAULT '0' NOT NULL) TYPE = MyISAM");

sub init_prot { my($file) = @_;

open (FN,$file) || die $!;

while(<FN>){

my($name,$proto) = split;

$protocol{"$proto"} = $name;

} }

sub init_serv { my($file) = @_;

open(FN, $file) || die $!;

$service{"$port"} = $name;

}

$service{"total"} = "total";

$service{"others"} = "others";

$service{"icmp"} = "icmp";

}

sub ipdeny {#added at 2004/02/25

my($ip,$insize,$outsize,$totalsize,$low,$middle,$high);

$low = 1000;

$middle = 2000;

$high = 3000;

$sth = $dbh->prepare("SELECT ip, fcuinsizetotal,fcuoutsizetotal FROM

$tablename ORDER by ip");

$sth->execute();

while(($ip ,$insize ,$outsize) = $sth->fetchrow_array()) {

$totalsize = $insize+$outsize;

if ($totalsize > $low && $totalsize <= $middle){

$dbh->do("INSERT INTO IpDeny(ip,status_id,date2) VALUES('$ip','1','$year$mon$mday')");

}elsif ($totalsize > $middle && $totalsize <= $high){

$dbh->do("INSERT INTO IpDeny(ip,status_id,date2) VALUES('$ip','2','$year$mon$mday')");

}elsif ($totalsize > $high ){

$dbh->do("INSERT INTO IpDeny(ip,status_id,date2) VALUES('$ip','3','$year$mon$mday')");

} }

$sth->finish();

}

相關文件