[トップページに戻る]

つぶやきSHIROへのご意見・ご感想などはこちらへ。

ジャンクメールフィルタを運用
2003年06月30日(月)


ホームページでメールアドレスを公開していると,非常に多くのジャンクメールがやってくる。特に独自ドメインを持っていると,ドメイン公開データベースに登録されているアドレス宛に海外からの宣伝メールがウンザリする程届くのである。しかも同じ送信元から何度も繰り返し送られてくるケースもあり,少々退廃的な気分を味わうことになる。

何百回も繰り返されると『ジャンクメールをどうにかしたい』という強い気持ちが自然に込み上げてくるわけで,行動を起こすきっかけとなった。そこで,まず比較的簡単なprocmailを用いたブラックリストによるフィルタを導入してみた。この方法はISPの環境がprocmailrcファイルの利用が行える場合,手軽に始められるというのが利点だ。



【方法1】procmail + ブラックリストでのフィルタリング

日本では経済産業省などが策定した『特定商取引法』『特定電子メール法』などの法律・政令が改正,平成14年7月に施行され,消費者・受信者から求めたメールでない商業広告メールの件名冒頭に『未承諾広告※』の表示が義務付けられた。これによって携帯電話のメールサービスなどで,『未承諾広告※』の文字が含まれた場合にフィルタリングするような設定が可能になった。

▼経済産業省『特定商取引法及び特定電子メール法の概要』
http://www.meti.go.jp/policy/consumer/downloadfiles/shiryo3_houkaiseigaiyo.pdf


しかし,これでは抜本的な対策になるハズも無かったのである。問題点として以下のようなことが挙げられるだろう。
・日本の業者のみが対象。日本の法律の及ばない海外のジャンクメールは当然ながら規制対象外
・もともと法律を守らない悪徳業者には無意味
・厳密に『未承諾広告※』の文字列だけがフィルタリングされるため,『末承諾広告』とか『未 承 諾 広 告』とか『未承認広告』などの文字列が来た場合,フィルタリングすることが出来ない

つまり『未承諾広告※』の文字列を厳密に守ったお行儀の良い(?)広告だけがフィルタリングされるという状態であり,法律が正しく機能するまでには,特に3番目の文字列を厳密にしない業者の大半は確信犯的であるため,罰則強化を含めた別な対策が必要であろう。

▼ZDNET mobile『「未承諾広告※」、受信拒否の矛盾』
http://www.zdnet.co.jp/mobile/0209/03/n_meiwaku.html


したがって,こういった現段階での打開策として,このようなジャンクメールを送ってきたメールアドレスをブラックリスト化して,新たに届いたメールがブラックリストに該当すると,Mailサーバに届いた時点で『ゴミ箱』行きにする設定を行ってみた。そしてここ半年ばかり運用してきた感想としては,まずまずの成果が上がったと思われ,ここでご紹介することにした。

具体的には,WebmasterのメールサーバでprocmailというLDAを利用した。これは,サーバ上のメールボックスに保存する際に,さまざまな条件に基づいてメールを振り分けたり転送するなどといった処理を行うツールである。

一つ一つの条件のことをレシピと呼び,これらを『.procmailrc』というファイルに書き込み,メールサーバ上のユーザ毎に決められたフォルダに保存すれば,動作するようになる。(ただし,すべてのメールサービス/ISPで通用するものではなく,.procmailrcを許可するISPのみで有効であることに注意されたい。詳しくは各自ISPにご確認願いたい。)

ブラックリストに該当するメールをゴミ箱へ移動させるレシピは以下のようになる。

▼Webmasterの『.procmailrc』より抜粋
LOGFILE=$HOME/procmail/procmail.log
DEFAULT=/var/spool/mail/ユーザID
BLACKLIST=$HOME/.blacklist

#件名に『未承諾広告』が含まれていたらゴミ箱へ
:0
* ^Subject:.*iso-2022-jp
* ^Subject:.*\/.*
* ? echo "$MATCH" | nkf -me | egrep '未承諾広告'
$HOME/procmail/junkmail

# From: Reply-To: Sender: From のどれかにブラックリスト
# のメールアドレスが含まれていたらゴミ箱へ。(部分一致)
:0
*$ ? test -s $BLACKLIST
* ? (formail -x From: -x Reply-To: -x Sender: -x From | fgrep -iqf $BLACKLIST)
$HOME/procmail/junkmail


さてしかし,上記の方法だと『.procmailrc』の利用を許可しているISPのメールサーバであれば,実行可能という利点があるのに対し,運用面では以下のような欠点が存在する。
・初めて来るメールアドレスorドメインからのメールをフィルタリングできない
・ジャンクメールが来たら,何らかの方法でブラックリストに追加する手動の作業が必要

1点目の欠点は,逆に未知のメールをすべてOKとしないと,このような単純なフィルタリング方法では,本当は必要なメールがジャンクと誤って判定され,本来のメールボックスに届かないという最悪の事態は避けなければならないため,構造上仕方が無いところではある。我慢がまん・・・。

2点目の欠点は,ジャンクメールが届くたびに運用上面倒な作業を強いるものであり,しかもこのメンテナンス作業自体が消極的な性格の作業であるため,なかなか憂鬱になるのだ。

毎日せっせとブラックリストを更新するというこの作業があるお陰で,すっかり『spamファイター(spamと戦うヒト)』を自認せざるを得ない状態にまで追い込まれていた。




【方法2】ベイズ理論によるメール評価

そこで現在,Webmasterはこれからのコンピュータソフトテクノロジのトレンドとなりそうな『ベイズ理論』と呼ばれる『統計的情報に基づく確率評価法』を用いたフィルタリング(以下ベイジアンフィルタ)で運用を行っている。人工知能の基礎であるこの手法によって,実にインテリジェントにジャンクメール判定が行われ,しかもほぼメンテナンス作業が皆無であるため,これまでジャンクメールが届くたびに憂鬱な気分になっていたのが,逆に今ではとても楽しみになってしまっている。他のベイジアンフィルタを利用したユーザや開発者の中には『これはもうレジャーだね』などと言う方もいらっしゃるほどである。

▼ただただし氏『ただのにっき』
http://sho.tdiary.net/20030518.html
Webmasterはこのページを発見し『レジャーだ』と言われたときには衝撃と感動を覚えたものだ。

これまでのジャンクメールのみに含まれる単語をデータベース化し,対象のメールがジャンクであるのかどうかの確率が90%以上と評価された場合にゴミ箱へ移動する,というのが基本である。未知の単語に関しては,とりあえず40%の中立的な暫定的な数値で評価するなどの手法によって,未知のメールを評価する場合に有効となっている。詳しくは以下が詳しい。今日のベイジアンフィルタの基礎概念を普及させたPaul Graham氏の論文を和訳したものである。

▼『スパムへの対策 ---A Plan for Spam』日本語訳
http://www.shiro.dreamhost.com/scheme/trans/spam-j.html
▼『ベイジアンフィルタの改善 --- Better Bayesian Filtering』日本語訳
http://www.shiro.dreamhost.com/scheme/trans/better-j.html

この理論の実装では,海外をはじめとしたいろいろなものが出てきた。海外で代表的なものではbogofilterifileが,クライアント側での実装としては,Mozilla1.3のスパムフィルタ機能が有名である。

Webmasterは日本語の各種エンコードに対応していること,サーバ側で携帯端末への転送を行っている関係上,サーバサイドでprocmailを用いてのジャンク判定が必要なこと,古いLinux環境(TurboLinux advanced server 6。特にglibcなどのライブラリが2.1と古い)での稼動が前提という3点から,Rubyスクリプトで実装した『bsfilter』を採用した。

▼nabeken氏『bsfilter / bayesian spam filter / ベイジアン スパム フィルタ』
http://www.h2.dion.ne.jp/~nabeken/bsfilter/

メールサーバ上で動作させるに当たって必要な主なものは以下の通り。
・Ruby言語環境
・sdbm(簡易データベース機構)
・ジャンクメールと非ジャンクメールのサンプルをそれぞれ最低100通以上

最低100通ほどのサンプルが必要なのは,より正確性を期すためである。統計上のデータを基に確率を捻出するため,母集団が多ければ多いほど良いと言える。逆に大量のサンプルを揃えられないケースでは,この手法がむしろ弱点と言える。

救済措置として,http://www.spamarchive.org/ などを利用して,既知の公開されているジャンクメールを確保するということも可能だ。公開されているものを利用しても十分機能するフィルタとなるが,ジャンクか非ジャンクなのかを判定するのは,各ユーザによって異なるし,何より届くジャンクメールの傾向もユーザ毎に異なる点が重要であるため,ユーザ宛に届いたジャンクメールを蓄積/保存しておき,かつ利用するユーザ毎に分けてデータベースを利用することをお勧めする。

自分のメール環境を正しくかつより多くを統計情報化することが,ベイジアンフィルタを既に活用している先人達のサイトにあるような脅威の精度を実現させるのである。

さて,Webmasterが利用するにあたって,MailサーバにRuby環境が無く,既存のバイナリ(rpmパッケージ)もglibcのバージョン不整合などで利用できなかったためソースからコンパイルするなど,いろいろと難儀してしまったが,結局導入に成功。

▼オブジェクト指向スクリプト言語『Ruby』
http://www.ruby-lang.org/ja/
今回は『ruby-1.6.7.tar.gz』をコンパイルした。

ジャンクメールサンプルは,方法1で紹介した方法で運用したときに半年間に渡って貯めていたゴミ箱のメールボックス(9.1MB・1993通)を,非ジャンクメールはNetscape4.7xとMozillaのInboxファイルをそのまま(計17.2MB・994通)を,それぞれ用意することができたので,これら利用した。

bsfilterにこれらのファイルをmbox形式と指定して直接読み込ませることで,統計情報は構築可能だ。例としては以下のようになるだろう。
./bsfilter -s --mbox < JunkMailBox
./bsfilter -c --mbox < Inbox
./bsfilter -u


あとはbsfilterの製作者のサイトにある『.procmailrc』のサンプル通りで動作している。

タイミングのいいことに,bsfilter導入に伴う一連の作業中に,新たにジャンクメール/非ジャンクメールがそれぞれ2通ずつ届いた。まだ統計情報上にないこれらのメールを試しにbsfilterで評価してみた。メールをヘッダも含めてそのままの形式でテキストファイル化する。

./bsfilter -v < メールファイル

でジャンクメールである確率が以下のように0.0000〜1.0000の表示で確認できる。

ジャンクメールではないメールは2通とも
combined probability 0.000000


ジャンクメールの1通目
combined probability 0.999940

ジャンクメールの2通目
combined probability 1.000000


いずれも目で見れば一目でわかるジャンクメールだが,これをspamブラックリストには無かった新たなメールであったにも関わらず,上記のように『junkである』と断定したこの結果を見ると,ベイジアンフィルタが機械的に処理した結果とはとても思えず,感動に値する出来事となった。

本来コンピュータには不向きと思われる抽象的な仕事をするためのプログラムの中身は,動作原理そのものは明快で,かつ単純作業の繰り返しに支えられた,如何にもコンピュータソフトウェアらしい動作を行っているに過ぎないが,これでなかなかインテリジェンスな動きを見せ付けられたら,きっと誰でも同様の思いに至るハズである。

最後になりましたが有意義なツール『bsfilter』の製作者nabeken氏,理論を紹介してる方々のサイトへ感謝いたします。

つぶやきSHIROへのご意見・ご感想などはこちらへ。

[トップページに戻る]