procmail + ezmlm


1. 目的

メーリングリスト管理ツールである ezmlm を用いたメーリングリストに送られるスパムは
一つのアドレスでたくさんの人に送られてしまうのでやっかいである。

ezmlm の設定を変更して登録メンバーのみ投稿可にすればスパムはまず来なくなるが、
それができないメーリングリストもある。

そこで、procmail を用いたスパムフィルターを作成し、そういったスパムの撃墜を試みた。
以下、その手順及び設定の中身である.

2. 設定

2.1 .qmail

ezmlm が作成する .qmail (実際は dir/editor にシンボリックリンクがはられている) の
ezmlm-reject や ezmlm-issubn と ezmlm-send の間に以下の行を追加。
簡単に説明すると、procmail の処理が返すステータスコードが 0 以外なら
ezmlm はステータスコード 100 を受け取り (exit 100) 、次の ezmlm-send の処理は行われない。
この事を利用すれば procmail 以外のスパムフィルターを利用する事も可能だろう。

|bouncesaying 'I do not accept' except /usr/local/bin/iftocc hoge-ml@foo.orz
|/usr/local/bin/ezmlm/ezmlm-reject -T /home/hoge/ml
|/usr/local/bin/ezmlm/ezmlm-issubn -n /home/hoge/ml/deny || {
  echo "Sorry, I've been told to reject your posts.
Contact hoge-ml-owner@foo.orz if you have questions about this (#5.7.2)"; exit 100
}
|preline /usr/bin/procmail -m /home/hoge/.procmailrc || exit 100
|/usr/local/bin/ezmlm/ezmlm-send /home/hoge/ml
|/usr/local/bin/ezmlm/ezmlm-warn /home/hoge/ml || exit 0

設定ファイルの編集中に届いたメールが消えてしまうトラブルを回避するために
あらかじめメールの配送を停めておく事を推奨する。

$ chmod +t ~/.qmail で配送停止
$ chmod -t ~/.qmail で配送再開

2.2 .procmailrc

基本的な考え方は procmail メモ に書いた内容と同じなので先にそちらを読むことを推奨する。

違いは、スパムと判定されたらゴミ箱に捨てるのではなく
ステータスコード 1 を返すように設定されていることである。
従って、最初に定義する変数が多少異なっている。

SHELL=/bin/bash
PATH=/bin:/usr/bin:/usr/local/bin
ADDRESS=hoge-ml@foo.orz
LOGFILE=$HOME/procmail/`date +%Y-%m`.log
VERBOSE=off
LOCKFILE=$HOME/procmail/.lockfile
DEFAULT=/dev/null
EXITCODE=""
TRAP="if [ -f $HOME/procmail/spam ] ; then rm -f $HOME/procmail/spam; exit 1; fi"

$EXITCODE は procmail が処理が終了した時に返すステータスコードで、
空にして定義すると $TRAP の処理の結果が入る。
$TRAP は procmail の処理が終了した後に起動されるシェルで、
処理中に出来る一時ファイルの削除などを行うことが出来る。

当初はスパムの判定結果をある変数に格納して、それを使って $TRAP の
ステータスコードを決めようとしたが、上手くいかなかったので
空ファイルを作ってそれの有無で判定を行っている。

スパムの判定法は procmail メモ と同じなのでここでは全ての判定条件を載せていない。

# 逆引きできないホストを中継してきたメールは撃墜
:0 f
* ^Received: .*\(unknown
|formail -A "X-Spam: no Domain"

# spam と判定されたら空ファイルを作る
:0
* ^X-Spam:
|touch $HOME/procmail/spam

3. 応用編

上記の方法でもスパムフィルターとして充分に機能するが、
スパム撃墜ログが残らない上、判定のためだけに空ファイルを作るのは
あまりスマートな方法とは言えないと思う。

そこでヘッダのログ抽出とスパム判定を行う perl スクリプトを作成した。
さらに、このログを元に撃墜レポートを作成するシェルスクリプトも作成し、
cron を利用して自動送信するよう設定を行った。

3.1 ml_header.pl を用いたログ作成及び、スパム判定

3.1.1 ml_header.pl の仕様

メールのヘッダ出力とスパム判定を行う perl スクリプト。
作者は森川氏で, 使用するには jcode.plmimer.pl、mimew.pl が必要。

メール全文 (ヘッダ、本文込み) を標準入力で受け取り、ヘッダのみを標準出力に出力する。

また、-G オプションを付けるとヘッダに特定の文字列が含まれているかどうかを
ステータスコードで返す。

3.1.2 .procmailrc の設定

基本的には 2.2 と同じ。
違うのは TRAP と最後の処理のみ。

2.2 の設定
TRAP="if [ -f $HOME/procmail/spam ] ; then rm -f $HOME/procmail/spam; exit 1; fi"

# spam と判定されたら空ファイルを作る
:0
* ^X-Spam:
|touch $HOME/procmail/spam

3.1.2 の設定
TRAP="$HOME/bin/ml_header.pl -G ^X-Spam"

# ヘッダをログに保存
:0
|{ $HOME/bin/ml_header.pl; echo; } >> $HOME/procmail/`date +%Y-%m`.log

3.2 procmail-report.sh + cron を用いたスパム撃墜レポートの自動送信

3.2.1 procmail-report.sh の仕様

ml_header.pl で作成されたログを元にスパム撃墜レポートを作成し、
メールで送信するシェルスクリプト。
使用するには GNU 版 date、grep、bc、sort、uniq、mail コマンドが必要。

cron を用いて毎月一日に procmail-report.sh を実行させると、
先月のスパム撃墜レポートを作成、指定されたアドレスに送信する。

3.3 スクリプトの公開

あるメーリングリストで実際に使用しているスクリプトを公開する。
なお、ml_header.pl の作者は森川氏だが、 許可を貰ったのでここで再配布を行う。

使用、改変、再配布は自己責任の範囲でご自由に。
gzip で圧縮してある。

使用する際にはコマンドパスや変数を適宜書き換える事。

3.3.1 ml_header.pl

Ver. 0.1 (2005/11/04)

ml_header.pl_0.1.gz (904 byte)

3.3.2 procmail-report.sh

Ver. 0.1.1 (2006/04/03)

procmail-report.sh_0.1.1.gz (818 byte)

2004/06/22 作成