SpamAssassin が何をしてるか
スパムフィルターをSpamAssassin に変えてから,DNS クエリーが増えた.
「なにこれ」と思ってだいぶ放置してたんだけど,あらためて何をしているか調べた.
ざっくり言うと
SpamAssassin は多数の外部ブラックリストサービスに依存しており,DNS クエリーを使って問い合わせる.スパマー側のMTA 構成やメール本文にもよるが,かなりクエリーを吐く.手元のメールでは 1 通を評価するのに50~70 クエリーほど.
SpamAssassin って?
Perl で書かれたアンチスパムソフトウェア.Wikipedia 読めばだいたい分かると思う.
$ spamc -R < path_to_a_spammail ... Content analysis details: (4.1 points, 4.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.0 RCVD_IN_CSS RBL: Received via a relay in Spamhaus CSS [123.57.40.62 listed in zen.spamhaus.org] 0.0 T_URIBL_SEM_FRESH_10 Contains a domain registered less than 10 days ago [URIs: ncsoft1.com] 0.0 T_URIBL_SEM_FRESH_15 Contains a domain registered less than 15 days ago [URIs: ncsoft1.com] 0.0 HTML_MESSAGE BODY: HTML included in message 0.8 BAYES_50 BODY: Bayes spam probability is 40 to 60% [score: 0.5158] 1.4 RCVD_IN_BRBL_LASTEXT RBL: RCVD_IN_BRBL_LASTEXT [123.57.40.62 listed in bb.barracudacentral.org] 0.8 RDNS_NONE Delivered to internal network by a host with no rDNS
こんな感じで,いろんなルールに基づいてスコアを加算し 閾値を超えたらスパムと判定する.
実際には,Postfix だとコンテンツフィルターに組み込む とか,procmail などでフィルターとしてspamc をくぐらせる.
何をしてるか
- spamc (クライアント) は,spamd (サーバー) に
PROCESS
やREPORT
などのコマンドを送る.その後メールヘッダ + 本文も送る - spamd は設定やルールに基づいてメールをスコアリングし,スパム判定
- spamd はspamc に,実行結果を送る.コマンドにより実行結果の前にリターンコードを送る場合がある
ルール定義は/usr/share/spamassassin/
などにあり,ルールにマッチした場合に加算されるスコア設定も同じ場所にある.
ルール実装はPerl module になっている場合も.
Rules
$ grep -hr loadplugin /etc/spamassassin
これで ロードしているプラグインが一覧できるので,動かしてみたり,コード読んだりして調べた.
- Mail::SpamAssassin::Plugin::URIDNSBL
- Mail::SpamAssassin::Plugin::Hashcash
- Mail::SpamAssassin::Plugin::SPF
- Mail::SpamAssassin::Plugin::Pyzor
- Mail::SpamAssassin::Plugin::Razor2
- Mail::SpamAssassin::Plugin::SpamCop
- Mail::SpamAssassin::Plugin::AutoLearnThreshold
- Mail::SpamAssassin::Plugin::WhiteListSubject
- Mail::SpamAssassin::Plugin::MIMEHeader
- Mail::SpamAssassin::Plugin::ReplaceTags
- Mail::SpamAssassin::Plugin::Check
- Mail::SpamAssassin::Plugin::HTTPSMismatch
- Mail::SpamAssassin::Plugin::URIDetail
- Mail::SpamAssassin::Plugin::Bayes
- Mail::SpamAssassin::Plugin::BodyEval
- Mail::SpamAssassin::Plugin::DNSEval
- Mail::SpamAssassin::Plugin::HTMLEval
- Mail::SpamAssassin::Plugin::HeaderEval
- Mail::SpamAssassin::Plugin::MIMEEval
- Mail::SpamAssassin::Plugin::RelayEval
- Mail::SpamAssassin::Plugin::URIEval
- Mail::SpamAssassin::Plugin::WLBLEval
- Mail::SpamAssassin::Plugin::VBounce
- Mail::SpamAssassin::Plugin::ImageInfo
- Mail::SpamAssassin::Plugin::DKIM
- Mail::SpamAssassin::Plugin::FreeMail
Mail::SpamAssassin::Plugin::URIDNSBL
メール本文に含まれるURI について,下のようなURI DNSBL サービスにDNS プロトコルで問い合わせる. ブラックリストに含まれていたら加点.
- multi.surbl.org
- multi.uribl.com
- dob.sibl.support-intelligence.net
- urired.spameatingmonkey.net
- uribl.spameatingmonkey.net
- fresh.spameatingmonkey.net
- fresh15.spameatingmonkey.net
- fresh10.spameatingmonkey.net
- dbl.spamhaus.org
どれもRFC5782 に基づいて実装されている.
DNS Blacklists and Whitelists (RFC5782)
かんぺきに脇道にそれるが,RFC5782 がおもしろいので簡単に紹介する.
たとえば doms.example.net というDNSBL サービスがあって,そこでは invalid.edu がブラックリスト入りしているなら
invalid.edu.doms.example.net A 127.0.0.2 invalid.edu.doms.example.net TXT "Host name used in phish"
という2つのレコードが登録される.
- A が返すアドレスは何でもいい
- TXT の中身はブラックリスト入りした理由
- A はMUST だが,TXT はSHOULD
ここまではギリギリわかるとしても,multiple sublists encode のムリヤリ感がすごい.
multi.surbl.org などがそうで,一発のクエリ
$ drill example.com.multi.surbl.org
で,6 ブラックリストの検索結果を返せるよう
2 = comes from SC 4 = comes from WS 8 = comes from PH 16 = comes from MW 32 = comes from AB 64 = comes from JP
のようなビットマスクを定義しておいて,IPv4 アドレスなら末尾1オクテットにエンコードする.
example.com.multi.surbl.org A 127.0.0.4
だったら「WS (sa-blacklist web sites) に登録されてるんだな」とわかるし
example.com.multi.surbl.org A 127.0.0.6
だったら「SC (SpamCop web sites) と WS (sa-blacklist web sites) に登録されている」とわかる.
「クライアントがデコードしないと意味を読み取れないなんて,強引なやつだ」と思うかもしれないが
- A レコードが存在 → どれかのブラックリストに登録されていることがわかる
- さらに興味があれば,ビットマスクをデコードしてリストを特定できる
- UDP なので通信コスト低
- リゾルバーが適度にキャッシュしてくれる
これはこれで良くできている.ちなみにRFC5782 はInformational.
Mail::SpamAssassin::Plugin::Hashcash
X-Hashcash
ヘッダーがついていたらHashcash に基づいて評価.
パスすれば減点.
Mail::SpamAssassin::Plugin::SPF
SPF に基づいて評価. パスすれば減点,失敗すれば加点.
Mail::SpamAssassin::Plugin::Pyzor
Pyzor を使って評価.Pyzor サーバー/クライアント間の通信はUDP. スパムデータベースに含まれていたら加点.
Pyzor クライアントがインストールされてなければ,テストされない.
Mail::SpamAssassin::Plugin::Razor2
Razor を使って評価.Razor サーバー/クライアント間の通信はHTTP. スパムデータベースに含まれていたら加点.
Razor クライアントがインストールされてなければ,テストされない.
Mail::SpamAssassin::Plugin::SpamCop
SpamCop へのレポート用プラグイン.スコアリングには関係ない.
spamd を-l
オプションで起動しておき,
$ spamc -C report < path_to_a_spammail
のようにしてレポートする.
Mail::SpamAssassin::Plugin::AutoLearnThreshold
スコアが高い(かなりスパムっぽい) or 低い(かなりハムっぽい) メールを,ベイズデータベースに自動登録する.
通常はsa-learn
コマンドなどを介して学習させる.
Mail::SpamAssassin::Plugin::WhiteListSubject
whitelist_subject
, blacklist_subject
が設定されていた場合,Subject とマッチすればそれぞれ減点,加点.
Mail::SpamAssassin::Plugin::MIMEHeader
MIME ヘッダーを扱えるようにするためのプラグイン.スコアリングには関係ない.
Mail::SpamAssassin::Plugin::ReplaceTags
正規表現パターンにタグを付け,タグでパターンを呼び出せるようにするプラグイン.スコアリングには関係ない.
Mail::SpamAssassin::Plugin::Check
テストの呼び出し元.スコアリングには直接関係ない.
Mail::SpamAssassin::Plugin::HTTPSMismatch
本文がHTML で,リンク先ホスト名とアンカーテキスト内のホスト名が異なる場合,加点.
<a href="http://foo.example.com">http://bar.example.com</a>
のようなやつ.
Mail::SpamAssassin::Plugin::URIDetail
本文に含まれるURI をパターンマッチにより評価できるようにするプラグイン.ルールを定義しないのでスコアリングには直接関係ない.
Mail::SpamAssassin::Plugin::Bayes
ベイジアンフィルターを実現するためのプラグイン.ベイズスコアは9段階に分類され,高いほうがよりスパムと判定されやすい. (0~1%: 減点,99~100%:加点)
- 0~1 %
- 1~5 %
- 5~20 %
- 20~40 %
- 40~60 %
- 60~80 %
- 80~95 %
- 95~99 %
- 99~100 %
sa-learn
コマンドを使って学習させる.
Mail::SpamAssassin::Plugin::BodyEval
本文の内容により評価する.
text/html
パートとmultipart/alternative
パートの差分が大きければ加点text/html
パートとmultipart/alternative
パートの単語数比が閾値を超えたら加点
Mail::SpamAssassin::Plugin::DNSEval
メールを送信してきたMTA のアドレスについて,下のようなRBL サービスに問い合わせる.
- bl.score.senderscore.com
- zen.spamhaus.org
- psbl.surriel.com
- list.dnswl.org
- bl.spameatingmonkey.net
- bb.barracudacentral.org
- bl.spamcop.net
- sa-trusted.bondedsender.org
- sa-accredit.habeas.com
- dnsbl.sorbs.net
- iadb.isipp.com
Envelope From のドメイン部分について,RHSBL サービスに問い合わせる.
- rhsbl.ahbl.org
ブラックリストに含まれていたら加点.
また Envelope From のドメインが A かMX レコードを持っているかどうかを調べ,持ってなければ加点.
Mail::SpamAssassin::Plugin::HTMLEval
本文のHTML にスパムっぽい点がないか評価し,該当すれば加点.
- 短すぎるコメントがある
- embedded オブジェクトがある
- 閉じタグが多すぎる
- フォントがでかい
- フォントのコントラストが低い (背景にまぎれている)
- フォントが文字ではない
- action がmailto: なフォームがある
- サイズの小さいimage タグがある
- 難読化している部分がある
- bgsound タグがある
- 不正なタグがある
- HTML が短すぎる
など.
Mail::SpamAssassin::Plugin::HeaderEval
ヘッダーにスパムっぽい点がないか評価し,該当すれば加点.
- To: がない
- Date: がずれている
- Subject: に,To: のローカルパートが含まれる
- Subject: が大文字
- 宛先に,似たアドレスが並んでいる
など.
Mail::SpamAssassin::Plugin::MIMEEval
MIME ヘッダーにスパムっぽい点がないか評価し,該当すれば加点.
- 添付ファイルがある
- 外国語のメール (よく受信する言語は設定で決めておく)
- multipart のほとんどがtext/html
など.
Mail::SpamAssassin::Plugin::RelayEval
MTA のスパマーっぽさを評価し,該当すれば加点.
- Received: にparse できない行がある
- HELO にIP アドレスが使われ,Received: を名前解決したリスト中に該当アドレスがない
- HELO にIP アドレスが使われ,Received: にIP アドレスのまま載っている
- Received: が偽装されている
- HELO の逆引きがない
など.
Mail::SpamAssassin::Plugin::URIEval
本文中のURI を評価し,スパムっぽいリンクがあれば加点.
など.
Mail::SpamAssassin::Plugin::WLBLEval
送信元,送信先アドレスがブラックリストにあれば加点し,ホワイトリストにあれば減点.
ブラックリスト,ホワイトリストはblacklist_to
, whitelist_to
, more_spam_to
, all_spam_to
などで設定する.
Mail::SpamAssassin::Plugin::VBounce
bounce しているメッセージでも,Received: にホワイトリストに含まれるホスト名があれば減点.
ホワイトリストはwhitelist_bounce_relays
で設定する.
Mail::SpamAssassin::Plugin::ImageInfo
添付画像のスパムっぽさを評価し,該当すれば加点.
- 画像数
- 画像フォーマット
- 画像サイズ
など.
Mail::SpamAssassin::Plugin::DKIM
DKIM に基づいて評価.DKIM-Signature: がついていて,invalid なら加点.
Mail::SpamAssassin::Plugin::FreeMail
メール中にフリーメールのアドレスが含まれていた場合,スパムっぽければ加点.
- Envelope From がフリーメールアドレス
- Reply-To: がフリーメールアドレス
- Subject: にフリーメールアドレスが含まれる
- Reply-To:, From:, body に異なるフリーメールアドレスが含まれる
だいぶ古い3.3.2 で試しました
Debian wheezy に入っていたものをそのまま使ったが,最新の3.4.0 にすれば結構うれしいことありそう.
- ベイズデータベースにredis が使えるので,SpamAssassin が複数ホストで動いていても大丈夫
- IPv6 対応が進んでいる
ブラックリストサービスへの問い合わせ,DNS でいいの?
DNS ゾーンの乗っ取りやキャッシュへの毒入れが流行っているので心配になるが,「多数のサービスを串刺し検索して使っているから大丈夫」って判断なのかな? よくわからない.
スパムは止まってる?
閾値の調整 + デフォルト設定 + ベイズデータベース学習で,ほぼ判定できている. false positive に振るか,false negative に振るかは好みかな.
required_score 4
いまはこんな閾値.時代に合わないルールもあるので,ブラックリスト系とベイジアンフィルターの重みを上げてもいいかもしれない.