Oracle Linux 6.2 にメール・サーバーを構築する第5章。統合型スパム・フィルターである Apache SpamAssassin を導入し、メール受信時に迷惑メールを排除できるようにする。今回の記事ではSpamAssassinが単独で動作するようにまで設定し、メール配送フローへの組込みは後ほどProcmailを使用して行う。以下は Oracle Linux 6.2 にインストールする方法だが、Red Hat Enterprise Linux (RHEL) / CentOS / Scientific Linux でも同様だろう。
まずはSpamAssassinをインストールしよう。
[root@zulu ~]# yum install spamassassin ...... ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: spamassassin x86_64 3.3.1-2.el6 ol6_latest 1.1 M ......
SpamAssassinがうまく迷惑メールを識別できるかどうかは設定ファイルの善し悪しに掛かっている。今回はTLECで以前公開されいた、日本語に対応している松田陽一氏のuser_prefsを使用し、Cronで定期的に更新することにした。
#!/bin/sh curl -so /etc/mail/spamassassin/local.cf.new http://www.flcl.org/~yoh/user_prefs RETVAL=$? if [ $RETVAL -ne 0 ]; then echo "[ERROR] Failed to download [CODE=$RETVAL]" >&2 exit 1 fi mv -f /etc/mail/spamassassin/local.cf{.new,}
[root@zulu ~]# chmod 755 /etc/cron.monthly/updatesaconf.cron
この設定ファイルを使用するにはtrusted_networks
でローカルIPアドレスなどの信頼できるIPアドレスを設定するだけだが、ボクの環境ではSpamAssassinの学習型フィルター(ベイジアン・フィルター)で迷惑メールの可能性が高いと判断された場合には間違いなく迷惑メールなので、BAYES_*
の点数をより高くに変更している。ただし、定期的な学習が必要にも関わらず実施していないユーザーが多いためにデフォルトでは低く設定されているため、後ほど紹介する定期的な学習を必ず実施しよう。また、report_safe
を0
にすると、迷惑メールと判断された場合にもヘッダーにそれが記述されるだけで外見上の変化がなくなるので、False Positive (偽陽性。迷惑メールでないメールを誤って迷惑メールと判断すること)のときの影響が少ない。
trusted_networks 192.168.0.1/16 score BAYES_80 11 score BAYES_95 13 score BAYES_99 15 report_safe 0
SpamAssassinを実行するには2通りの方法がある。一つはspamassassin
コマンドを使用して、その都度SpamAssassinを起動する方法。もう一つはspamdというSpamAssassinデーモンを事前に起動しておき、spamc
コマンドでそのデーモンに接続しに行くクライアント・サーバー方式だ。SpamAssassinはかなり重いので、spamc/spamdを使ったほうがメール配送のボトルネックにならないだろう。
まずはspamassassin
コマンドで動作検証してみよう。X-Spam-Flag:
などのヘッダーが追加されて出力されるはずだ。以下では、点数が13以上のときに迷惑メールと判断されるところで、999.9点となっているために迷惑メールと判断されている。
[root@zulu ~]# spamassassin < /usr/share/doc/spamassassin-3.3.1/sample-spam.txt X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on zulu.rewse.jp X-Spam-Flag: YES X-Spam-Level: ************************************************** X-Spam-Status: Yes, score=999.9 required=13.0 tests=CONTENT_TYPE_PRESENT,GTUBE, NO_RECEIVED,NO_RELAYS autolearn=no version=3.3.1 X-Spam-Report: * -0.1 CONTENT_TYPE_PRESENT exists:Content-Type * -0.0 NO_RELAYS Informational: message was not relayed via SMTP * 1000 GTUBE BODY: Generic Test for Unsolicited Bulk Email * -0.0 NO_RECEIVED Informational: message has no Received headers Subject: Test spam mail (GTUBE) Message-ID: Date: Wed, 23 Jul 2003 23:30:00 +0200 ......
同様にspamc/spamdでも行ってみよう。
[root@zulu ~]# service spamassassin start spamd を起動中: [ OK ] [root@zulu ~]# chkconfig spamassassin on [root@zulu ~]# spamc < /usr/share/doc/spamassassin-3.3.1/sample-spam.txt X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on zulu.rewse.jp X-Spam-Flag: YES X-Spam-Level: ************************************************** X-Spam-Status: Yes, score=999.9 required=13.0 tests=CONTENT_TYPE_PRESENT,GTUBE, NO_RECEIVED,NO_RELAYS autolearn=no version=3.3.1 X-Spam-Report: * -0.1 CONTENT_TYPE_PRESENT exists:Content-Type * -0.0 NO_RELAYS Informational: message was not relayed via SMTP * 1000 GTUBE BODY: Generic Test for Unsolicited Bulk Email * -0.0 NO_RECEIVED Informational: message has no Received headers Subject: Test spam mail (GTUBE) Message-ID: Date: Wed, 23 Jul 2003 23:30:00 +0200 ......
SpamAssassinはベイズ理論を応用した学習型フィルターも備えているので、既存のメールを学習させることで、迷惑メールっぽいメールはより迷惑メールとして認識されやすくなる。迷惑メールの傾向を学習させるには以下のコマンドのように迷惑メールの入っているメール・ボックスを引数に与える。なお、この学習結果はsa-learn
コマンドを実行したユーザーごとに $HOME/.spamassassin 内に保存される。
[tats@zulu ~]$ sa-learn --spam ~/Maildir/.Junk/cur Learned tokens from 324 message(s) (324 message(s) examined)
合わせて迷惑メールでないメール(ハム)も学習させよう。
[tats@zulu ~]$ sa-learn --ham ~/Maildir/cur Learned tokens from 4 message(s) (4 message(s) examined)
Cronで実行するために、24時間以内の迷惑メールとハム・メールを学習し、7日以上古い迷惑メールを自動で削除するスクリプトを作成した。以下のソースコードはBSDライセンスを元としたこちらのライセンスに従って再頒布および使用ができる。このスクリプトの最新版は GitHub: rewse / sa-learn-all にある。
#!/bin/sh ###################################################################### # @(#) Learning mails for SpmaAssassin # # This script learns spam and ham mails within 24 hours. Optionally, # it can purge the old spam mails 7 days ago. # # Author: Tats SHIBATA # Licenct: http://rewse.jp/license/2012.01.txt # # Copyright (c) 2012 Rewse Lab. All rights reserved. # ###################################################################### trap 'exit 1' 1 2 3 15 MAILDIR=$HOME/Maildir NEEDTO_REMOVE_DB=0 NEEDTO_PURGE=0 LEARN_PERIOD="-mtime -1" PURGE_PERIOD="-mtime +6" # {{{ show_usage show_usage() { cat <<! >&2 [USAGE] sa-learn-all [-fp] -f Learn all mails in the mailboxes -p Purge old spam mails ! exit 1 } # }}} # {{{ now now() { LANG=C date '+%b %e %T' } # }}} # {{{ Options while getopts fph OPT; do case $OPT in f) LEARN_PERIOD="" NEEDTO_REMOVE_DB=1 ;; p) NEEDTO_PURGE=1 ;; h) show_usage ;; esac done if [ `whoami` == root ]; then echo "[ERROR] The user must not be root" >&2 show_usage fi # }}} # {{{ Main echo "`now` [NOTICE] Learning begins..." if [ $NEEDTO_REMOVE_DB -eq 1 -a -f $HOME/.spamassassin ]; then echo "`now` [NOTICE] Removing the SpamAssassin database..." rm -rf $HOME/.spamassassin/bayes_* fi if [ -d $MAILDIR/cur ]; then echo "`now` [NOTICE] Learning the ham mails in INBOX..." find $MAILDIR/cur -type f $LEARN_PERIOD -print0 2> /dev/null | xargs -0 sa-learn --ham --no-sync fi echo "`now` [NOTICE] Learning the ham mails in the other boxes..." find $MAILDIR/.INBOX*/cur -type f $LEARN_PERIOD -print0 2> /dev/null | xargs -0 sa-learn --ham --no-sync if [ -d $MAILDIR/.Junk/cur ]; then echo "`now` [NOTICE] Learning the spam mails in .Junk..." find $MAILDIR/.Junk/cur -type f $LEARN_PERIOD -print0 2> /dev/null | xargs -0 sa-learn --spam --no-sync fi echo "`now` [NOTICE] Updating the SpamAssassin database..." sa-learn --sync if [ $NEEDTO_PURGE -eq 1 -a -d $MAILDIR/.Junk/cur ]; then echo "`now` [NOTICE] Purging the old spams..." find $MAILDIR/.Junk/cur -type f $PURGE_PERIOD -print0 | xargs -0 rm -f fi echo "`now` [NOTICE] Learning ended"
迷惑メールとハム・メールをそれぞれ200通以上学習をさせると、ヘッダーのX-Spam-Status:
にBAYES_00
などが表示されるようになるはずだ。