読者です 読者をやめる 読者になる 読者になる

LGTM

Looks Good To Me

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 をくぐらせる.

何をしてるか

  1. spamc (クライアント) は,spamd (サーバー) に PROCESSREPORT などのコマンドを送る.その後メールヘッダ + 本文も送る
  2. spamd は設定やルールに基づいてメールをスコアリングし,スパム判定
  3. spamd はspamc に,実行結果を送る.コマンドにより実行結果の前にリターンコードを送る場合がある

ルール定義は/usr/share/spamassassin/ などにあり,ルールにマッチした場合に加算されるスコア設定も同じ場所にある. ルール実装はPerl module になっている場合も.

Rules

$ grep -hr loadplugin /etc/spamassassin

これで ロードしているプラグインが一覧できるので,動かしてみたり,コード読んだりして調べた.

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 レコードを持っているかどうかを調べ,持ってなければ加点.

問い合わせはすべてDNS プロトコルを使う.

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 を評価し,スパムっぽいリンクがあれば加点.

  • アンカーテキストはFQDNで,リンクはIP アドレス
  • URI が8192 文字を超える

など.

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 にすれば結構うれしいことありそう.

ブラックリストサービスへの問い合わせ,DNS でいいの?

DNS ゾーンの乗っ取りやキャッシュへの毒入れが流行っているので心配になるが,「多数のサービスを串刺し検索して使っているから大丈夫」って判断なのかな? よくわからない.

スパムは止まってる?

閾値の調整 + デフォルト設定 + ベイズデータベース学習で,ほぼ判定できている. false positive に振るか,false negative に振るかは好みかな.

required_score      4

いまはこんな閾値.時代に合わないルールもあるので,ブラックリスト系とベイジアンフィルターの重みを上げてもいいかもしれない.