ちかごろ、掲示板へのスパムが多くなった。いぜんからポツポツとあった、エッチサイトとか、mp3がわんさかあるサイトとかへの広告だけではなく、明らかにスパムメールの本文と覚しい文章が切れ切れにはいっているのである。
どこから来るのか、とIPアドレスをgoogleでみてみると結構有名なプロキシらしい。ただし漏れ串とかそういうのではないようである。
しかも毎週毎週定期的である。これはきっとロボットで自動的にポストしているに違いない。ほっといてもいいのだが、結構な量だし、いちいちおつきあいするのも疲れる。
そこでIPアドレスのブラックリストをつくり、そこからの投稿は受けつけないことにした。まずは見掛け上のIPaddressの取得であるが、これは、$ENV{REMOTE_ADDRで得られる。これ以降は最初からスパム用のIPaddressをあつめておいてこれに抵触するものだけお引き取り願ってもいいのだが、まあ、投稿ロボットはわりと少量のプロキシサーバーをランダムに選んでいるようである。そこで、投稿がおこなわれる度にひっそりブラックリストに記録しておき、それと比較することにした。
まずはリストづくりである。これは各掲示板の書き込み部分に
open( LOG2 ,">>secret.log"); print LOG2 ' '; print LOG2 "name=$arg{name} IPadress_port=$ENV{REMOTE_ADDR}:$ENV{REMOTE_PORT} browser_and_os= $ENV{HTTP_USER_AGENT} proxy= $ENV{HTTP_X_FORWARDED_FOR} date=$date"; close(LOG2);
という記述を追加して、書き込みをする人の名前、IPアドレス、ブラウザ、プロキシの接続元を記録することにした。これ自体は極悪掲示板ですでに実験済みなのであるが、まあ、わざわざ悪意の書き込みをしようとする人なら、身元を隠蔽するタイプのプロキシを使うであろう。そいつを発見することが目的なら面倒なことになるが、有名プロキシごしの書き込みを阻止すればよいだけだからこれで十分である。
ただどうも相手のIPアドレスをこっそり記録というのは気持わるいことではある。もちろん、ウェブで接続にしてくる以上は、向こうから自分ブラウザとか、IPアドレスとか、各種の情報をこっちに差出してくるというわけだから、別に構わないわけではあるが。とはいえ、掲示板プログラムにとってはスパムもふつうの書き込みも同じであるから、人間がブラックリストをつくってやるほかはない。
というわけで、書き込み時間と名前、書き込み内容から人間がスパムかどうかを判断、スパムを送ってきたIPアドレスはブラックリストに載せ、以降接続を拒否するというスタイルとする。
プログラムとしては、リストを読み込んで接続してきたIPアドレスと照合し、リストにあれば、書き込みをさせない、というだけである。よって、いままでの掲示板の頭にこういう記述をいれた。
####書き直した部分。#### require './bbssub.pl'; $flag = &blacklist; if($flag == 1){ &i_love_you; exit; }
内容は、ライブラリbbssub.plを読みこみ、blacklistという判定プログラムを実行する。もし一致したときはi_love_youというプログラムを実行して終了。もし一致しないときは、通常の動作に入る。きわめて原始的である。そして、bbssub.plの中身はというと、こうである。
どうせ相手はロボットであるから、何も表示せずに終了してもよいのだが、なんとなく、やんわりとお断りの趣旨を示すhtmlをそえておいた。
それにしても、不思議といえば不思議な書き込みである。どうみても内容はsendmailか何かに標準入力で流し込むような、メールヘッダまできっちりしたメール文である。cgiというcgiをメール発送cgiとみなして、流しこんでいるのだろうか。
#####掲示板への追加分#################### #/usr/bin/perl sub blacklist { #ここから関数blacklist my @b_lst; my $flag = 0; #$flagに0をセットしておく。 open LST, "black.lst"; #ブラックリストをひらく。 while(<LST>){ #一行ずつ読みとって chop; #行末の\nをとる。 chop; #行末の\rもとる。 @b_lst=(@b_lst,$_) #配列にいれる。 } close LST; foreach(@b_lst){ #配列のひとつひとつの要素をとりだして、 if ($ENV{REMOTE_ADDR} eq $_){ #IPアドレスを比較。 $flag = 1; #もし一致したら、$flagに1をセット } } $flag; #$flagを出力する。 } #これで関数blacklistはおわり。 sub i_love_you { #ここから関数i_love_you print<<END; #ここからENDまでを出力 Content-type: text/html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML lang="ja" > <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=Shift_JIS"> <META NAME="Author" CONTENT="micmic"> <LINK REL="NEXT" HREF="http://www.satani.org/index.html"> <TITLE>GOT YOU</TITLE> </HEAD> <BODY> <h1>HEY sir. I have got you.</h1> I've found you. You will be welcome. I'll visit you with small presents. </BODY> </HTML> END } #これで関数i_love_youはおわり。 1; #どういうわけかこういう呪文をいれる。 ##########################
2006/02/22