SMTP AUTH の記事でも触れたが spam が多いんですわ。以前 ( 2004/04/19 00:00 〜 2004/04/27 24:00 ) の調査では「まとめると毎日 240 通くるメイルの内、心待ちしてにいるメイルは 2 通で、ゴミは 200 通ってことですな」という状態だった。これはどういうことかというと三ヶ月で 20,000 通の spam をいただけるという状態なわけで、正直ウザくて放置していたら知り合いのエラーい人から「職場へごめんなさい、メイルボックスあふれてエラーでてますよ」とメイルもらった。「ひー、ごめんなさーい」ということと、大学のときの同期が「最近メイル読んでない?返事こないけど」と電話があり一念発起した。
だが、しかーし、 Linux は使ってるけどサーバとしてだけで、普段使いは Windows だけなんだよって文句をいっても始まらない。特に筆者が使っているのは Winbiff というマイナーなメイルソフトでいろいろな困難があったけど、使い始めて一週間くらいでそこそこの状態にまで持ってくることができた。まだ spam を残したり、spam じゃないものを spam と判定したりすることがあるけど注意すれば何とかなるレベルなのでこれからフィルタの学習を進めて賢くしていこうと思う。現時点での成績的には 200 通のメイルのうち、 spam 判定 150 通で spam じゃないのにそう判定されたのは 2 通、 spam なのにそうでないと判定されたものが 10 通。十分使い物になると思える精度だと思う。
spam を見たくないためにはどういう方式があるかを考えてみるといくつかは下記の 4 方法が挙げられよう。
今回は「 spam の特徴をプログラムが作成する統計的フィルタで排除する」という方法でチャレンジしてみる。
どういうフィルタがあるかを探してみると現在メジャーなものにベイジアンフィルタという方式がある。詳しくはベイジアンフィルタ( Bayesian Filtering )などの語で検索してみるといいだろう。簡単に書けば spam 特有の語などを統計的にどれくらい spam 的かを数値化するものである。実際にはその上で人間が閾値を決めて判定という流れになる。
有名どころだとSpamAssassin ( http://www.spamassassin.org/index.html ) だろう。しかし SpamAssassin は重いとか、 perl を使っているので日本語はイマイチ得意じゃないとかいうウワサがあるので、重いというウワサも見つけられず、 ruby を使って日本語の分かち書きソフトとも連携できる bsfilter ( http://bsfilter.org/ ) を使ってみることにした。なお、 Windows 版もあるのでソレを使うのがもっとも簡単な方法だが、 Linux のサーバを使っているのでいろいろチャレンジすることにした。
ハードウェア |
特にナシ、今回はソフトの設定と運用の話 しいて言えば bsfilter をインストールできる Linux サーバがあること。 |
ソフトウェア(サーバ側) |
|
ソフトウェア(クライアント側) |
|
その他 |
|
インターネット上のメイルサーバ | NAT BOX ( ファイアウォール代わり ) | +--- Linux サーバ | +--- Windows クライアント
従来は Windows クライアントからインターネット上のメイルサーバに直接メイルを取りに行っていた。 新方式では Linux サーバにメイルを取得させて、 Windows クライアントは Linux サーバにメイルを取りに行くようにする。 こうすることで、見かけのメイル受信が早くなることと、 spam 判定を Linux サーバで判定させるなどのことができるようになる。
すでに bsfilter がインストールされているとか、 Debian GNU/Linux Sarge がインストールされているときにはこの項目は飛ばして次を見よう。
従来 Debian GNU/Linux potato を使っていたが、いろいろゴミがたまっていたので思い切って Debian GNU/Linux Sarge をクリーンインストールすることにした。インストールの詳しいことは他のインストール記事に譲るが、 Windows XP では下記の方法でダウンロードし、インストール CD-ROM をつくり、インストールした。クライアントマシンが WindowsXP だから基本的操作は Windows XP で操作するのだ。なお、 Sarge の正式リリース前なので時間が経つと URL が変わっている恐れがあるので注意すること。
Debian の Sarge の CDROM イメージをダウンロードする http://www.debian.org/devel/debian-installer/ から iso9660 イメージの CD1 の分をダウンロードする。
CDManipulator で CD-R に起動用 CD として焼く http://download.seesaa.jp/contents/win/system/backup/10295/ から CDManipulator をダウンロードしてインストールし、 Sarge の iso9660 イメージを CD-R に焼く。
Debian GNU/Linux Sarge をインストール 作成した起動用 CD を入れてサーバの電源を入れると boot プロンプトからインストールが開始できる。 ここで日本語環境でインストールもできるが基本言語環境が日本語になるが、キモチ悪ければ英語でインストールすべし。(あとで Lang=C とすればいいのだが最初はちょっとビックリする)
telnet 代わりに ssh を使うのでサーバに sshd を、 Windows 側に TeraTermPro と TTSSH をインストールする。 Linux サーバに ssh サーバをインストールするがたいしたことなくて root 権限で apt-get install ssh だけだ。 telnet 代わりに使うので /etc/ssh/sshd_config をいじってこれくらいにしておくといいだろう。
あるいは ListenAddress 0.0.0.0 にしておいて、 /etc/hosts.deny には ALL: ALL くらい書いておいて、許可したいホストだけを記述するようにして sshd : 192.168.1.4 とかアクセスする Windows マシンの IP アドレスを書いておくのもいいだろう。当然ながらこれらの設定に矛盾があるとどこからもつながらないので気をつけよう。 次に TeraTermPro と TTSSH をインストールしよう。 ちゃんとインストールできれば TTSSH でログインできるハズだ。 ここまでできればサーバの画面をみて Windows の画面を見ながらということも必要なくなる。ListenAddress 192.168.1.0 Protocol 2,1 PasswordAuthentication yes
root 権限で apt-get install samba で終わりだ。 /etc/samba/smb.conf はこんな感じだ。( printer セクションや tmp セクションはおまけだ) 設定を変更したら samba を再起動しよう /etc/init.d/samba restart とする。
これ以降、 Winbiff のファイルを bsfilter に食わせるためにサンプルファイルをサーバに転送するのにいちいち WinSCP などを起動しないでも Windows の標準的なファイルコピー方法でファイルコピーができるようになる。
[global] printing = bsd printcap name = /etc/printcap load printers = yes guest account = nobody invalid users = root coding system = euc client code page = 932 interfaces = 192.168.1.3/24 security = user workgroup = WORKGROUP server string = %h server (Samba %v) syslog only = no syslog = 0; socket options = IPTOS_LOWDELAY TCP_NODELAY SO_SNDBUF=4096 SO_RCVBUF=4096 encrypt passwords = yes wins support = no name resolve order = lmhosts host wins bcast dns proxy = no preserve case = yes short preserve case = yes unix password sync = yes passwd program = /usr/bin/passwd %u passwd chat = *Enter\snew\sUNIX\spassword:* %n\n *Retype\snew\sUNIX\spassword:* %n\n . max log size = 1000 [homes] comment = Home Directories browseable = no read only = no create mask = 0700 directory mask = 0700 [tmp] comment = temp directory browseable = yes read only = no create mask = 0777 [printers] comment = All Printers browseable = no guest ok = yes path = /tmp printable = yes public = yes
bsfilter をインストールするには root 権限で apt-get install bsfilter だけだ、ほんとにそれだけ。(感動も何もない、笑) これだけでは何もできない。 spam とはどんなものか、 spam でないメイルはどんなものかを教えなくてはならない。 ここから下は bsfilter の教育のための方法がメインだ。 読みながら試してみるといいだろう。
構成の説明通り Linux サーバがメイルを取得できるようにする。 インストールは root 権限で apt-get install fetchmail だ。 次に pop 対応ソフトで今回は qpopper をインストールする。 インストールは root 権限で apt-get install qpopper だ。
標準では Debian は Exim という MTA がインストールされている。今回は変更していないので Configuring Exim v4 という題名の質問がいくつかでてくる。参考に筆者の例を挙げておく。
Winbiff は標準で APOP に対応しているので qpopper もパスワードを APOP にしておく。 もちろん、ローカルネットワークだから POP3 でもいいのだろうが、無線 LAN などを不意に使うときなどにも APOP を選んでおいたほうが少々安心だ。 また Outlook Express などを使う場合は APOP には対応していないので下の作業は必要ない。 作業は root 権限で popauth というコマンドをつかう
# popauth -init Really initialize POP authentication DB? yes # popauth -user <USERNAME> Adding only APOP password for <USERNAME>. New password: Retype new password:
個人のホームディレクトリにあるメイルを取得できるようにしたいので /etc/qpopper.conf のパラメータをこんな感じに変更した
そして個人のホームディレクトリでディレクトリを作成しておこう。set home-dir-mail = ".Maildir/mbox"
$ mkdir .Maildir
procmail をインストールするには root 権限で apt-get install procmail だ。 ホームディレクトリに .procmailrc を作成しよう、中身は最初はこんなだ。 MAILDIR で指定するディレクトリが違うと qpopper で見るところと違ってしまうのでメイルがこないことになってしまうので注意が必要だ。
PATH=/usr/local/bin:/usr/bin:/bin MAILDIR=$HOME/.Maildir DEFAULT=$MAILDIR/mbox LOGFILE=$MAILDIR/.from
今回は Winbiff を使っているので今までの受信していた設定を変更する。
ツール→ユーザ設定→アカウント→プロパティ→受信タブをえらんで、
サーバ名に今回のサーバのアドレス(例では 192.168.1.3 ) 使用するプロトコル POP3 ユーザ名を <USERNAME>
続いてオプションタブをえらんで 受信済みメールの削除を「削除しない」に当面しておこうそうすればメイルを失わずに済むし、安定したら「受信後すぐに削除」に変更すればいい 上の popauth の作業をしたならば APOP を使うにチェックをいれておこう
ためしに受信してみよう。 期待としてはエラーがでず、メイルが届いてないとでてくれば OK だ。
ホームディレクトリに .fetchmailrc というファイルをつくり、中身は下記のようにしてみよう。 ここでいう <USERNAME> は手元の Linux サーバで前に popauth したユーザ名で、メイルサーバのユーザアカウントとパスワードはそれぞれ <MAILUSERNAME> <POPPASSWORD> であらわしている。 メイルサーバは mail.example.com としておく。
set postmaster <USERNAME> set no bouncemail defaults # この keep はインターネット上のメイルサーバのメイルを削除しない設定だ、あとで削除する設定にする keep no mimedecode fetchall poll mail.example.com proto POP3 user "<MAILUSERNAME>" there password "<POPPASSWORD>" is <USERNAME> here mda "/usr/bin/procmail -f %F"
やり方は単に fetchmail -v と打つだけだ。 するとやり取りがバラバラとでてくると思う、うまくいっていればこんな感じになるハズだ。
fetchmail: 6.2.5 querying mail.example.com (protocol POP3) at Thu 25 Nov 2004 10:00:02 PM JST: poll started fetchmail: POP3< +OK QPOP (version 3.1.2) at mail.example.com starting. <12814.1101391234@mail.example.com> fetchmail: POP3> CAPA fetchmail: POP3< +OK Capability list follows fetchmail: POP3< TOP fetchmail: POP3< PIPELINING fetchmail: POP3< USER fetchmail: POP3< EXPIRE NEVER fetchmail: POP3< UIDL fetchmail: POP3< RESP-CODES fetchmail: POP3< AUTH-RESP-CODE fetchmail: POP3< X-MANGLE fetchmail: POP3< X-MACRO fetchmail: POP3< X-LOCALTIME Thu, 25 Nov 2004 23:00:34 +0900 fetchmail: POP3< IMPLEMENTATION Qpopper-version-3.1.2 fetchmail: POP3< . fetchmail: POP3> USER <MAILUSERNAME> fetchmail: POP3< +OK Password required for <MAILUSERNAME>. fetchmail: POP3> PASS * fetchmail: POP3< +OK <MAILUSERNAME> has 5 visible messages (0 hidden) in 31927 octets. fetchmail: POP3> STAT fetchmail: POP3< +OK 5 31927 5 messages for <MAILUSERNAME> at mail.example.com (31927 octets). fetchmail: POP3> LIST 1 fetchmail: POP3< +OK 1 2920 fetchmail: POP3> RETR 1 fetchmail: POP3< +OK 2920 octets reading message <MAILUSERNAME>@localhost.localdomain:1 of 5 (2920 octets) . not flushed −省略− fetchmail: POP3> QUIT fetchmail: POP3< +OK Pop server at mail.example.com signing off. fetchmail: 6.2.5 querying mail.example.com (protocol POP3) at Thu 25 Nov 2004 10:00:09 PM JST: poll completed fetchmail: normal termination, status 0
Winbiff までメイルがくればメイルの代理取得は成功だ。
bsfilter は学習しないと、ナニが spam でナニがそうでないかを知らない状態だ。それは善悪のわからない子供に、いいことと悪いことを教えることに似ている。子供と違うところは時間をかけなくてもたくさんのデータを食わしてあげるとすぐに学習することだ。 spam のサンプルと、自分が必要なメイルのサンプルをなるべくたくさん用意しよう。 spam のサンプルは「 Linux-usersメイリングリストのspamをかき集めたもの」があって http://www.flcl.org/~yoh/spam9xxxx.tar.gz からもらってくると便利だ。 自分が必要なメイルのサンプルは、過去の誰かとやり取りしたメイルとか自分が出したメイルとか、メイリングリストとか自分が必要だったことがあるありとあらゆるメイルだ。
実は今回最大の難関がここにあったりする。 bsfilter は mbox 形式のファイルを読み込んで学習するわけだが、今回 Windows 用メイルソフトの Winbiff は独自形式で保存している。 したがって、どうにかして mbox 形式にしないといけないわけだ。
Winbiff のメイルの保存形式を見てみよう。 Version2 になって標準で JIS 形式だが、Windows でハンドルしづらいので S-JIS で保存している(これが後でもうひと手間かける必要がある原因だ) 基本的には mbox のファイルと比べると from 行(差出人と時刻が記録されている)がないこと、メイル同士の区切りに「 . 」(ピリオド)が一個というファイルであることがわかった。 なおメイル本文中に「 . 」が一個だけの場合には保存ファイルには「 .. 」とピリオドが二個になるというようになっている。 今回は MailExp を使用したが、将来はファイル変換と文字コード変換するスクリプトを書こうと考えている。
作成者のサイトをみたら「本人退職ため…」のような文言で、プログラムがなくなっていた。 これは困ったということで探していたら何とか上記用意するもののところで紹介した URL のサイトにあることを発見し、胸をなでおろした。 やはり将来はスクリプトを書いたほうがいいだろう。
変換は図のように元ファイルと出力先フォルダを指定すればよい。
学習用ファイルは MailExp で作成したものをそのままでは使えない。 なぜなら、 S-JIS で作成したものだから、入ってくるメイルストリームが JIS のため bsfilter では読んでも同一化できないからだ。 そこで S-JIS → JIS 変換をかける必要がある。 やり方は作成された 0000.TXT のようなファイルを cat してパイプして nkf -j で変換しリダイレクトして保存する。
まず nkf をインストールし、変換をおこなう。 同時に kakasi もインストールしておこう。 nkf と kakasi のインストールは root 権限で apt-get install nkf kakasi で終わり。 具体的には下記のように行う。
cat 0000.txt | nkf -j > 0000.jis
bsfilter の設定ファイルはホームディレクトリに bsfilter.conf としておけばよい。 bsfilter の設定ファイルはこんな感じだ。
jtokenizer kakasi spam-cutoff 0.6 db gdbm
bsfilter の学習は四通りだ。 1) spam を spam だと教える、 2) spam でないメイルを spam でないと教える、 3) spam でないと判定したメイルが実は spam であるものを spam と教える、 4) spam と判定したが間違っていたときにそれを spam でないと教える。
1) の場合 $ bsfilter -s spam 2) の場合 $ bsfilter -c ham 3) の場合 $ bsfilter -C -s spamfalse 4) の場合 $ bsfilter -S -c hamfalse
学習すると ~/.bsfilter ディレクトリの下にデータのファイルができているだろう。 学習に失敗したと思ったら、これらのファイルをすべて削除して再度学習させるといいだろう。
$ ls -l .bsfilter/ total 2952 -rw------- 1 help help 0 2004-11-11 10:36 C.clean.sdbm.dir -rw------- 1 help help 1024 2004-11-11 10:36 C.clean.sdbm.pag -rw------- 1 help help 4096 2004-11-24 00:06 C.prob.sdbm.dir -rw------- 1 help help 1048576 2004-11-24 00:06 C.prob.sdbm.pag -rw------- 1 help help 4096 2004-11-11 10:38 C.spam.sdbm.dir -rw------- 1 help help 1047552 2004-11-11 10:38 C.spam.sdbm.pag -rw------- 1 help help 4096 2004-11-24 00:05 ja.clean.sdbm.dir -rw------- 1 help help 207872 2004-11-24 00:05 ja.clean.sdbm.pag -rw------- 1 help help 4096 2004-11-24 00:06 ja.prob.sdbm.dir -rw------- 1 help help 1044480 2004-11-24 00:06 ja.prob.sdbm.pag -rw------- 1 help help 4096 2004-11-24 00:05 ja.spam.sdbm.dir -rw------- 1 help help 258048 2004-11-24 00:05 ja.spam.sdbm.pag
学習したら bsfilter をアップデートしよう。 コマンドオプションは bsfilter -u だ。
$ bsfilter -u
ここで bsfilter を通す設定に変えておこう .procmailrc はこんな感じにする。
$ cat .procmailrc PATH=/usr/local/bin:/usr/bin:/bin MAILDIR=$HOME/.Maildir DEFAULT=$MAILDIR/mbox LOGFILE=$MAILDIR/.from :0 fw | bsfilter --pipe --insert-flag --insert-probability
では受信してみよう。 前のテストで成功していたなら Winbiff で同じように受信できるハズだ。 ヘッダを見てみよう。 ヘッダを見の見方は、「表示→ヘッダの表示→すべてのヘッダの表示」で見ることができる。 このような感じだ。
Return-Path: <millsvh@sdc.helsingborg.se> Delivered-To: <MAILUSERNAME>@mail.example.com Received: from localhost.localdomain [127.0.0.1] by localhost with POP3 (fetchmail-6.2.5) for <MAILUSERNAME>@localhost (single-drop); Tue, 23 Nov 2004 22:00:10 +0900 (JST) Received: from telepoint.com.sg (unknown [***.***.***.***]) by mail.example.com (Postfix) with SMTP id 0EE721507B for <<MAILUSERNAME>@mail.example.com>; Tue, 23 Nov 2004 22:58:41 +0900 (JST) Received: from 135.244.150.47 by smtp.sdc.helsingborg.se; Tue, 23 Nov 2004 13:59:18 +0000 Message-ID: <754401c4d164$89a9d120$c4b80cda@telepoint.com.sg> From: "Davis Mills" <millsvh@sdc.helsingborg.se> To: <MAILUSERNAME>@mail.example.com Subject: New product! Cialis soft tabs. Date: Tue, 23 Nov 2004 15:58:50 +0200 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8bit X-Spam-Flag: Yes X-Spam-Probability: 1.000000 X-UIDL: f&!"!R!j"!k!L"!;VD!! X-winbiff-received-account: localhost X-winbiff-flags: @S-----------@
Winbiff の振り分けの仕方は、振り分け条件の設定をしてメールを振り分ける。
振り分け条件を設定したら振り分けてみよう。 spam 判定をされたメイルは spam-filtered に入る。
さて、受信直後に振り分けたメイルで上記作業終了後には大きく四通りのフォルダに分かれる。 spam フォルダにいれた spam と、 inbox に残っている、 spam ではない必要なメイル、 spam なのにそうでないと判断されたが hamfalse に移動したメイル、いったんは spam 判定されて spam-filterd に入ったが spam ではないので救済されるべき spamfalse に入っているメイルだ。 まず、それぞれのファイルを MailExp で mbox 形式にしよう。 次に samba でマウントしたディレクトリに mbox 形式にしたファイルを適当なディレクトリにコピーしよう。 そして、それらを jis コードに変換すべくターミナル中のプロンプトから cat 0000.txt | nkf -j > spamfalse などのように変換しよう。 下の表のようにできたファイルを bsfilter に食わしてやろう。 終わったらアップデートを忘れないこと。
場面 | 命令 |
---|---|
spam の場合 | bsfilter -s spamfile |
spam でないメイルの場合 | bsfilter -c hamfile |
spam なのにそうでないと誤判定したメイルの場合 | bsfilter -C -s hamfalse |
spam でないのに spam と誤判定したメイルの場合 | bsfilter -S -c spamfalse |
bsfilter のアップデート | bsfilter -u |
うまくいくようになったら .fetchmailrc の keep を flush に変えてサーバから削除するようにし、 Winbiff の設定も qpopper から受信したらサーバから削除する設定に変更しておこう。
crontab に登録しておく(毎正時に取りにいく場合)
0 * * * * ~/script/fetchmail/getmail
$ cat ~/script/fetchmail/getmail #! /bin/bash if [ ! -e ~/stopfetchmail ] && [ ! -e ~/.fetchmail.pid ]; then ( fetchmail -v -f ~/.fetchmailrc; ) >& ~/.Maildir/fetchmailerr & else exit 0 fi
ssh 経由で pop3 が使えればソレをやる .fetchmailrc はこんな感じ。 前提としては『 ssh にてパスワードを利用しないでログインする方法』http://www.turbolinux.co.jp/knowledge/public/152.html ができていること
set postmaster help set no bouncemail defaults #keep flush no mimedecode fetchall poll mail.example.com via "localhost" with proto POP3 port 50110: user "<MAILUSERNAME>" there with password "<POPPASSWORD>" is <USERNAME> here preconnect 'ssh -f -C -L 50110:mail.example.com:110 -l <MAILUSERNAME> mail.example.com sleep 15' mda "/usr/bin/procmail -f %F"
Winbiff は UTF-8 をうまく扱えないので読むと文字化けするのでフィルターを入れておくのもひとつの手だ。 UTF-8 は Gmail などがだすメイルでそういうことがある。 下の例は bsfilter を通す前に utf8filter として通してある。 このフィルターは Gmail-Filter として http://yamagata.int21h.jp/tool/gmail-filter/ で配布されている。 メイリングリストのサーバで使われることを前提としているようだが、 procmail でもつかえるので使っている。 .procmailrc に bsfilter に入る前に変換をかけてしまうように入れておく。
:0 fw | /home/help/script/fetchmail/utf8filter :0 fw | bsfilter --pipe --insert-flag --insert-probability
どうだろう? だんだん賢くなってくるはずだ、しっかり育ててやってくれ。 ただ、最近は spam の本文以外のところに無意味な単語を並べ立てて学習を妨害するタイプの spam も増えていると聞く。 これらに対抗するにはどうしたらよいかは今後の課題だろう。
当方(SHIBATA Akira)は, 本サイトをご利用の際に起きるかもしれない不利益に対し, 一切責任を負いません.