Exim + SpamAssassinで迷惑メール対策
迷惑メールが急増
最近中国からの迷惑メールがどんどん激しさを増してきて、受信メールの99%がスパム?な状況になってきたのでSpamAssassinを導入して対策することにしました。
実行速度を考えるとサーバープロセスとして常駐させる必要があり、スパム対策のためだけに貴重なサーバー資源を浪費するのが嫌で今まで導入をためらってきたのですが、ここまでの状況になるともはや仕事に使えない状況です。
またiPhoneには迷惑メール判定機能がないので、サーバ側で振り分けてくれると、毎度毎度「プチプチ」つぶしのごとく迷惑メールをゴミ箱に放り込む作業が不要になります。
SpamAssassinって何?
SpamAssassinは読んで字のごとく(Spam=迷惑メール Assassin=刺客)迷惑メール判定対策ソフトで、チョー有名ドコロのオープンソース・ソフトウェアです。ウェブサーバーで有名なASFのトッププロジェクトの一つでもあります。結構長い間バージョンが上がっていませんが、十分な機能と安定性があるからだと思います。
SpamAssassinをDebianへ導入
弊社サーバーは[Debian Linux][]で構築しているので、apt-getコマンド一発でインストール出来ます。
~$ sudo apt-get install spam assassin
/etc/default/spamassassinを変更します。
ENABLED=0
CRON=0
ENABLED=1
CRON=1
変更出来たら以下のコマンドで実行を開始します。
~$ sudo /etc/init.d/spamassassin start
デフォルト設定のままだと783ポートを使いますので、以下のコマンドで実行を確認出来ます。
~$ sudo lsof -i:spamd
その他にも色々あるので好みの方法で実際に動いている事を確認して下さい。
~$ netstat -a | grep spamd
~$ ps aux | grep spamd
~$ /etc/init.d/spamassassin status
Eximの設定
注)
heavyじゃないと駄目です。
この記事では既にEximは導入済みであることが前提ですが一つ注意があります。DebianのExim4には二つのdaemonパッケージ(exim4-daemon-lightとexim4-daemon-heavy)があり、SpanAssassinを利用したい場合はexim4-daemon-heavyをインストールする必要があります。もしlightをお使いの場合はheavyに置き換えて下さい。sudo apt-get install exim4-daemon-heavy
で自動的に置き換わる(squeezeで確認)ので、手間は殆どかかりませんのでご安心を。
single or multi ?
Eximは導入時に設定ファイルを単独ファイルにするか、分割ファイルにするかを選択するようになっています。これから出てくるファイル名は分割ファイル設定用ですので、単独ファイル設定の場合は修正先が異なります。
設定ファイルを変更
spamdの接続先設定
SpamAssassinの接続ポート番号を変更していなければ変更の必要はありません。/etc/exim4/conf.d/main/02_exim4-config_optionsの以下の行をコメント外して変更します。複数のspamdを設定出来るのでスケールさせる時に使うって感じでしょうかね。
# spamd_address = 127.0.0.1 783
X-Spamヘッダー追加設定
/etc/exim4/conf.d/acl/40_exim4-config_check_dataの以下のコメントをはずします。これでX-Spamヘッダーがメールボディに追加されるようになります。X-Spam_reportはかなりうざいヘッダーなので正直いらないかも。普通は見えないので問題にはならないと思いますが。
# warn
# spam = Debian-exim:true
# message = X-Spam_score: $spam_score
# X-Spam_score_int: $spam_score_int
# X-Spam_bar: $spam_bar
# X-Spam_report: $spam_report
warn
spam = Debian-exim:true
message = X-Spam_score: $spam_score
X-Spam_score_int: $spam_score_int
X-Spam_bar: $spam_bar
X-Spam_report: $spam_report
システム全体フィルタの設定
この設定はどこでも良さそうなのですが、とりあえず/etc/exim4/conf.d/main/02_exim4-config_optionsの最後のほうに書いておいて下さい。system_filterは任意のファイル名です。
transportについては/etc/exim4/conf.d/transport以下で定義済みの名前を使っています。「既存の設定じゃ満足出来ないんだよ、ジョー!」って人は独自にtransportを定義してもらって、お好きな名前に変更することも可能です。homeじゃないけどmaildirは自動で生成して欲しい等のワガママを叶えるには独自transportの定義が必要になるかもですね。参考ページ
system_filter = "/etc/exim4/system.filter"
system_filter_user = Debian-exim
system_filter_group = Debian-exim
system_filter_directory_transport = address_directory
system_filter_pipe_transport = address_pipe
system_filter_file_transport = address_file
system_filter_reply_transport = address_reply
system.filter作成
あくまでサンプルですので好みに合わせて修正をお願いします。
スパマーにメールを送り付けるサンプル
# Exim filter
if $h_X-Spam_score_int is above 99 and
foranyaddress $recipients ($thisaddress contains "@mydomain.com") then
testprint "SPAM !!"
save /var/mail/suspect_spam
mail to $thisaddress
subject "[ SPAM Witheld ] $local_part $h_subject:"
from "Company Mail Server <noreply@mydomain.com>"
text "This Message is sent automatically by e-mail software, please do not reply to it\n\nThe server suspects that a message sent to you by $h_From: is spam.\nThe original message has not been sent to you, but stored on the server.\nIf you were expecting it, please contact your system administrator with the reference\n$message_id"
finish
endif
最初はここのをまるごとコピーして使ってみたのですが、記述ミスがいくつも有ってエライ事になりました。テスト送信してもメールが届かないのでログを見てみたら案の定このざまでした。paniclogなんて初めて見ましたよ(笑)。
cat /var/log/exim4/paniclog
2013-08-31 14:43:39 1VFdx2-000692-9h Error in system filter: "and" or "or" or "then" expected near line 3 of filter file, but found "save"
いくらプライベートメールサービスだからってノーテストでの実践投入はさすがに無理がありました。焦ってリスタートとしようとしたら、以下のメッセージに追い打ちをかけられたりで実にガクブルな体験が出来ました。ちなみに取り敢えずフィルターの中身を空っぽにして、/var/log/exim4/paniclogを消してから落ち着いてリスタートすればあっさり動きます。
~$ sudo /etc/init.d/exim4 restart
Stopping MTA for restart: exim4_listener.
Restarting MTA: exim4.
ALERT: exim paniclog /var/log/exim4/paniclog has non-zero size, mail system possibly broken ... failed!
で、さすがにやばいと思ったので本家のドキュメントを読んだらちゃんとテスト方法ものってました。
exim -bF system.filter -bfl user_name -bfd mydomain.com < test.mail
メールアドレス毎のフィルタの設定
Systemwide Filterで迷惑メールを判定した後、直接特定ユーザーの迷惑メールフォルダに送り込めると思っていたのですが、それは間違いで.forward同様にメールアドレス毎に呼び出す設定を追加しないと駄目でした。てな訳で/etc/exim4/cond.d/router/にファイルを追加します。
#####################################################
### router/650_exim4-config_gotojunk_filter
#####################################################
gotojunk_filter:
debug_print = "R: gotojunk_filter for $local_part@$domain"
driver = redirect
domains = +local_domains
check_local_user
check_owner = false
file = /etc/exim4/gotojunk.filter
no_verify
no_expn
check_ancestor
allow_filter
forbid_smtp_code = true
directory_transport = address_directory
file_transport = address_file
pipe_transport = address_pipe
reply_transport = address_reply
#####################################################
### end router/650_exim4-config_gotojunk_filter
#####################################################
迷惑メールフォルダ(Maildir前提)にしまっちゃうサンプル
# Exim filter
if $h_X-Spam_score_int is not "" and
$h_X-Spam_score_int is above 96 then
save $home/Maildir/.Junk/
finish
endif
ちなみにUser Filterをテストする場合のオプションは-bF
ではなくて-bf
です。
exim -bf gotojunk.filter -bfl user_name -bfd mydomain.com < test.mail
雑感
元々がqmailからの乗り換え組だったのでeximには余り思い入れが無かったのですが、今回のSpamAssassin導入にあたって関連ドキュメントを読んで、理解が深まりちょっと愛着がわきました。それにしてもfilterが非常にプログラマブルに書ける事を知ったのは収穫でした。