2005-11-13 Sun

コメントスパムと不毛な小競り合い

Nucleus でコメントスパムを駆逐するプラグインの本命は「NP_Blacklist 0.98 jp2 - NP_cles()」で間違いないと思います。以前のサイトや、僕が構築のお手伝いをさせてもらったところでも大活躍してました。ですが、なんか表示が遅くなるとかちょっとしたトラブルの時に外して、それっきりにしてます。理由は「すり抜けられる可能性がある」というところですね。まあ仕組みをまったく理解してないので、こう言うとなんなんですけど。要はメンテしたくないんですよ。楽にBlogを続けたい。

で、当サイトは「最近のコメント(トラックバック含む)」を表示していないし、なにより当サイトは来訪者が少ないので、コメントスパムもそうそう来ないだろうと期待してたんです。ところが先日、爆撃を食らってしまいました。しばらく放置して、後でゆっくり消そうなんて余裕の態度をとっていたのですが、10通を超えた辺りから我慢できなくなり、以前から気になっていた対策を施すことにしました。再開以来、一方的にお世話になりっぱなしの「Nucleus.skooler.org」さんの「簡易コメント・スパム対策」です。

詳しいことはよく分かりませんが、コメントスパムを送信してくる人というかなんというか、まあとにかく、ページを実際に開いてコメント欄に書き込むっていうことはしてないそうです。そりゃそうですよね。で、dj k!ng さんの分かりやすい解説によれば、ページを開いていないのにコメントすることを禁止する改造を、Nucleus のコアに施すということですね。ということで爆撃真っ最中に改造すると、ぴたりとスパムが止まりました。小躍りして喜んでいたのですが、コメントスパムがタイミング良く止まっただけなのかもしれません。

で、確認できる術は無いものかという思いと、サイト再開時のお約束「コアファイルに手を出さない」という原則を守るため、dj k!ng さんの対策をプラグイン化しました。

…したんです。たぶん。でね、動いたんです。ブロックした時にはログに残すようにもして、2回ほど防いでくれたんです。でもね、その後微調整してるうちに、おかしくなっちゃって、再びスパムくらったんです。で、その後元に戻したんですが、それっきりコメントスパムが来なくなって、確認できないんです。まともに動いているのか。はっきりいって、dj k!ng さんのコードをコピーしてるだけなので、その実際の動きを把握してないんですよね。何やってるか、はわかるのですが、なぜそう動くか、がわかっていない。

で、なんか明らかにまどろっこしい処理というか、ある関数で作った変数を流用したいんですけど、その方法が分からなかったりして、つまり変なんです変なコードなんです。あと「event_ValidateForm」という関数に「global $CONF, $errormessage, $manager;」としててもしてなくても、スパム弾いていたような気もしますし。

ということで公開できるレベルでは全然ないのですが、コードを公開しますので、お手すきの方はご指導していただけるとありがたいです…あ、多分 Nucleus 3.2 以上じゃないと動かないはずです。

しかし早くコメントスパムこないかなぁ…ちゃんと動いているのか確認する術がない。

<?
 // plugin needs to work on Nucleus versions <=2.0 as well
 if (!function_exists("sql_table")) {
  function sql_table($name) {
   return "nucleus_" . $name;
  }
 }

class NP_NoRobotComment extends NucleusPlugin {

 function getName() {
  return 'No Robot Comment'; 
 }

 function getAuthor()  { 
  return 'pushman'; 
 }

 function getURL() 
 {
  return 'http://blog.heartfield-web.com/'; 
 }

 function getVersion() {
  return '0.2'; 
 }

 function getDescription() { 
  return 'block comment from the robot.';
 }

 //put in support for SqlTablePrefix, needed in 2.0
 function supportsFeature($feature) {
  switch($feature) {
   case 'SqlTablePrefix':
    return 1;
   default:
    return 0;
  }
 }

 function getMinNucleusVersion() {
  return 320;
 }
 function getEventList() {
  return array('FormExtra', 'ValidateForm');
 }

 function install() {
  $this->createOption('cname', 'name attribute', 'text', 'spammer');
  $this->createOption('cvalue', 'value attribute', 'text', 'suspicious');
  $this->createOption('header', 'start tag', 'text', '');
  $this->createOption('footer', 'end tag', 'text', '');
  $this->createOption('debug', 'Use Action Log?', 'yesno', 'no');
 }

 function event_FormExtra() {

  $cname = $this->getOption ('cname');
  $cvalue = $this->getOption ('cvalue');
  $header = $this->getOption ('header');
  $footer = $this->getOption ('footer');

  echo $header . '<input type="hidden" name="' . $cname . '" value="' . $cvalue . '" />' . $footer;
 }

 function event_ValidateForm(&$data) {
  global $CONF, $errormessage, $manager;

  $cname = $this->getOption ('cname');
  $cvalue = $this->getOption ('cvalue');

  $debug = $this->getOption ('debug');

  if (requestVar($cname) != $cvalue) {
   if ($debug == 'yes') {
    ACTIONLOG :: add(INFO, '[NP_NoRobotComment] NANE: ' . $data['comment']['user'] . ' ID: ' . $data['comment']['userid'] . ' BODY: ' . $data['comment']['body']);
   }
   doError(_ERROR_BADACTION);
  }

 }

}
?>

追記

dj k!ng さんにアドバイスをいただき完成しました。
NP_NoRobotComment|使用方法とダウンロード

Keyword:

2005-11-13 Sun / Author - pushman / Nucleus / Comment - 2 / TrackBack - 0

「コメントスパムと不毛な小競り合い」へのトラックバック

TrackBack URL:

「コメントスパムと不毛な小競り合い」へのコメント

dj k!ng wrote...

どうも dj frakción (a.k.a. dj krist) です. 連絡が遅れてしまったのですが, とある事情で改名することになりました :-(

プラグイン化は面白いですね. とりあえずコードを斜め読みしただけで動作確認はしていないのですが, 特にこれといった問題はないように思います. ただ気になった点が幾つか.

冒頭の sql_table() 関数の宣言は必要ありません. if ブロックごと消してしまいましょう. ちなみにこの宣言が必要なのは, プラグインで独自にデータベースにテーブルを作成する場合で, なおかつそのプラグインを Nucleus v2.0 以前で動作させる必要がある場合のみです. 今回はテーブルを作成しませんし, v3.2 以降でしか動かないことが分かっているので, 全く必要ありません.

それから, NP_NoRobotComment::supportsFeature() メソッドもほぼ同上の理由で必要ありません.

NP_NoRobotComment::event_ValidateForm() メソッド中の "global $CONF, $errormessage, $manager;" という記述は必要ありません. global 宣言が必要なのは, そのグローバル変数を使用するときだけです.

同メソッド中の "doError(_ERROR_BADACTION);" という記述は, "$data['error'] = _ERROR_BADACTION;" と書いたほうが良いでしょう. "_ERROR_BADACTION" ではなく, 単にエラー・メッセージを代入することもできます.

という感じでいかがでしょう. 是非配布なさってください :-)

2005-11-15 Tue 08:22

pushman wrote...

dj k!ng さん
こんにちは。改名の件、偶然拝見しましたので、当サイトの記述も変更しました。変更ミス等ありましたら、ご遠慮なくお申し付けくださいませ。

なんか催促してしまったみたいですみません(笑)。とにかく、dj k!ng さんのコメントをはじかなくてほっとしました。そして、ご指導ありがとうございます。後学のためにここのソースはこのままにしておいて、無駄な部分の削除、意味を自分でつかんだのちに配付させてもらおうと思います。

しかしこなくていいコメントスパムをじっと待つのも、奇妙な気分です(笑)。

2005-11-15 Tue 11:12





このページの先頭に戻る