Web サーバ兼 MTA なサーバを(ある組織で)共有で使っているのだけど,以前は SPAM 対策がされていた(おそらくプロプライエタリなもので,SPAM を隔離した旨メールが届いて,Web から確認するタイプのもの)のだけど,サーバリプレースに伴いその機能がなくなり,SPAM が多くなってきた(特に ML で悲惨)ので対策.
もともと procmail + fml でなんとなくシステムを作ってあるので(MTA は postfix と qmail の併用),procmail から簡単に使える SpamAssassin を利用する.タイトルどおりユーザ権限で,必要なものをどんどん入れていく.のメモ.
方針としては以下.
- Perl の Module は可能な限り CPAN を使って入れる.
- SpamAssassin も
cpan Mail::SpamAssassin
で Install できれば簡単だけど,依存するものの,特に test 段階で失敗するものがあり,SpamAssassin は手動で入れることにする.
まず,SpamAssassin の機嫌を尋ねる.
Mail-SpamAssassin-3.4.6
取得,展開- 基本的には
perl Makefile.PL
でMakefile
ができて,あとはmake; make install
という流れだけど,perl Makefile.PL
の段階で依存にするものがリストされるので,それを順番に入れていく(入れられないものは諦める)
ユーザ権限で CPAN でモジュールを入れると ~/perl5/
にファイルがインストールされていく.加えて ~/.cpan/
に管理用(や build)のファイルが溜まっていく.手元環境でインストールしたもの,以下.たぶん.順番とか怪しい.
- Net::DNS
- YAML
- NetAddr::IP
- Log::Log4perl
- IO::String
- Net::CIDER::Lite
- BSD::Resource
- Geo::IP
- GeoIP2::Database::Reader
- IP::Country::DB_File
- IO::Socket::INET6
- Mail::SPF (失敗)
- Mail::DKIM (失敗)
- Net::Patricia (失敗 → あきらめ; 8/16 改めて
cpan Net::Patricia
したら Install できた) - Net::LibIDN2 (失敗; なにかが依存していたはず)
Mail::SPF は /usr/sbin
にファイル(spfd
)を copy しようとして失敗する(権限がない; see https://rt.cpan.org/Public/Bug/Display.html?id=34768).以下のようにして $HOME/perl5/bin
にインストールするようにする.spfd
は今のところ使わないつもり.
cpan Mail::SPF (→ install でコケる)
cd ~/.cpan/build/Mail-SPF-v2.9.0-0 (build directory に移動)
sed 's,/usr/sbin,/home/myn/perl5/bin,' -i Build.PL
cpan .
Mail::DKIM はまず依存する Crypt::OpenSSL::RSA や Crypt::OpenSSL::Random のインストールでこける.これは,手元では独自に OpenSSL をインストールしていて,その OpenSSL のパスを探せず(あるいは設定できず)に嵌った.
Crypt::OpenSSL::RSA は Crypt::OpenSSL::Guess に依存して,これがパスを探してくれるが,カスタムなパスをどのように渡すが謎だったので,直接推定(?)させることにした.~/perl5/lib/perl5/Crypt/OpenSSL/Guess.pm
の @guesses
という連想配列の先頭に '/home/myn/local/bin/openssl' => '/home/myn/local',
を追加して,確実にこれが推定されるようにする.ほか rpath
関連もなにか問題があったような気がするが(~/.cpan/CPAN/MyConfig.pm
で makepl_arg
で LIBS
や INC
を自前で指定していると Crypt::OpenSSL::Guess の推定が使われないとかだったように思う; makepl_arg
の設定をなくし,Crypt::OpenSSL::Guess で正しく推定できれば LD_RUN_PATH
付きで build されていたような気がする).
Mail::DKIM が依存するものがインストールできたとして,次は Mail::DKIM の test でコケる.t/policy.t
と t/public_key.t
のテストでコケていて,
cd ~/.cpan/build/Mail-DKIM-1.20200907-0
% perl -Ilib t/policy.t
1..19
ok 1 - new() works
ok 2 - parse() works
DNS query timeout for _domainkey.policy.test.authmilter.org at lib/Mail/DKIM/DNS.pm line 100.
これ,8.8.8.8
(Google の Public DNS) および 1.1.1.1
(Cloudflare の Public DNS) を DNS サーバ(リゾルバ)としてテストするのが原因(ゲートウェイをパケットが通らない環境なので...).それぞれのテストファイルのリゾルバ(のリスト)の箇所を手元の /etc/resolv.conf
に合わせて修正して解決.
Net::LibIDN2 は,そもそも libidn2 (IDN (internationalized domain names) の encode/decode ライブラリ)を install するところから(システム側にヘッダファイルが用意されていない...).
wget https://ftp.gnu.org/gnu/libidn/libidn2-2.3.2.tar.gz
tar zxfv libidn2-2.3.2.tar.gz
cd libidn2-2.3.2
./configure --prefix=/home/myn/local
make
make install
そのうえで cpan Net::LibIDN2
が上記 install した libidn2 を見つけられずに当然ハマる.上記 libidn2.so の symbol が見つけられず perl module LibIDN2.so
が load できない,とか.以下でなんとかする.cpan
する前に ./Build
したかも.いずれにせよ --extra_linker_flags
でしていた option 付きで link された LibIDN2.so
が ~/perl5/lib/perl5/x86_64-linux-thread-multi/auto/Net/LibIDN2/LibIDN2.so
にインストールされれば OK.ldd LibIDN2.so
で自前インストールの libidn2.so に link されているか確認できる.
cd .cpan/build/Net-LibIDN2-1.01-0
perl Build.PL --extra_compiler_flags=-I/home/myn/local/include --extra_linker_flags='-L/home/myn/local/lib -lidn2 -Wl,--rpath,/home/myn/local/lib'
cpan .
色々整った段階でようやく Mail-SpamAssassin をインストール.
tar jxfv Mail-SpamAssassin-3.4.6.tar.bz2
cd Mail-SpamAssassin-3.4.6
perl Makefile.PL CONTACT_ADDRESS=admin@example.com
make
make install
~/perl5/bin/spamassassin
に install される.CONTACT_ADDRESS
を指定しないとインタラクティブに聞かれる.
SpamAssassin 設定
もう疲れたので,手短に.
% spamassassin -D < mail_file
とかでテストする.はじめは rule が存在しないので sa-update
で取得する(かつ cron を仕込んでおく).なお ~/perl5/var/spamassassin/3.004006/
に rule ファイルが置かれる.
~/.spamassassin/user_prefs
にユーザ設定を置く.
required_score 10
score SUBJECT_ENCODED_TWICE 0
score DNS_FROM_AHBL_RHSBL 0
report_safe 0
internal_networks 1XX.XX.XX.XX....
whitelist_from ...@....
SPAM 判定のしきい値は高め(10; default は 5)に設定した.スコア 0 にしているものは,以前そのような設定にしたもので,今でもこのルールがあるかどうかは確認していない.internal_networks
にはこのメールサーバに到達するために通常通過するサーバをリストする(それらの IP address の良し悪しを評価しなくなる; 評価すると SPAM Score が通常は下がる).
whitelist_from
は welcomelist_from
に将来的に(Target Milestone: 4.0.0)変更になる様子だが,現時点(3.4.6)では welcomelist_from
と書くと parse error になる.なお,blacklist_from
は blocklist_from
になる.ただし,spamassassin の report では USER_IN_BLACKLIST DEPRECATED: See USER_IN_BLOCKLIST
とか表示されるので感じ悪い.
あとは procmail から spamassassin を filter として呼び出して,その結果に応じて処理をする.procmail をローカル配送に使っていないので,無理やり procmail を呼び出すようにしていて,
[~/.qmail-hoge]
|/usr/bin/procmail /home/myn/spool/procmail/hoge
そのレシピファイルで spamassassin を通して,その結果に応じて処理を変える.以下では spam@example.com
に転送しているが,これはローカル配送を想定していて,結果同じメールサーバ(example.com)の Maildir に保存されていく,みないな設定にした.なお spamassassin.lock
のロックファイルは $HOME/spamassassin.lock
に作成される.
[/home/myn/spool/procmail/hoge]
LOGFILE=$HOME/spool/procmail/log/hoge.`date +%Y-%m`
SENDMAIL=/var/qmail/bin/sendmail
DEFAULT=$HOME/Maildir/.myn/
:0fw: spamassassin.lock
* < 10000000
| /home/myn/perl5/bin/spamassassin
:0
* ^X-Spam-Flag: YES
!spam@example.com
:0c
!myn@example.com
あと,はじめはあまり賢くないので,sa-learn --ham
および sa-learn --spam
で HAM (!SPAM)と SPAM の違いを覚えさせる.ある程度覚えるとあとは autolearn してくれる(はず).
追記 (2021/8/15)
高速化のために re2c
をインストールして,rule ファイルを native code にコンパイルできるようにしていたのだけど,手動で sa-compile
する必要があるのを忘れていた(sa-update
とともに cron に仕込む).
ただし,手元の CPAN 環境では,手動で実行した感じ以下のようにエラーで落ちる.
Aug 15 14:15:06.345 [4115915] info: generic: base extraction starting. this can take a while...
Aug 15 14:15:06.345 [4115915] info: generic: extracting from rules of type body_0
100% [==========================================================================================] 5277.67 rules/sec 00m00s DONE
100% [==========================================================================================] 4722.65 bases/sec 00m00s DONE
Aug 15 14:15:07.069 [4115915] info: body_0: 1328 base strings extracted in 1 seconds
cd /tmp/.spamassassin4115915hkQrfJtmp
reading bases_body_0.in
cd Mail-SpamAssassin-CompiledRegexps-body_0
re2c -i -b -o scanner1.c scanner1.re
re2c -i -b -o scanner2.c scanner2.re
re2c -i -b -o scanner3.c scanner3.re
re2c -i -b -o scanner4.c scanner4.re
re2c -i -b -o scanner5.c scanner5.re
re2c -i -b -o scanner6.c scanner6.re
re2c -i -b -o scanner7.c scanner7.re
/usr/bin/perl Makefile.PL PREFIX=/tmp/.spamassassin4115915hkQrfJtmp/ignored INSTALLSITEARCH=/home/myn/perl5/var/spamassassin/compiled/5.026/3.004006
Only one of PREFIX or INSTALL_BASE can be given. Not both.
command failed: exit 25
CPAN の初期設定段階で ~/.zshrc
に以下が書かれていたのが原因の様子.ということで PERL_MM_OPT= sa-compile
でうまく compile できる.
PERL_MM_OPT="INSTALL_BASE=/home/myn/perl5"; export PERL_MM_OPT;
踏まえて仕込んだ cron (から呼ばれる script)はだいたい以下のような感じ.case 文は Debian の /etc/cron.daily/spamassassin
を参考にした.
/home/myn/perl5/bin/sa-update
case $? in
0)
# got updates!
PERL_MM_OPT= sa-compile
;;
1)
# no updates
;;
2)
# lint failed!
;;
*)
echo "sa-update failed for unknown reasons" 1>&2
;;
esac
コンパイルされたものは ~/perl5/var/spamassassin/compiled/
に置かれることになる.
追記 (2021/8/16)
書き忘れていた.コンパイルされた rule を利用するには ~/perl5/etc/mail/spamassassin/v320.pre
の以下の行のコメントアウトを外す.
loadplugin Mail::SpamAssassin::Plugin::Rule2XSBody