/** * spamp: SPAM post validator * * readme.txt * * @package spamp * @version 1.0.1 (2010-05-04) * @link http://www.sound-uz.jp/php/ * @author Yuji Iwashita * @copyright Yuji Iwashita * * charset=UTF-8 */ 【概要】 spampは、ロボットによるスパム投稿を判定するライブラリです。 PHPで書かれた掲示板やブログなど、既存のPHPアプリケーションに スパム判定機能を加えます。 掲示板スパムボットには JavaScript による対策が極めて有効ですが そうもいかない諸事情に対応するため JavaScript・Cookie・Session の 状況に依存することなく、掲示板スパムボットを判定できることを 最重点にしています。 spampは、マルチバイトを含まない場合はじく、投稿出来るURLを1つに限定する、 プロキシっぽいクライアントを拒否する、といったフィルタはまったく使っていません。 またCAPTCHA(画像認証)やパスワードによる認証方式でもありません。 掲示板スパムボットのプロファイリングから生まれたロジックで スパム判定をおこなう点がこのスクリプト最大の特徴です。 補助的に、IPアドレスとキーワードによるフィルタリング機能も備えていますので ロジックで判定出来ない手動スパム投稿にも対応可能です。 最新のスクリプトとドキュメントは以下のURLにて公開しています。 http://www.sound-uz.jp/php/script/spamp また、フィルタリングだけでなく、スパムのリクエストそのものを 減らす対策も必ず実施し、掲示板スパム、コメントスパムを撲滅しましょう。 http://www.sound-uz.jp/php/note/spampost 【適用】 - サーバー環境 - PHP4.3以降、PHP5.2でも動作テスト済みです。 ココの掲示板とブログ(WordPress)にて検証しました。 掲示板やブログのコメントなど、特定のウェブフォームを使って 投稿するものなら、どのようなPHPスクリプトにも使えます。 特定のフォームが無いトラックバックや、書き込みツールからの 投稿を許可しているアプリケーションには対応していません。 - クライアント環境 - テキストブラウザには対応していません。必ずSPAMと判定します。 また、モバイル端末は完全には対応していません。 このようなクライアントには、許可IPリストを併用することで適用可能です。 【更新履歴】 2010-05-04 version 1.0.1  $lifeTime切れのセッションファイルが2日以上残っていることがあるので  セッションファイルの削除頻度を倍にアップ。  putImage() のレスポンスヘッダに'Pragma: no-cache'を追加。  1.0 からの更新は、spamp.php を差し替えるだけでOKです。  他のファイルは 1.0 と変えてません。  ※ 'Pragma: no-cache'を追加しましたが、FireFoxだけ、画像がキャッシュされ、    セッションが確立できず、1/2の確率で投稿に失敗することを確認しています。    「1度でもセッションを確率できるクライアントはスパムボット判定からを除く」    方向で仕様変更を検討します。 2010-04-12 version 1.0 release 【使用条件】 ここに公開しているフリースクリプトは、個人・法人・商用・非商用を問わず 使用できるフリーウェアです。編集・改造・再配布もご自由にどうぞ。 ただし著作権は放棄していませんので次の条件をご了解頂いた上でお使いください。  当スクリプトが原因でおこった損害は一切責任を負いません。  使用者自身の責任においてお使いください。  継続的なバージョンアップやサポートは保証出来ません。  再配布する場合は、責任の所在がわかるよう、スクリプト中の著作者表示や  連絡先はそのまま残し、修正や追加、削除などスクリプトになんらかの変更を  加えた場合は、変更箇所とお名前、連絡先(URLやメールアドレス)を  必ずスクリプトに追記した上で配布して下さい。 ご意見・ご感想・バグ報告などいただければ今後の開発の糧とさせていただきます。 もしありましたら掲示板にお寄せください。 【spampを構成するファイル】 spamp.php - spamp クラス本体 spamp.conf.php - 設定 access.php - セッション開始用コマンド allow.host.php - 許可IPリスト deny.host.php - 拒否IPリスト deny.word.php - 拒否ワードリスト readme.txt - 簡単な説明書(このファイル。実行には無関係です。) 【おすすめするディレクトリ構成】 + /home/userdir/lib/spamp <1> - spamp.php - spamp.conf.php - allow.host.php - deny.host.php - deny.word.php + /home/userdir/tmp/spampwork <2> + /home/userdir/www <3> - access.php <1> spamp ライブラリのディレクトリ   任意の場所ではかまいません。spamp.php は他のファイルから読み込んで   使うので、include_path の通ったディレクトを推薦します。 <2> 作業用ディレクトリ (読み書き属性必須)   spamp はセッションやリストのキャッシュなど一時的なファイルを読み書き出来る   ディレクトリをひとつ必要とします。DocumentRoot以下でなければ任意の場所で   かまいません。専用のディレクトリを作成しウェブサーバーの権限で読み書き出来る   属性を与えておきます。 <3> DocumentRoot以下   access.php だけはクライアントから直接アクセス出来る必要があるので   必ず DocumentRoot 以下に配置します。DocumentRoot 以下ならばディレクトリは   問いません。 【最少限必要な設定】 使い始める前に少なくとも2つのファイルで計6ヶ所設定します。 # # access.php の設定箇所 # /** * Load Spamp class */ require_once '/home/userdir/spamp/spamp.php'; 【1】spamp.php のパスを指定します。必ず実際に配置したパスに書き変えてください。 # # spamp.conf.php の設定箇所 # /** * Signature * * @var string $signature unique strings */ $signature = 'u5*a0(9gil#4krxb-s;g%t7~yd2'; 【2】ユニークなIDを生成するためのキーとなる文字列を設定します。文字種や文字数は    問いませんので、必ず管理者固有の文字列に書き変えてください。 /** * Work directory * * Writable attribute * * @var string $workDir directory. default 'configrationfile_dir/work' */ $workDir = '/home/userdir/tmp/spamp_work'; 【3】spamp はセッションやキャッシュなど一時ファイルを保存する    作業用ディレクトリをひとつ必要とします。DocumentRoot下でなければ場所は    問いませんのでSpamp専用のディレクトリをつくり、ウェブサーバの権限で    読み書きできる属性を与えておきます。 /** * Internal encoding * * @var string $internalEncoding encoding name. default 'UTF-8' */ $internalEncoding = 'UTF-8'; //$internalEncoding = 'EUC-JP'; 【4】Spampがデータとして取りあつかう文字エンコーディング名を指定します。    この文字エンコーディングは拒否ワードリストやログファイルの出力に影響します。    通常は対象の掲示板スクリプトやブログが内部で用いている文字エンコーディングに    合わせてください。多くの場合 php の mbstring.internal_encoding になると思います。 /** * Cookie path * * @var string $cookiePath path. default '/' */ $cookiePath = '/'; 【5】Cookieを有効とするパスを指定します。    DocumentRootが自分の管理下にある場合はデフォルトで構いませんが、    共用サーバーやプロバイダのホームページスペースなどで /~YourHome     みたいなURLが自分のホームの場合は必ずそれ以下のパスに書き換えます。 /** * Cookie Domain * * @var string $cookieDomain your domain. default $_SERVER['HTTP_HOST'] */ $cookieDomain = null; //$cookieDomain = $_SERVER['HTTP_HOST']; // default //$cookieDomain = 'www.sound-uz.jp'; // your domain 【6】Cookieを有効とするドメインを指定します。    www 有り無しなどサブドメインを複数使って運用しているなど特定の    ドメインからのみCookieが有効となるよう書き換えます。 【アプリケーションに spamp を組み込む】 【1】投稿フォームにイメージタグを書き加える まずは投稿フォームのHTMLに以下のようにイメージタグを書き加えます。 投稿フォームのHTMLの記述例 src="..." には、実際に配置した access.php のURLを記載します。 イメージタグを書き込む位置は、フォームが完全に表示されることが望ましいので できるだけページの下部がおすすめです。 access.php はレスポンスとして 1px×1px の透明GIFを返します。 イメージタグを書き込む位置は、フォームが完全に表示された後が望ましいので できるだけページの下部がおすすめです。 access.php はレスポンスとして 1px×1px の透明GIFと一緒にクッキーを送信します。 さらにサーバー側ではクライアントの情報を元にセッションを作成します。 【2】受信側スクリプトにスパム判定コードを書き加える 続いて投稿を受ける側(投稿処理)のスクリプトに書き加えるのは3点です。 1. spamp クラスを読み込み 2. spamp オブジェクト生成と初期化 3. SPAM判定と後処理 受信側スクリプトの記述例 isSpam()) { // スパムと判定した時の処理例 header('HTTP/1.0 403 Forbidden'); exit(); // スパムに本文を返す必要なし。エコ・トラフィックでいきましょう } $Spamp->removeSession(); /* * これ以降は、スパムでない場合の投稿処理・・・ */ スパムの判定は、isSpam() をコールするだけです。 isSpam() は、クライアントが送ってきた値を元に次の順で評価し、 スパムでなければ 0 を、スパムと判定すれば 1以上の整数を返します。  1. Cookieの待ち時間と整合性(戻り値:1)  2. セッションの待ち時間と有無(戻り値:2)    3. 許可IPリスト (allow.host.php)  4. 拒否IPリスト (deny.host.php) (戻り値:4)  5. 拒否ワードリスト (deny.word.php) (戻り値:8) 1と2でスパムと判定した場合に限って許可IPリストによるチェックを行います。 許可IPリストに該当しなかった場合、これ以降の判定は行わずすぐに結果を返します。 1と2でスパムと判定されなかった場合と許可IPリストに該当する場合は、続いて 4と5のチェックが行われます。すべてのチェックをパスすれば戻り値は 0 です。 さらに、スパムと判定した場合に限り、isSpam() はあえて整合性のとれてない Cookieをクライアントに送信します。これにより、一度スパムと判定した クライアントを継続してスパムと判定し続けます。 あとは、isSpam() の戻り値を元に、適切に処理を振り分けてください。 尚、セッションは、$lifeTime で設定した時間が過ぎるまで生きていますので 不要となればすぐに $Spamp->removeSession() を呼んで破棄します。 なお、ここで言う「セッション」は Spamp 独自のモノで PHP の $_SESSION とはまったく関係ありません。 また、Cookieのチェックは Cookieがある場合だけ行うので Cookie非対応のクライアントがCookieでスパムと判定されることはありません。 以上、最も簡単な使い方です。 【3】投稿フォーム出力スクリプトにクッキー送信コードを書き加える ここまでの段階で基本的に使えるようになっています。が、さらに 投稿フォームを出力前にクッキーを送信することにより、Spampの判定ロジックが 100%活かされ効率良くスパム判定を行うことが出来ます。 投稿フォーム出力スクリプトの記述例 sendCooki(true); /* * これ以降は、通常の投稿フォーム出力処理・・・ */ sendCooki() は 引数 true を指定すると整合性のとれてないクッキーを送信します。 あえて整合性のとれてないクッキーを送信することでクッキーの確認だけでスパムを 判定できるので、セッションや拒否リストチェックによるファイルアクセスがなくなり 余分な負荷を軽減できます。 尚、クッキーは、何か出力した後からでは送信できませんので、あらゆる出力処理の前に 記述する必要があります。 【許可リストと拒否リストの編集】 spampのクッキやセッションで判定出来ない手動スパムや携帯端末は、 拒否IPリストと許可IPリストを使って補うことが出来ます。 各リストファイルは、1件1行の単純なリスト構造のテキストファイルです。 エディタで簡単に編集できます。 行頭の # から行末までは読み飛ばされますので保守しやすいよう適当にコメントを つけておきましょう。データ行の後に #コメント をつけることはできません。 allow.host.php - 許可IPリスト deny.host.php - 拒否IPリスト この2つは、IPv4形式(***.***.***.***)または、 CIDR形式(***.***.***.***/***)で記述します。 deny.word.php - 拒否ワードリスト 拒否ワードリストにマルチバイト文字を加える場合は、ファイルの 文字エンコーディングを spamp.conf.php の $internalEncoding に必ず 合わせる必要があります。 尚、リストファイルにPHPスクリプトの拡張子をつけていますが これはやむなくこれらをDocumentRoot下に配置しなければならない場合の 情報漏えい策です。spamp内部では単純にテキストファイルとして処理していますので リスト中にコードを書くことはできません。 allow.host.php にはあらかじめ国内の代表的なモバイル端末のIPリストを 記載しています。これを本当に必要とするのはおそらくi-mode だけだとは 思いますが、なにせ古い携帯端末も現役で活躍しており、これらを含めた 沢山の端末を試すことも実際不可能なため、不要だと判断出来るIPアドレスは 使用者自身で削除してください。 以上簡単ではありますが、これでスパム投稿をフィルタリングする準備OKです。 Good Luck!