日々の怪しげなアクセス元トップ5

ログ表示

apacheのアクセスログ(/var/log/apache2/access.log.*)を解析し、存在しないファイルのアクセスを試みるアクセス元のIPとアクセスのRequestなどを表示します。

ステップ1:一次処理。定期的にスクリプトを実行して不審なアクセス元のトップ5を出力する。(アクセス回数、アクセス元IP、国コード)

ステップ2:ブサウザーからの「ログ表示」の要求にしたがって、過去7日分の表を表示する。表中のアクセス元IPをクリックしたら、生ログ(/var/log/apache2/access.log*)からR該当する行を表示する。

cat /var/log/apache2/access.log /var/log/apache2/access.log.1 | /usr/bin/php /root/apt.php

ステップ1:apt.phpのソースコード

#!/usr/bin/php
<?php
$TOP=5;
$PATH="/var/www/html/log";  // 1次処理結果の保存先
$mDB=array('Jan','Feb','Mar','Apr','May','Jun','Jly','Aug','Sep','Oct','Nov','Dec');

$fp=fopen("php://stdin","r");
while($in=fgets($fp)){
        $t=explode(' ',$in);
        $ip=$t[0];
        $tmp=substr($t[3],1);
        $s=explode('/',$tmp);
        $day=$s[0];
        $year=substr($s[2],0,4);
        $mo=array_search($s[1],$mDB)+1;
        if($mo<10) $mo='0'.$mo;
        $date=$year.$mo.$day;
        #echo "$ip,$year$mo$day\n";
        if(strpos($in,' 404 ')>0){
                @$buf[$date][$ip]++;
        }
}
fclose($fp);
arsort($buf);
foreach($buf as $date =>$ip_array){
        arsort($ip_array);
        echo "---$PATH/$date---\n";
        $fw=fopen("$PATH/$date.txt","w");
        $n=0;
        foreach($ip_array as $ip =>$count){
        //      echo "$ip,$count\n";
           if(substr($ip,0,10)!='192.168.68' && $ip!='::1'){
                try{
                $country=geoip_country_code_by_name($ip);
                if(trim($country)=="") $country=`whois $ip | grep -m1 country | awk '{print $2}'`;
                } catch (Exception $e ) {
                        $country=`whois $ip | grep -m1 country | awk '{print $2}'`;
                        if($country="") $country="??";
                }
                $country=trim($country);
                $msg= "$count $ip $country\n";
                fwrite($fw,$msg);
                $n++;
                if($n>$TOP) break;
           }
        }
        fclose($fw);
}
?>

apt.phpスクリプト出力の一例

968 43.243.222.44 HK
61 92.63.196.29 RU
25 45.155.205.27 RU
16 104.131.73.21 US
6 121.196.182.183 CN

ログ表示のためにブラウザーからアクセスするPHPファイル

<HTML>
<head>
<link rel="stylesheet" type="text/css" href="/st1.css">
</head>
<?php
$TOP=5;

echo "<H3>怪しいアクセス元トップ5</H3>\n";

for($i=0;$i<=7;$i++){
        $date=date("Ymd",time()- $i * 60 * 60 * 24);    // $i days ago
        $file="log/$date.txt";
        if(file_exists($file)){
                $data=file($file);
              $msg="<H3>$date2</H3>\n";
                if( $i % 2 ==1 ){
                        $msg="<TABLE width=400 border=1><CAPTION><B>$date</B></CAPTION><TR>";
                } else {
                        $msg="<TABLE border=1><TD valign=\"top\">\n<TABLE width=400 border=1><CAPTION><B>$date</B></CAPTION><TR>";
                }
                $n=1;
                foreach($data as $line){
                        $tmp=trim($line);
                        $t=explode(' ',$tmp);
                        for($m=0;$m<3;$m++){
                                if($m==1){
                                        $ip=$t[$m];
                                        $ref="<a href=proc.php?date=$date&ip=$ip>$ip</a>";
                                        $msg.="<TD>$ref</TD>";
                                } else {
                                        $msg.="<TD>$t[$m]</TD>";
                                }
                        }
                        $msg.="</TR>";
                }
                        if( ($i % 2 ) == 1 ){
                                $msg.="</TR></TABLE></TD></TABLE>\n";
                        } else {
                                $msg.="</TR></TABLE></TD><TD valign=\"top\">";
                        }
                echo "$msg\n";
//              print_r($data);
        }
}
?>
</HTML>

生ログから該当箇所を抽出するスクリプト

<?php
if (isset($argv)){
        $date  =$argv[1];
        $ip    =$argv[2];
} else {
        $date  = htmlspecialchars($_GET["date"]);
        $ip    = htmlspecialchars($_GET["ip"]);
}
$mDB=array('Jan','Feb','Mar','Apr','May','Jun','Jly','Aug','Sep','Oct','Nov','Dec');
$year=substr($date,0,4);
$day=substr($date,6,2);
$mo =$mDB[(int)(substr($date,4,2))-1];
$dateS= $day."/".$mo."/".$year;
$name="/var/log/apache2/$f_name";
echo "<H3>DATE:$date  IP:$ip</H3>";
echo "\n";
$today    = date("Ymd");
$tmp      = mktime(0, 0, 0, date("m")  , date("d")-1, date("Y"));
$yesterday= date('Ymd',$tmp);

function proc_msg($in,$date,$ip){
        $msg="";
        if(strpos($in,$ip)===0 && strpos($in,$date)>0){
                $in=str_replace(' - - ','',$in);
                $in=str_replace(' +0900','',$in);
                $t=explode("\"",$in);
                $s=explode(':',$t[0]);
                $time="$s[1]:$s[2]:$s[3]";
                $time=str_replace(']','',$time);
                $msg= "<TR><TD>$time</TD><TD>$t[1]</TD><TD>$t[2]</TD></TR>\n";
        }
        return $msg;
}

function proc($fp,$date,$ip){
        $msg= "<table><TR BGCOLOR=lightblue><TD>Time</TD><TD>Request</TD><TD>Result</TD></TR>\n";
        $n=strlen($msg);
        while ($in=fgets($fp)){
                $msg.=proc_msg($in,$date,$ip);
        }
        if(strlen($msg)>$n){
                $msg.="</TABLE>";
                echo $msg;
        }
        fclose($fp);
}

function procGZ($fp,$date,$ip){
        $msg= "<table><TR BGCOLOR=lightblue><TD>Time</TD><TD>Request</TD><TD>Result</TD></TR>\n";
        $n=strlen($msg);
        while ($in=gzgets($fp)){
                $msg.=proc_msg($in,$date,$ip);
        }
        if(strlen($msg)>$n){
                $msg.="</TABLE>";
                echo $msg;
        }
        fclose($fp);
}

//echo "$date,$today,$yesterday<BR>";
$off=(int)$today - (int)$date;
if($off<=2){
        $fp1=fopen("/var/log/apache2/access.log","r");
        proc($fp1,$dateS,$ip);
        $fp2=fopen("/var/log/apache2/access.log.1","r");
        proc($fp2,$dateS,$ip);
} else {
        $off--;
        $gz_file="/var/log/apache2/access.log.$off.gz";
        echo "$gz_file<BR>\n";
        $fp3=gzopen($gz_file,"r");
        procGZ($fp3,$dateS,$ip);
}
?>