IISに感染するある種の worm が次のようなログを残す。IISでないと判るとそれでおしまい。 192.168.1.1 - - [27/Mar/2004:00:17:23 +0900] "GET / HTTP/1.1" 200 1168 "-" "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)" 普通のクライアントからならばこれに続いて画像やCSSをリクエストするがそれ がない。IPアドレスは不特定ので2004-03-27の一日で80件ほど。ここみたいな寂 れたサイトだと普通のアクセスとまぎれてうざい。これをログから削除しよう。 UAは本当に存在するものを偽装しているのでUAでは除外できないとするとIPアド レスを元に除外するしかないだろう。プログラムの方針にはいくつか考えられる。 1. ログを読んで1件しか無いIPアドレスを除外する。 2. あるアクセスについて前後に同じIPアドレスからのアクセスが無い場合はworm と見倣して除外する。 1.の方法にはログ全体を2回読むか、一度読んだものを記憶しておかないといけ ないので富豪的。プログラムは2.に比べれば簡単。ISPから同じアドレスを割り あてられた複数のマシンからアクセスがあったときにワームを除外できない。 2.の場合は前後の何件かを記憶しておけばよいし、ログが大きくなっても処理し たところから吐きだせるので使うメモリも少なくてすむ。大きい組織では複数の proxyを通してアクセスが来ることがある。この場合 最初の"GET /"と他の画像 要求が別のアドレスからになって無実なのに除外されてしまう可能性がある。 2.の方がプログラム的に面白そうなので2.でやってみる。 #! /usr/local/bin/perl use strict; my( @buf ); my( $ip ); my( %count ); my( $dummy_ip )=("0.0.0.0"); foreach( 1..25 ){ push( @buf, $dummy_ip ); } while(<>){ ∈ &out; } foreach( 1..25 ){ $_ = $dummy_ip; ∈ &out; } sub in { push( @buf, $_ ); $ip = &ip( $_ ); ++$count{ "" . $ip}; } sub out { if( @buf > 50 ){ $ip = &ip($buf[ 25 ]); if( $count{ "" . $ip } > 1 ){ print $buf[ 25 ]; } else{ # print ">> $buf[ 25 ]"; } $a = shift( @buf ); $ip = &ip( $a ); --$count{"" . $ip}; } } sub ip { local($a) = @_; $a =~ /^([-A-Za-z0-9.]+)/; return $1; } かっこいいプログラムとはいえない。もっと短くできないだろうか。 |