メール交換機でのスパム排除 - Hatuka*nezumi

メール交換機でのスパム排除
外部から来る SMTP ト ランザクションで不要メールを拒否するには
Tor Slettnes1
Joost De Cock2
Devdas Bhagat3
池田, 荘児5
4th July 2005
1
著者
技術面の校閲
3
技術面の校閲
4
言語面の校閲
5
日本語訳
2
Tom Wright4
Keywords
anti-spam, スパム対策, anti-virus, ウィルス対策, bogus virus warnings, いんちきウィルス警告, collateral
spam, 巻き添えスパム, 後方散乱メール , delivery status notification, 配送状況通知, DSN, Exim, Exim4,
Exiscan, Exiscan-ACL, greylisting, グレーリスト法, junk mail, 不要メール , SA-Exim, SMTP, spam,
スパム, Spamassassin, teergrubing, タール坑法, transaction delay, トランザクションの遅延
はじめに
この文書の目的
この文書では、 メール交換機 (MX ホスト ) での外部から来る SMTP トランザクションの間に スパムや
マルウェアを取り除くための、 効果が高く悪影響が少ないさまざまな方法について論ずる。 これらの方法
では、 いわゆる巻き添えスパム [78] を除去することも重視している。
議論はおおむね概念的であるが、 Exim MTA と特定のソフトウェアツールを使ったサンプル実装も提供
する。 これには、議論で述べた以外にもさまざ まな工夫をもりこんである。
対象者
この文書が意図する対象者はメールシステム管理者であり、SMTP, MTA/MDA/MUA, DNS/rDNS, MX
レコード のような略号にはなじみがあるものとする。 メールリーダ (Evolution, Thunderbird, Mail.app,
Outlook Express のような) でスパムを排除するための解決策を探しているエンド ユーザは この文書の対
象ではないが、 自分のド メイン (企業、学校、ISP...) のメールシステム管理者に この文書の存在を知らせ
ることができるであろう。
この文書の新版
この文書の最新版は http://slett.net/spam-filtering-for-mx/ で見つかる。訂正や追補がないか、
定期的に確認してほしい。
改版履歴
改訂履歴
改訂 1.0
2004-09-08
TS
2004-09-07
TS
最初の一般公開。
改訂 0.18
Tom Wright による 2 度目の言語面の校閲を反映。
改訂 0.17
2004-09-06
TS
Tom Wright による言語面の校閲を反映。
改訂 0.16
2004-08-13
TS
Devdas Bhagat の第 3 次の変更を反映。
改訂 0.15
2004-08-04
TS
Devdas Bhagat の技術面の校閲に伴う第 3 次の変更を反映。
改訂 0.14
2004-08-01
TS
Devdas Bhagat からの技術面の校閲での意見/訂正を反映。
改訂 0.13
2004-08-01
TS
Joost De Cock からの技術面の校閲を反映。
i
改訂 0.12
2004-07-27
TS
"論争についての注" [A Note on Controversies] の節を、 より主張のはっきりした "善玉、悪玉、
卑劣漢" の節で置き換え。 また、DNS ブロックリストについての文章を書き換え。 Seymour J. Metz
からの若干の訂正。
改訂 0.11
2004-07-19
TS
Rick Stewart からの RMX++ についての意見を反映。 "テクニック" と "検討事項" の順序を入れ
換え。 Exim による実装での書体の軽微な修正。
改訂 0.10
2004-07-16
TS
<?dbhtml..?> タグを追加して、生成される HTML ファイル名を制御 --- Google などでのリンク切
れを防げる。 "転送されてきたメール " と "ユーザの設定" の順序を入れ換え。 Tony Finch からの
Bayes 式フィルタ についての訂正を反映; Johannes Berg によって、 Subject: 、Date: 、MessageID: ヘッダの検査をコメントアウト ; Alan Flavell からの助言で、SMTP 遅延の処理時間を減らす。
改訂 0.09
2004-07-13
TS
エンヴェロープ送信者のシグネチャとメーリングリストサーバの問題と、 ホスト /ド メインごとに任
意であるこのようなシグネチャを各々のユーザが作る方式 の部分を推敲。 "検討事項" の節を独立
の章に移動 --- "他の SMTP サーバへのアクセスを阻止する" 、 "ユーザの設定" 、"転送されてきた
メール " の節を追加。 シグネチャを生成する機構についての Matthew Byng-Maddick の意見、 Cris
Edwards の送信者の呼出し 確認法についての意見、 Hadmut Danisch の RMX++ その他の話題につ
いての意見を反映。 許諾条項を変更 (GFDL から GPL へ)。
改訂 0.08
2004-07-09
TS
Exim による実装への追加: Tollef Fog Heen からの助言により、 SpamAssassin のためのユーザ
ごとの設定とデータについての節を追加。 Exiscan-ACL による SPF 検査を追加。 Sam Michaels か
らの訂正。
改訂 0.07
2004-07-08
TS
Exim のエンヴェロープ 送信者のシグネチャの例に訂正。 また、Christian Balzer の助言により、
この仕様にユーザの "オプト イン " 対応を追加。
改訂 0.06
2004-07-08
TS
Exim/MySQL のグレーリスト法の実装と、 Johannes Berg によるさまざ まな訂正を反映。 "送信者
認証方式" を 2 段階上げて、テクニックの章の最上位の節にした。 空のエンヴェロープ送信者のため
の、DATA の後でのグレーリスト法を追加。 SpamAssassin の設定を、Exim の例に合うように追加。
Dominik Ruff, Mark Valites, "Andrew" at Supernews からの訂正を反映。
改訂 0.05
2004-07-07
TS
(中身のない) Sendmail による実装はいまのところ外す、
改訂 0.04
2004-07-06
TS
レ イアウトを若干再構成:
"SMTP の時点での排除" 、"SMTP の入門" 、"検討事項" は単一の "背景"
の章にまとめた。 Exim による実装 の中の "ACL の構築" の節は分離して最上位の節に。 SPF 以外
の送信者認証方式を追加: Microsoft Caller-ID for E-mail と RMX++。 Ken Raeburn からの
意見を反映。
改訂 0.03
2004-07-02
TS
複数の受入用メール交換機についての議論を追加; 送信者の呼出し確認法に関係する軽微な訂正。
改訂 0.02
2004-06-30
TS
2004-06-16
TS
Exim による実装を付録として追加
改訂 0.01
最初の草稿。
ii
謝辞
[改版履歴] [i] に記してあるとおり、 おおぜいの方々からフィード バック、訂正、寄贈を戴いている。 感
謝する。
以下は、この文書にツールやアイデ ィアを提供して下さった方々や組織の一部である (順不同)。
a puremagic.com>。 グレーリスト法を発案し 、 その白書を著した。
• Evan Harris <eharris°
a hiss.org>。 タール坑法を発案したとされる。
• Axel Zinser <fifi°
• SPF1 、 RMX++2 やその他の[送信者認証方式] [17] の開発者の方々。
• DCC3 、 Razor4 、 Pyzor5 のような、 分散型で協調型の不要メールシグネチャ集積システムの作成
者とメンテナの方々。
• SpamCop6 、 SpamHaus7 、 SORBS8 、 CBL9 、 その他たくさん 10 のような、 さまざ まな DNS ブ
ロックリストやホワイトリストの作成者とメンテナの方々。
• SpamAssassin11 の開発者の方々12 。 彼らは、さまざまなスパム排除テクニックの開発と、 洗練され
たヒューリスティックに基づくツールへの統合に長足の進歩をもたらした。
a timj.co.uk>。 いんちきウィルス警告の一覧をまとめ、 メンテナンスして、
• Tim Jackson <tim°
SpamAssassin で利用できるようにした。
a cus.cam.ac.uk>
• 素晴らしい Exim MTA を開発した、 数々の明敏な方々: Philip Hazel <ph10°
a duncanthrax.net> (SMTP 時点でのコンテンツ検査のための
( メンテナ) 、 Tom Kistner <tom°
a debian.org> (Exim 4 の Debian
Exiscan-ACL パッチを書いた) 、 Andreas Metzler <ametzler°
パッケージをビルド するという、素晴らしい働きをした) 、 ほか。
• スパムの蔓延に抗するためのアイデ ィア、ソフトウェア、 その他のテクニックを提供して下さった、
その他数多くの方々。
• 有用なコミュニケーションツールとしての電子メールを取り戻すことに関心を寄せ、 この文書を読ん
で下さっている、あなた。
フィード バック
この文書で概説しているテクニックについての実地の体験や、 その他のさまざ まな意見や疑問や助言を
聞かせてもらうこと、 寄贈をいただけることは、私にとって喜ばしいことだ。 <[email protected]> に電子
メールを送ってほしい13 。
他のメール転送エージェント [79] (Sendmail や Postfix のような ) での実装を提供できる方は、知らせて
ほしい。
1 http://spf.pobox.com/
2 http://www.danisch.de/work/security/antispam.html
3 http://rhyolite.com/anti-spam/dcc/
4 http://razor.sf.net/
5 http://pyzor.sf.net/
6 http://www.spamcop.net/
7 http://www.spamhaus.org/
8 http://www.sorbs.net/
9 http://cbl.abuseat.org/
10 http://moensted.dk/spam/
11 http://www.spamassassin.org/
12 http://www.spamassassin.org/full/3.0.x/dist/CREDITS
13 [訳注]
著者によると、日本語は読めないので、 英語 (かノルウェイ語 :-) がよいそうである。
iii
翻訳
翻訳はまだない。やりたい方は、知らせてほしい。
著作権情報
[訳注: 本節は訳さない。]
c
Copyright °2004
Tor Slettnes.
This document is free software; you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This document is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the license is included in 付録 B
[81].
Read The GNU Manifesto14 if you want to know why this license was chosen for this book.
The logos, trademarks and symbols used in this book are the properties of their respective owners.
日本語訳について
c
Japanese translation is copyright °2005
by IKEDA Soji.
当日本語訳の翻訳物に関する著作隣接権は、池田荘児に帰属する。
当日本語訳の再配布等の条件は、原文の条件に準ずる。
必要なこと
この文書で説明するテクニックでは、 自分が電子メールを受け取るインターネットド メインの 内部行き
のメール交換機 [79] のシステムへアクセスできることを前提にしている。 つまり、自分でソフトウェアを
インストールしたり、 自分でそのシステムのメール転送エージェント [79] の設定ファイルを変更したりで
きなければいけない。
この文書での議論は、総じて概念的ではあるが 、 多くの異なる MTA で実現可能なものだから、Exim 4
のサンプル実装も提供している。 この実装ではまた、 SpamAssassin15 のようなほかのソフトウェアツー
ルを組み込んでいる。 詳細は付録 A [29] を見てほしい。
この文書の凡例
文中に現れる書体と用字は以下のとおり。
この文書の構成
この文書は、以下の章からなる:
[背景] [1] SMTP の時点での排除、および SMTP の一般的な紹介。
14 http://www.fsf.org/gnu/manifesto.html
15 http://www.spamassassin.org/
iv
Table 1: 書体と用字
書体
意味
「引用文」
発言の引用、計算機の出力の引用。
terminal view
端末から写し取った計算機の入出力そのもの。 普
通は薄灰色の背景で表示される。
command
コマンド ラインに入力されるコマンド の名前。
VARIABLE
変数の名前、変数の内容を示す。 例: $VARNAME
option
コマンド のオプション。 例: 「 ls コマンド の -a
オプション 」
。
コマンド の引数。例: 「 man ls を読め」
。
argument
コマンド の書式や一般的な用法。 独立した行で表
command options arguments
記する。
filename
ファイルやディレクトリの名前。 例えば 「 /usr/
bin デ ィレクトリへ移動する。」
キーボードで打つキー。 例: 「終了するには Q を
Key
タイプする」
。
Button
OK ボタンのように、 クリックできるグラフィカ
ルなボタン。
メニュー → 選択
グラフィカルなメニューから選択できるもの、例
えば : 「 Web ブラウザで ヘルプ → Mozilla につ
いて を選択する。」
用語
重要な用語や概念: 「 Linux のカーネルは、 シス
テムの心臓部だ。」
この案内の中の関連する話題。
[用語集] [75] を見よ
著者 http://slett.net/gallery/2003-05/
外部の Web リソースへのクリックできるリンク。
IMG 1655
[テクニック ] [7] SMTP トランザクションで不要メールを阻止するさまざ まな方法。
[検討事項] [25] トランザクションの時点での排除に関する課題。
[質問と回答] [27] あなたの疑問に先回りして答えてしまおうという試み。
付録 A [29] では、Exim によるサンプル実装を提供する。
v
目次
はじめに
この文書の目的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
対象者 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
この文書の新版 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
改版履歴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
謝辞 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
フィード バック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
翻訳 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
著作権情報 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
日本語訳について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
i
i
i
i
i
iii
iii
iv
iv
iv
必要なこと
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
この文書の凡例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iv
iv
この文書の構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iv
第 1 章 背景
1
SMTP トランザクションの間にメールを排除する理由 . . . . . . . . . . . . . . . . . . . . .
1.1.1 現状 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1.2 原因 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1
1
1.2
1.1.3 解決策 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
善玉、悪玉、卑劣漢 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
3
1.3
SMTP トランザクション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
1.1
第 2 章 テクニック
2.1
2.2
2.3
7
SMTP トランザクションの遅延 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
DNS による検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.1 DNS によるブラックリスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
8
9
2.2.2 DNS による整合性検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SMTP での検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
10
ハロー (HELO/EHLO) の検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
10
11
2.3.1
2.3.1.1
2.3.1.2
2.3.2
2.3.3
HELO/EHLO の簡易な構文検査 . . . . . . . . . . . . . . . . . . . . . . .
ハロー挨拶を DNS で確認する . . . . . . . . . . . . . . . . . . . . . . . .
送信者アドレスの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3.2.1
送信者アドレスの構文検査 . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3.2.2
2.3.2.3
2.3.2.4
詐称の検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
送信者アドレスの簡易な検証法 . . . . . . . . . . . . . . . . . . . . . . . .
送信者呼出し確認法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
受信者アドレスの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3.3.1
開放型リレーの防止 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3.3.2
2.3.3.3
2.3.3.4
受信者アドレスの確認 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
12
12
12
12
13
13
受信者が一つの DSN だけを受け付ける . . . . . . . . . . . . . . . . . . .
13
14
15
2.4 グレーリスト法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4.1 どのように動作するか . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
15
複数のメール交換機でのグレーリスト法 . . . . . . . . . . . . . . . . . . . . . . . .
16
16
2.4.2
2.4.3
辞書攻撃の防止 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
vii
2.5
送信者認証方式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sender Policy Framework (SPF) . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Microsoft Caller-ID for E-Mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
17
18
2.5.3 RMX++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
メッセージデータの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.1 ヘッダの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
18
19
ヘッダがない . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ヘッダアドレスの構文検査 . . . . . . . . . . . . . . . . . . . . . . . . . .
19
19
2.6.1.3 ヘッダアドレスの簡易な検証法 . . . . . . . . . . . . . . . . . . . . . . . .
2.6.1.4 ヘッダアドレス呼出し確認法 . . . . . . . . . . . . . . . . . . . . . . . . .
不要メールシグネチャ集積システム . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
19
19
2.6.3
2.6.4
バイナリゴ ミデータの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
20
2.6.5
2.6.6
2.6.7
添付ファイルの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.5.1
2.5.2
2.6
2.6.1.1
2.6.1.2
2.6.2
2.7
MIME の検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ウィルス検出ソフトウェア . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
スパム検出ソフトウェア . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
巻き添えスパムの阻止 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.1
いんちきウィルス警告を排除する . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.2
2.7.3
2.7.4
自分のド メインの SPF 情報を公開する . . . . . . . . . . . . . . . . . . . . . . . . .
エンヴェロープ送信者のシグネチャ . . . . . . . . . . . . . . . . . . . . . . . . . . .
実在するユーザへのバウンスだけを受け付ける . . . . . . . . . . . . . . . . . . . . .
第 3 章 検討事項
20
21
21
22
22
22
22
24
25
25
3.1
複数の受入用メール交換機 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2
3.3
他の SMTP サーバへのアクセスを阻止する . . . . . . . . . . . . . . . . . . . . . . . . . . .
転送されてきたメール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
25
3.4
ユーザごとの設定とデータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
第 4 章 質問と回答
27
付録 A Exim による実装
A.1 必須事項 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
29
A.2 Exim の設定ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.2.1 アクセス制御リスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
29
A.2.2 展開 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.3 オプションと設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.4 ACL の構築 — 第一段階 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
30
31
A.4.1 acl connect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.4.2 acl helo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
32
A.4.3 acl mail from . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.4.4 acl rcpt to . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.4.5 acl data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
32
36
A.5 SMTP トランザクションの遅延を追加する . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.5.1 簡易な方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
37
A.5.2 選択的な遅延 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.6 グレーリスト法への対応を追加する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.6.1 greylistd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
41
41
A.6.2 MySQL による実装 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.7 SPF の検査を追加する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
46
viii
A.7.1 Exiscan-ACL による SPF の検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.7.2 Mail::SPF::Query による SPF の検査 . . . . . . . . . . . . . . . . . . . . . . . . . .
A.8 MIME とファイル型の検査を追加する . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
47
48
A.9 ウィルス対策ソフトウェアを追加する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.10 SpamAssassin を追加する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.10.1 Exiscan から SpamAssassin を呼び出す . . . . . . . . . . . . . . . . . . . . . . . . .
49
49
49
A.10.2 SpamAssassin の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.10.3 ユーザごとの設定とデータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
51
A.10.3.1 Exim が配送ごとに一つの受信者しか受け付けないようにする . . . . . . .
A.10.3.2 SpamAssassin に受信者のユーザ名を渡す . . . . . . . . . . . . . . . . . .
A.10.3.3 SpamAssassin でユーザごとの設定を有効にする . . . . . . . . . . . . . . .
51
51
52
A.11 エンヴェロープ送信者のシグネチャを追加する . . . . . . . . . . . . . . . . . . . . . . . . .
A.11.1 送信者アドレスに署名するためのトランスポートを作成する . . . . . . . . . . . . .
53
53
A.11.2 リモート配送のためのルータを新たに作成する . . . . . . . . . . . . . . . . . . . . .
A.11.3 ローカル配送のための転向ルータを新たに作成する . . . . . . . . . . . . . . . . . .
A.11.4 ACL シグネチャの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
55
55
A.12 実在するユーザへのバウンスだけを受け付ける . . . . . . . . . . . . . . . . . . . . . . . . .
A.12.1 受信者のメールボックスの検査 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
56
A.12.2 エイリアスルータでの空送信者の検査 . . . . . . . . . . . . . . . . . . . . . . . . .
A.13 転送されてきたメールを通す . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.14 できあがった ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
58
60
A.14.1 acl connect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.14.2 acl helo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
61
A.14.3 acl mail from . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.14.4 acl rcpt to . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.14.5 acl data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
64
69
用語集
79
付録 B GNU General Public License
B.1 Preamble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
81
B.2 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
B.2.1 Section 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2.2 Section 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
82
82
B.2.3 Section 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2.4 Section 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
82
83
B.2.5 Section 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2.6 Section 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2.7 Section 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
83
84
84
B.2.8 Section 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2.9 Section 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2.10 Section 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
84
84
84
B.2.11 Section 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2.12 NO WARRANTY Section 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
85
B.2.13 Section 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.3 How to Apply These Terms to Your New Programs . . . . . . . . . . . . . . . . . . . . . .
85
85
ix
第 1 章 背景
概要
ここでは、 メールのルーティングや配送の段階での通常のアプローチによるのではなく、 外部から来
る SMTP トランザクションの間にメールを排除することの利点を説明する。 また、SMTP トランザク
ションの簡単な紹介もする。
1.1
1.1.1
SMTPト ランザクションの間にメールを排除する理由
現状
スパムを受け取ってる人、手を挙げて。手は挙げたままにしといてね。
コンピュータウィルスやその他のマルウェア1を受け取ってる人も、手を挙げて。
自分が送ってもいないメッセージについて、 いんちきな配送状況通知 [78] (DSN) (「 Message Undeliv-
erable 」 というようなの) とか、
「 Virus found 」 とか、 「 Please confirm delivery 」 などのメッセージを
いっぱい受け取ってる人も、手を挙げて。 こういうものを巻き添えスパム [78] と言う。
いま言ったものは、実に厄介だ。なぜなら、 「標準的な」 スパムやマルウェアより取り除きにくいし 、
メッセージヘッダを読み解く神業を身につけていない受信者だと、 このようなメッセージがあると混乱し
てしまうからだ。 これがウィルス警告だった場合は、 受信者側に不必要な心配をさせてしまうことも、よ
くあることだ — これが常態化すると、 多くのひとはこのようなメッセージをすべて無視するようになり、
そのため、真っ当な DSN まで見落とすことになる。
じゃあ最後。スパム検出ソフトウェアやウィルス検出ソフトウェアの設定ミスで、 真っ当なメールが虚
空のかなたに消え去っちゃったことのある人は、 — 両足あげて。
さっきから立っていて、いまでも立っていられる人がいるとしたら、 その人は、自分のメールがど うなっ
ているかをちゃんと把握できていないのだろう。 どんなやりかたでスパム排除をやってきた人でも (DNS
ブラックリスト — SpamHaus, SPEWS, SORBS... — のような素朴な排除テクニックを実践してきた人は
もちろん 、 メールをメールリーダのゴ ミ箱フォルダに手作業で移動しているだけの人であっても) 、 必要
なメールを失っている可能性はあるのだ。
1.1.2
原因
スパムは、貪欲2 の罪業が生み出してきたさまざ まな人造物と同じく、 社会の病理である。蕩尽熱3とで
も呼ぶがよかろう — インターネットという生態系は愚かな人間どもの活動によって危機に瀕しており、 ひ
いてはこのことがインターネット上での人類の生存をも脅かしかねないのである。
社会の大問題やよりよい人生の在り方についてはひとまず置いておくが 、 あなた — メールシステム管
理者 — 自身も、このゴ ミを始末するための方法について、 極めて具体的な実生活上のジレンマに直面す
1 [訳注] malware — ラテン語 mal- (悪い) と software による造語。 コンピュータウィルス、ワーム、トロイの木馬などの、「悪
意のこもった」 ソフトウェアの総称。
2 [訳注] greed 。 中世ヨーロッパキリスト教での 「七つの大罪」 の一つ。
3 [訳注] affluenza — affluence と influenza による造語。 大量生産、大量消費の現代社会では、 物質的な欲望が肥大して、いく
ら消費しても精神的に満たされることがなく、 借金や長時間労働のためにストレスはますます増大する。 いっぽうで、貧富の格差は
ますます広がり、 一部の人々、企業、国だけに富が偏在している。 このような社会状況を伝染性疾患に見立てた語。
1
ることになる。
メールの処理を メール転送やメール配送のためのさまざ まなコンポーネントに丸投げするという従来の
方法では、 いくつかの制限があることが判明している。伝統的な設定では、 一つまたはそれ以上のメール
交換機 [79] で、 ド メインのアドレス宛てに外部から来るメールの配送の ほとんど (ないしはすべて) を受
け付ける。 それから、よくあることだが、 メールを一つまたはそれ以上の計算機に転送してさらに処理し
たり、 ユーザのメールボックスへ配送したりする。 これらのサーバのいずれかで要求された配送や機能を
実行できないときは、 DSN を生成して、元のメールの送信者アドレスへ送り返す。
多くの組織では、スパムやウィルスの検出ソフトウェアを使い始めたとき、 こういうソフトウェアはメッ
セージの配送経路上で動かすのが最善だと考えた。 こういうソフトウェアを、メールが受入用メール交換
機 [79] から内部の配送先ホストや配送用ソフトウェアに転送されるメッセージ配送の途上で働かせる、と
いうことである。 例えば 、スパム排除をするには、 まずメールが SpamAssassin などのソフトウェアを通
るようにルーティングし 、 その後にメールをユーザのメールボックスに配送したり ユーザのメール利用者
エージェント [79] でのスパム排除機能に委ねたりする、 という方法をとるのが一般的になっている。
その際にスパムやウィルスに選別されたメールをど う始末するかについては、 選択肢が限られる:
• 送信者に配送状況通知 [78] を送り返す。 問題は、スパムやウィルスが生み出す電子メールのほとん
ど すべてが 偽の送信者アドレスをつかって配送されているという点だ。 こういうメールに返送する
と、必ずと言っていいくらい、 無辜の第三者 — きっと、韓国のおばあちゃんだね。 Mac OS X を
使っていて、コンピュータのことはよく分からない — に、あなたは Blaster ワームに感染していま
すなどというメールが 行ってしまうことになる。 換言すれば 、巻き添えスパム [78] を発生させるこ
とになる。
• 送信者になにも通知を送り返さず、 メッセージをビットバケツに放り込んでしまう、というのはど う
だろうか。 これは、メッセージが偽陽性 [76] であった場合に より大きな問題を引き起こしてしまう。
なぜなら、送り手も受け手もメッセージがど うなったか分からない (受け手にとっては、それが存在
したことすら分からない) からだ。
• ユーザが メールにアクセスする方法によっては (例えば 、IMAP プロトコルや Web に基づくメール
リーダでアクセスしていて、 POP-3 でメールを取り込んでいないとしたら ) 、 — たぶんユーザのアカ
ウント設定のオプションに応じて — 別のゴ ミ箱フォルダに移してしまうこともできるかもしれない。
これは、3 つの選択肢のうちでは最善のものだ。 しかし 、メッセージを見ないでほおっておくユーザ
もいるだろう。 自分の 「ゴ ミ箱」 フォルダに入ったメールをちゃんと調べて 不要なものだけ削除し
てくれる受け手もいるだろうが 、 見落としはあるだろう。
1.1.3
解決策
この問題の唯一の正しい解決策は、 ド メインの内部行きメール交換機でメールを受け取る際に、 リモー
トホストとの SMTP 通信の間にスパムやウィルスの排除を行なってしまうことだ、 ということを、分かっ
ていただけると思う。 この方法では、望ましくないメールだと判明したときでも 先に述べたようなジレン
マに直面することなく SMTP 拒否応答を発行できる。 その結果:
• SMTP トランザクション初期の 実際のメッセージデータを受け取る以前にほとんどの不要メールの
配送を 止めることができるから、 ネットワークの帯域と CPU の処理能力の両方を節約できる。
• [SMTP トランザクションの遅延] [7] や[グレーリスト法] [15] のような スパム排除テクニックを、か
なり早い段階で使うことができる。
• 配送が (例えば有効でない受信者アドレスのために ) 失敗した場合も、 直接的には巻き添えスパム [78]
を発生させることなく、 送信者に知らせることができるようになる。
2
メーリングリストサーバや他のサイトのメールアカウントのような 信頼できる出所から転送されて
くるメールを拒否した結果、 間接的に巻き添えスパムを起こしてしまうことを防止する方法について
は、 後ほど 論じることにしよう4 。
• よそからの巻き添えスパム (ウィルス対策ソフトウェアからのいんちきな 「 You have a Virus 」 メッ
セージのような ) も、 防止できる。
よーし 、じゃあ、手をおろしていいよ。 地に足がつかなくなってた人も、立ち上がっていいよ。
1.2
善玉、悪玉、卑劣漢
排除テクニックの中には、 他の手法とくらべて SMTP トランザクションの間に使うのにより向いている
ものがある。 あるものはほかのものよりすぐれている。 ほとんどのやりかたには、それぞれ擁護派と反対
派がいる5 。
言うまでもなく、こういった論争はこの文書で論じる手法に対しても起きている。例えば :
• [DNS による検査] [8] は、 個々のメール送信者を利用するインターネットサービスプロヴァイダ (ISP)
だけに基づいて罰するもので、メッセージそのものの評価に基づいていない、 という主張もある。
• [SMTP トランザクションの遅延] [7] や[グレーリスト法] [15] といったラットウェア向けのトラップは
容易に乗り越えることができ、 時間がかかる割に効果が薄く、 そのいっぽ うで真っ当なメールに対
するサービスの品質を低下させていく、 という指摘もある。
• [Sender Policy Framework] [17] といった[送信者認証方式] [17] は、 ISP が顧客を囲い込む手段を与
え、 異なるネットワークの間を移動するユーザや 電子メールをあるホストから他のホストへ転送す
るユーザをうまく扱えない ことが分かってきている。
私は 、こうした論争には触れないことにする。 その代り、利用できるさまざ まなテクニックの機能面を、
ありうる副作用も含めて説明することにし 、 そのうちのいくつかを使ってみた私自身の経験を少々述べる
ことにする。
とはいうものの、今日利用されている排除手法のうちいくつかには、 この文書ではわざと触れていない:
• チャレンジ -レスポンス・システム (TMDA6 など )。 これは、SMTP の時点での排除には向かない。
最初にメールを受け付けることになっていて、 それから確認要求をエンヴェロープ送信者 [76] に送
り返すからだ。 このテクニックはそのため、この文書では扱わない7 。
• Bayes 式フィルタ [75]。 これは、特定のユーザ、そしてまた特定の言語ごとに特化した学習を必要と
する。 そのため、これも通常は SMTP トランザクションの間に使うのには向かない (が 、[ユーザご
との設定とデータ] [26] も見てほしい)。
• 小額課金方式 [77] は、 この世のあらゆる真っ当なメールに仮想的な切手が ついて送られるようにな
るまでは、実際には不要メールを取り除くのには向かない (だが 、当面はこれを逆の目的に使える。
つまり、他の方法では拒否されてしまうメールでも、 切手があれば受け付けることにするのだ )。
4 それでも、信頼できない第三者ホストのメールを拒否すると、 巻き添えスパムを発生させるかもしれない。 しかしながら、その
ホストが開放型プロキシ [76] や開放型リレー [76] でない限り、 そのホストは真っ当な送信者からのメールを配送していると考えられ
るので、 そのアドレスは有効であるはずだ。 そのホストが 開放型のプロキシや SMTP リレーであるのなら — そうだねえ、メール
は拒否して、そのホスト の 送出用メールキューに留めておくほうが 、 自分のところに留めるよりもいいだろう。 いつか、そのサー
バの持ち主の手がかりにならないとも限らないから。
5 [訳注] 本節の表題は 「 The Good, The Bad, The Ugly 」 (Il Buono, il brutto, il cattivo) (監督: Sergio Leone 。1966 年イ
タリア。 出演: Clint Eastwood, Lee Van Cleef 他。 邦題 「続・夕陽のガンマン 」) から採られているようだ。
6 http://tmda.net/
7 個人的には、チャレンジ -レスポンス・システムは どんな場合でもいい考えではない、 と思う。これは巻き添えスパム [78] を発
生させるし 、 毎月の銀行の明細のような自動化された出所からのメールに特別な配慮が必要になるし 、 人々が制約なく自由に触れ合
えるという電子メールの利便性を損なう。 よくあることだが、真っ当なメールの送信者は 確認要求を処理しなければならないのをい
やがるか、 またはそんなことをしなければならないことに気づかない。 そのため、メールを失う。
3
総じて、できるだけ精度が高いテクニックを採用するようにし 、 偽陽性 [76] を避けることに意を用いるよ
うにした。 だれにとっても、自分の電子メールは大切なものだ。だから、時間と労力を費やして書く。 私
見だが 、真っ当なメールを大量に拒否してしまうテクニックやツールをあえて使うことは、 それで直接影
響を被る人々にも、 またインターネット全体に対しても、礼を失した行ないだと思う8 。 これはとりわけ、
SMTP 時点でのシステム全体での排除について言えることだ。 なぜなら、最終受信者は普通、メールの排
除に使う基準をほとんど 、あるいはまったく、 制御できないのだから。
1.3
SMTPト ランザクション
SMTP は、インターネットでのメール配送に使うプロトコルである。 このプロトコルの詳細な記述は、
RFC 28219や、Dave Crocker の インターネット メールのアーキテクチャ1011 の紹介を参照してほしい。
メールの配送には 、 接続してきたホスト (クライアント ) と受信側のホスト (サーバ ) の間での SMTP
トランザクションが伴う。 ここでの議論では、接続してきたホストが相手側で、受信側のホストが自分の
サーバである。
典型的な SMTP トランザクションでは 、クライアントは EHLO 、MAIL FROM: 、 RCPT TO: 、
DATA のような SMTP コマンド を発行する。 サーバは 、ひとつひとつのコマンド に対して 3 桁の数値
コードで応答し 、 コマンドを受け付けた (2xx) か、 一時的な失敗や制約がある (4xx) か、 確定的、永続的
な失敗 (5xx) かを示す。 その後には、人間が読みやすい説明がつく。 コード の完全な説明は RFC 282112
の中にある。
最善の場合の筋書きによる SMTP トランザクションは、典型的には以下の一連の手順から成る:
8 私のこの見解は、 SPEWS http://www.spews.org/ ブラックリストのメンテナのような 世のおおぜいの 「スパム・ハクティ
ヴィスト 」 [訳注: hacktivist は hack (ハックする) と activist (活動家) を組み合わせた造語。 「技術的な手段を駆使してスパム撲
滅のために闘う人 (々) 」 の意] のそれとは、好対照をなしている。 これらのリストの狙いのひとつを正確に言うと、 「 ISP が苦情
に反応するよう圧力をかける手段として巻き添え被害 [78] の試練を与えること」である。 リストに載せられたことに異義を申し立て
ても、しばしば 「我々ではなく、あなたの ISP を責めなさい」 とか 「 ISP を替えなさい」 というような 木で鼻をくくったような
返事しか返ってこない。
これはまた、実現不能な選択肢であることも多い。 開発途上国のことを考えてみるとよい。 ついでに、ほぼすべての地域で広帯域
プロヴァイダは寡占状態にある、 という事実についても考えてみるとよい。 このような傾向が 、 こういったグループを信頼すべき
かど うかという問題の鍵を握ると、私は思う。
賭けてもよいが 、 不要メールを排除するには、より良く、より的確な方法がある。
9 http://www.ietf.org/rfc/rfc2821.txt
10 http://www.ietf.org/internet-drafts/draft-crocker-email-arch-04.txt
11 [訳注] 翻訳の時点では新版に更新されていたので、原文の URL を修正した。
12 http://www.ietf.org/rfc/rfc2821.txt
4
Table 1.1: 単純な SMTP 通信
クライアント
サーバ
サーバへの TCP 接続を開始する。
SMTP バナー — これは、コード 220 で始まる挨
拶で、 SMTP (か、普通は ESMTP — SMTP の
スーパーセット ) で話す用意ができたことを示す
— を表示する: 220 サーバの.f.q.d.n ESTMP...
ハローコマンド を使って、自己紹介をする。 こ
その挨拶を 250 応答で受け入れる。 クライアント
れは HELO (いまや旧式) か EHLO のいずれ
がハローコマンド の拡張版 (EHLO) を使ってい
かのコマンド で 、 後にクライアント自身の完全
れば 、サーバにはクライアントが複数行の応答を扱
修飾ド メイン名 [76] が付く: EHLO クライアント
えると分かるので、 通常は、このサーバで使える
の.f.q.d.n
機能を示す数行のテキストを送り返す: 250-サー
バの.f.q.d.n Hello ... 250-SIZE 52428800
250-8BITMIME 250-PIPELINING 250-STARTTLS
250-AUTH 250 HELP PIPELINING 機能が応答
に示されていれば 、 クライアントはその時点から、
ひとつひとつのコマンド への応答を待たずに、 い
くつかのコマンド を一度に先行して発行できる。
250 応答を発行して、 送信者を受け付けたことを
エンヴェロープ送信者 [76] を指定することにより、 示す。
新たに メールトランザクションを始める: MAIL
FROM:<送り手の@アドレス>
メッセージのエンヴェロープ受信者 [75] を一度に
それぞれのコマンド に応答 (その受信者への配送
一つずつ列挙する。 次のコマンド を使う: RCPT
が受け付けられたか、 一時的に失敗しているか、
TO:<受け手の@アドレス>
拒否されたかによって、 2xx 、 4xx 、 5xx) を発
行する。
DATA コマンド を発行して、 メッセージを送る
用意ができたことを示す。
354 で応えて、 コマンド をとりあえず受け付けた
ことを示す。
メッセージを伝達する。 メッセージは RFC 2822
250 で応じて、 メッセージを受け付けたことを示
準拠のヘッダ部 (From: 、To: 、 Subject: 、Date: 、 す。
Message-ID: のような) で始まる。 ヘッダと本体
は空行で区切る。クライアントは、 メッセージの
終りに単一のピリオド (”.”) から成る単独の行を
送る。
配送したいメッセージがまだあれば 、 次の MAIL
切断。
FROM: コマンド を発行する。 そうでなければ 、
QUIT と言うか、 (まれなケースだが ) 単に接続
を切る。
5
第 2 章 テクニック
概要
本章では、 リモートホストからの SMTP トランザクションの間に不要メールを取り除く さまざまな
方法を見る。 また、これらのテクニックを用いることによる副作用についても検討してみる。
2.1
SMTPト ランザクションの遅延
内部行きの SMTP 通信にトランザクションの遅延をはさむことが 、 スパムを止めるのにかなり効果的
だということが判明している。 これは タール坑法1 (http://www.iks-jena.de/mitarb/lutz/usenet/
teergrube.en.html を見てほしい) の素朴な形態である。
多くのスパムと、ウィルスが生み出す電子メールのほぼすべてが 、 大量のメールを極めて短時間で送信
できるように最適化された特殊な SMTP クライアントソフトウェアを使って サーバに直接配送される。 こ
のようなクライアントは一般にラットウェア [79] として知られる。
この仕事をやり遂げるために、ラットウェアの作者はたいがい近道、 というか、RFC 2821 仕様からの
若干の 「逸脱」 をしようとする。 ラットウェアならではの特徴として、それが名うての短気者であると
いうことがある。 特に、ゆっくり応答するメールサーバに対してそうだ。 サーバが最初の SMTP バナー
を示す前に HELO コマンド や EHLO コマンド を発行したり、 サーバが PIPELINING 機能をまだ広
告していないのに SMTP コマンド をパイプラインしようとしたりする。
ある種のメール転送エージェント [79] (Exim のような) は、 このような SMTP プロトコル違反を自動
的に同期エラーとして扱い、 即座に外部からの接続を切る。このような MTA を使っていれば 、 ログファ
イルにはこの効果によるエントリが多数現れていることだろう。 事実、 最初の SMTP バナーを表示する
のに先立って時間のかかる検査 ([DNS による検査] [8] のような ) を実施しているときは、 ラットウェアク
ライアントであればサーバが活動を始めるのを待たないから、 このようなエラーが頻繁に起きる (こうい
うことをするのは、スパムを送信しようとする者だ )。
さらに遅延をはさむことも役立つ。例えば 、 次のようなときに待つようにすることもできる:
• 最初の SMTP バナーを表示する前に、20 秒、
• ハロー (EHLO か HELO) の挨拶の後で、20 秒、
• MAIL FROM: コマンド の後で、20 秒、
• RCPT TO: コマンド の後ごとに、20 秒。
20 秒という数字はどこから来たのだろうか。なぜ 1 分とか数分ではいけないのか。 RFC 2821 は、送信側
のホスト (クライアント ) が SMTP 応答ごとに数分は待たなければならないと定めているというのに。 問
題は、受信側のホストによっては (特に Exim を使っているものでは ) 、 外部から来るメールの配送の試み
への応答の際に [送信者呼出し確認法] [12] を実行するものがあるという点だ。 ユーザがこのようなホスト
にメールを送ると、ド メインのメール交換機 [79] (MX ホスト ) に接続して、 送信者アドレスを確認するた
めの SMTP 通信を始める。 このような [送信者呼出し確認法] [12] の既定のタイムアウトは、30 秒である
— この長さまで遅延をはさむと、相手の送信者呼出し確認法が失敗してしまい、 次に、ユーザからの元々
1 [訳注] teergrubing — ド イツ語 Teergrube (タール坑) より。 tarpitting — 英語 tarpit (同意) より — と表記している文献も
ある。
7
のメール配送が拒否されるおそれがある (普通は一時的な失敗なので、メッセージの配送を 5 日くらい再試
行することになり、 メールは最後には送信者に返送される)。
言い替えると、20 秒というのは、 真っ当なメールの配送を妨げることなく足留めしておけるほぼぎりぎ
りの長さなのだ。
このような遅延をすべての SMTP トランザクションにはさみたくないときは (サイトが非常に多忙で計
算機の資源が少ない、といったときだね ) 、「選択的な」トランザクションの遅延にすることもできる。 こ
の場合は、次のようなときに遅延をはさむ:
• 相手の DNS 情報に問題があるとき ([DNS による検査] [8] を見てほしい)。
• SMTP トランザクションの間に何か問題の徴候が見つかったら、その後に ([SMTP での検査] [10] を
見てほしい)。
• DNS ゾーン中の MX ホストのうち、番号の一番大きいもの、 つまり、最も優先度の低いメール交換
機だけで。よくあることだが 、 ラットウェア [79] はこういうホストを特に狙う。 真っ当な MTA で
あればまず、より番号の小さい MX ホストを使おうとする。
実際は、選択的なトランザクションの遅延は、 以下の節で議論するあまり決定的でないいくつかの検査と
併用するのに いい方法かもしれない。 例えば 、SPEWS ブラックリストの結果を見て即座にメールを 拒
否したくはないだろうが 、その結果がやっかいごとの徴候をはっきり示していれば 、 トランザクションの
遅延をはさんでみてもよいだろう。 そうしたとしても、 真っ当なメール配送であれば 、わずかに遅延を余
儀なくされるほかは影響を受けない。
逆に、スパム送信の決定的な証拠 (例えば [SMTP での検査] [10] での方法によるもの) が見つかり、サー
バに余裕があれば 、 最終的に配送を拒否する前に、より長い遅延 (例えば 15 分くらい) をはさむこともで
きる 2 。 スパム送信者は、DNS ブラックリストや他の協調型ネットワーク検査に追いつかれるまでに でき
るだけ多くの人々を探索しようとする。 SMTP トランザクションの遅延はその歩みをほんのわずか遅める
が 、 それ以外にはたいして得になることはない。 いわば 、純粋な利他の行ないだね。:-)
私自身の場合、選択的なトランザクションの遅延と SMTP 同期エラーとで、 外部からの配送の試みの
50% 近くを拒否できている。 これは大雑把に言い替えると、外部から来る不要メールの 50% 近くは SMTP
トランザクションの遅延だけで止められる、ということだ。
スパム送信者が適応してきたら ...も見てほしい。
2.2
DNS による検査
SMTP コマンドがまだ発行されていないうちでも、 特定の相手の整合性の指標をいくつか ド メインネー
ムシステム [77] (DNS) から拾いあげることができる。 特に、さまざまな DNS によるブラックリストを使
えば 、 特定の IP アドレスがある基準を満足したり基準からはずれていたりするかど うかが分かる。 簡単
な正引き/逆引き (DNS/rDNS) の検索結果を比べるだけでも、 ホストの一般的な整合性のおおまかな指標
になる。
さらに、SMTP 通信の間に示されるさまざまなデータ (ハロー挨拶で表示する名前のような) も、利用でき
るようになればすぐ DNS での検証にかけることができる。こういったデータについての議論は 下の[SMTP
での検査] [10] についての節を見てほしい。
しかし 、気をつけなければならないことがある。 DNS による検査はいつも決定的なものではない (例え
ば 、必要な DNS サーバが応答しないこともある) し 、 いつもスパムかど うかを言明するものでもない。さ
らに、非常に多忙なサイトでは これはメッセージの処理時間の面で高くつくかもしれない。 とはいえこの
検査では、ログに記録するのが目的のときやより全般的な整合性検査の一部にするようなときには、 有用
な情報を得ることができる。
2 外部から来る SMTP 配送を保持している間は、 サーバの TCP ソケットやメモリなどのサーバ資源も保持しているのだという
ことに気をつけよう。 一般に多忙なサーバで SMTP トランザクションの遅延をはさむと、 サービス不能攻撃に対する脆弱さを増す
ことになる。 より 「スケーラブル」 な選択肢も考えられる。 送信者がラットウェアクライアントであるという決定的な証拠をつか
んだら すぐに接続を切る、というものだ。
8
2.2.1
DNS によるブラックリスト
DNS によるブラックリスト (DNSbl 、かつては元々のブラックリスト ”mail-abuse.org” にちなんで ”Realtime Black-hole Lists” と言った) は、トランザクションの時点でのスパムの阻止を実施するための、 おそ
らくもっとも一般的な方法になった。 受信側のサーバは、相手の IP アドレスに対してさまざ まな DNSbl
ゾーン (”dnsbl.sorbs.net” 、”opm.blitzed.org” 、 ”lists.dsbl.org” 、等のような ) の中での DNS 逆引きを実
施する。 一致する DNS レコードが見つかったときの典型的な動作は、 メール配送を拒否するというもの
だ3 。
DNS アドレス (”A” レコード ) に加えて、エントリの ”TXT” レコード も検索すれば 、 典型的にはリス
ト登録についての 1 行の説明を受け取ることができ、 SMTP の拒否応答に含めるのに役立つ。 試してみ
るには、ほとんどの Linux システムや UNIX システムで提供される ”host” コマンドが使える:
host -t txt 2.0.0.127.dnsbl.sorbs.net
現在、こういうリストが何百もあり、それぞれのリストに入れる基準は異なっていて、 リスト登録/削
除の方針も異なっている。 一部のリストでは、ひとつの DNSbl で複数のリスト登録基準を併用していて、
与えられたアドレスがどの基準に触れるかによって DNS 逆引き応答で異なるデータを発行する。 例えば 、
sbl-xbl.spamhaus.org に対する DNS 逆引きでは SpamHaus のスタッフがスパム送信者とそのプロヴァ
イダに直接属していると考える IP アドレスには 127.0.0.2 を返し 、 ゾンビホスト [77] には 127.0.0.4 を、
開放型プロキシ [76] サーバには 127.0.0.6 を返す。
残念なことに、こういうリストの多くが、 申し立てられた違反に直接責任のないより広範囲の IP アドレ
スブロックを登録したり、 リスト登録/削除の方針を明確にしていなかったり、 アドレスの登録について
誤った情報を公告していたりする4 。 このようなリストを鵜呑みにすると、 巻き添え被害 [78] (巻き添えス
パム [78] と混同しないように ) と呼ばれるものを大量に生み出すことがしばしばある。
このため、多くの管理者が、 DNS によるブラックリストから肯定的な応答を一つだけ受け取ったことに
基づいて 即座に拒否応答をするより、こういうリストをより微妙なやりかたで使うことを好む。 複数のリ
ストを参考にして、肯定的な応答ごとに ”得点” をつける。 与えられた IP アドレスの得点の合計が決まっ
た閾値に達すると、 そのアドレスからの配送を拒否する。 これが、SpamAssassin ([スパム検出ソフトウェ
ア] [21]) のような排除ソフトウェアで DNS ブラックリストを使うときのやりかたである。
また、このようなリストを外部からの接続での SMTP トランザクションの遅延 (別名 ”タール坑法”) を
使うきっかけにすることもできよう。 あるホストがある DNSbl に登録されていたら、 自分のサーバでは
相手が発行する SMTP コマンドごとに応答に遅延を、 そう、たとえば 、20 秒入れる。他のいくつかの基準
もこのような遅延のきっかけに使える — [SMTP トランザクションの遅延] [7] についての節を見てほしい。
2.2.2
DNS による整合性検査
DNS の別の使いかたとして、 相手の IP アドレスの逆引きを実施してから結果の名前を正引きする、と
いうものがある。 結果が元の IP アドレスを含んでいれば 、 そのホストの DNS 整合性が検証できたこと
になる。 そうでなければ 、接続してきているホストの DNS 情報は有効なものではない。
この基準に基づいてメールを拒否してもかまわない場合があるとすれば 、 自分が DNS 治安部隊の戦闘
的な隊員であり、 受入用 MX を自分の個人的なド メイン用にだけ設置していて、 たとえ真っ当なメールで
3 目的の異なる類似のリストが存在する。例えば 、 「 bondedsender.org 」 は DNS によるホワイト リスト (DNSwl) で、 「信頼
できる」 IP アドレスを含んでいる。 このアドレスの持ち主は保証金を積んでおり、 そのアドレスからスパムが発生することがあれ
ば 、保証金は没収される。 他にも、特定の国や ISP などが使う IP アドレスを含むリストがある。
4 例えば 、いまこれを書いているときにも、 世界最大のインターネットサービスプロヴァイダ (ISP) である comcast.net の送出
用メール交換機 (「スマートホスト 」) が、 SPEWS の Level 1 リストに登録されている。これは、Comcast が自身の定めた AUP
[訳注: Acceptable Use Policy。 ユーザのネットワーク利用に対して、利用目的に制限を加える規則] をより厳格に適用すべきであ
るという観点からすれば 、 全面的に不当なものとは言えない。 が 、リストへの登録は、米国の全インターネット ユーザの 30% (ほ
とんどが私のような 「無辜の」 契約者) に影響を与えているのだ。
さらにひどいのは、SPEWS FAQ http://spews.org/faq.html で公表されている案内が、こう表明していることだ : Level 1 リ
スト の大多数は、スパム送信者か、 彼らのスパム行為を幇助する機関が有するネットブロックで、 他に真っ当な顧客がほとんど、ま
たはまったく見つからなかったものである。 形式的には、この案内は (a) Comcast を 「スパム幇助機関」 とみなし 、(b) 「他に」
という語に注意を払えば 、正確である。 だが語釈としてはそうでも、この案内は明らかに誤っている。
9
も拒否すれば送信者のほうがシステム管理者に DNS レコード の整頓を頼まなければならないと実感してく
れるからかまわない、 というときだけだろう。 そうでないのなら、DNS による整合性検査の結果はおそ
らく、 より大きなヒューリスティックの中のデータのひとつとしてだけ使うべきだろう。 その代わりに上
記のように、 設定がおかしいホストには SMTP トランザクションの遅延を使うというのは 悪くない考え
だろう。
SMTP での検査
2.3
SMTP 通信が始まってからも、 リモートホストが示すコマンド や引数についてのさまざまな検査を実施
できる。 例えば 、ハロー挨拶で示す名前が有効かど うかを確認するとよいかもしれない。
ただし 、SMTP トランザクションの初期のうちに配送の試みを拒否すると決まったときでも、 実際には
すぐに拒否を実施しないほうがよいかもしれない。 かわりに、RCPT TO: の後の SMTP トランザクショ
ンの遅延で 送信者を足留めし 、それからそのメールを拒否するほうがよい。
そのわけは、 ラットウェアのの中には SMTP トランザクションの初期に拒否されても気づかないものが
あるためだ — それでも送信を続けようとする。いっぼう RCPT TO: が失敗すると、たいていは諦める。
それはともかく、これは小規模なタール坑法を 実行するのにはよい機会だ。
2.3.1
ハロー (HELO/EHLO) の検査
RFC 2821 によれば 、クライアントが最初に発行する SMTP コマンドは EHLO (あるいは対応していな
ければ HELO) でなければならず、 これには そのクライアントのプライマリ完全修飾ド メイン名 [76] が続
かなければならない。 これをハロー挨拶と言う。意味のある FQDN が使えないときは、 クライアントは
自分の IP アドレスを角括弧で囲んだものを使える: ”[1.2.3.4]”。後のほうの形式を、IPv4 アドレス ”リテ
ラル ” 表記と言う。
至極当然なことだが 、 ラットウェア [79] がハロー挨拶で自分自身の FQDN を表示することはまずない。
むしろ、ラットウェアからの挨拶では普通、送信側のホストの素性を隠そうとしたり、 困惑させ誤解させ
るような ”Received:” 経路を メッセージヘッダに入れようとしたりする。このような挨拶の例をいくつか
挙げる:
• 非修飾名 (つまり、ピリオド のない名前)。 受信者アドレスの 「ローカル部」 (ユーザ名) など 。
• 裸の IP アドレス (つまり、IP リテラルではない) — 普通はサーバのアドレスだが 、でたらめなもの
もある。
• サーバのド メイン名、あるいはサーバの FQDN.
• 第三者のド メイン名。 yahoo.com や hotmail.com など 。
• 存在しないド メイン名、あるいは存在しないネームサーバのド メイン名。
• 挨拶をまったくしない。
2.3.1.1
HELO/EHLO の簡易な構文検査
これらの RFC 2821 違反のいくつかは、容易に検査でき、 送信側のホストがある種のラットウェア [79]
を 実行していることの明白なしるしにもなる。このような挨拶は拒否してよい — すぐにでもよいし 、例
えば RCPT TO: コマンド のあとでもよい。
10
まず、ハロー挨拶に裸の IP アドレスがあったら、遠慮なく拒否しよう。 たとえあなたが RFC 2821 で
定め、推奨し 、 示唆するようなものはなんでも気前よく受け付けたいのだとしても、 IP アドレスを名前
の代わりにするときは角括弧で囲まなければならないのだ 5 。
特に、 あなたの IP アドレスで — またはあなたのホスト名で — 自分を紹介するようなホストには、 強
い調子の拒否メッセージを発行してもいいだろう。 嘘をついていることは明らかだ。 この送信者の挨拶へ
の応答では、 桁外れに長い SMTP トランザクションの遅延で足どめしておくのもいいだろう — そう、数
時間くらい。
ちなみに私の経験では、 インターネット上の真っ当なサイトなら、他のインターネットサイトに自分を示
すときに IP アドレスリテラル ([x.y.z.w] 表記) を使うことはない。 そんなことをすべきでもない — イン
ターネット上で直接メールを送信しているホストはすべて、 自身の有効な完全修飾ド メイン名 [76] を使う
べきだ。 私が見かける IP リテラルは、私のローカルエリアネットワークで、 私のサーバを送出用 SMTP
サーバ (スマートホスト ) に使うように設定してある メール利用者エージェント (Ximian Evolution のよ
うな) が使っているものだけだ。 事実、私は自分の LAN から来るリテラルしか受け付けない。
非修飾ホスト名 (ピリオド のないホスト名) は、拒否したほうがいいかもしれないし 、 しないほうがいい
かもしれない。 これが真っ当なホストであることはまずない (が、まったくないのではない — 否定の否定
でわかりにくいな)6 。
同様に、無効な文字を含むホスト名も拒否できる。 インターネットのド メインには、英数字とハイフン
だけが有効な文字である — ハイフンは最初の文字にはできない (アンダースコアも有効な文字とすること
を検討したほういいかもしれない。 なぜなら、これは設定は間違っているが悪意の全然ない Windows ク
ライアントで、とてもよく見かけるからだ )。
最後に、始めにハロー挨拶を受け取っていないのに MAIL FROM: コマンドを受け取ったとき。 そう。
礼儀をわきまえている人なら、まず挨拶するものだ。
私のサーバでは、上のいずれかの構文検査で失敗した挨拶は拒否する。 しかし 、拒否は RCPT TO: コ
マンド の後まで行なわない。 この間、 それぞれの SMTP コマンド (HELO/EHLO, MAIL FROM:,
RCPT TO:) の後に 20 秒のトランザクションの遅延をはさむ。
2.3.1.2
ハロー挨拶を DNS で確認する
ホストは、少なくとも見た目にはもっともらしい挨拶を示してきた。 では今度は、与えられた名前を DNS
で確認しよう。 次のようにすればできる:
• 与えられた名前の正引きを実施し 、 結果を相手の IP アドレスと照合する。
• 相手の IP アドレスの逆引きを実施し 、 挨拶で与えられた名前と照合する。
この 2 つの検査のど ちらかが成功すれば 、その名前は確認できたことにする。
MTA に、この検査を実施する組み込みのオプションがあるかもしれない。 例えば 、Exim (付録 A [29] を
見てほしい) では、 ”helo try verify hosts = *” を設定し 、 ”verify = helo” 条件に基づいて動作する ACL
を作成するとよいかもしれない。
この検査は、処理時間とネットワーク資源の面で、 簡易な構文検査よりは少し高くつく。 それだけでな
く、構文検査とちがい、 照合ができなかったことがいつもラットウェアのしるしになるわけではない — い
くつかの大規模なインターネットサイト (hotmail.com, yahoo.com, amazon.com のような) は頻繁に、確
認できないハロー挨拶を示す。
5 この 検査は 通常は 、ゴ ミを 取り除くのにとても効果が あるのだが 、 L-Soft listserv http://www.lsoft.com/products/
default.asp?item=listserv のイン ストレ ーションにはバグがあるものがあって 、 リストサーバの裸の IP アド レ スで挨拶す
る、との報告がある。
6 [訳注] 同様のものとして、 インターネット上に存在しない最上位ド メインをもつ 「 FQDN 」 が 、たまに見受けられる。例えば
smtp.example.local のようなもの。
これは、非修飾ホスト名の場合と同様な原因で発生すると考えられる。 つまり、ラットウェアが身許を隠そうとしているか 真っ当
なメールを送ろうとしている送信側ホストだが MTA が適切に設定されていないか、のいずれかである。 後者はまずない (が 、まっ
たくないとは言い切れない)。 いずれにせよ、拒否したければしてよい。
2005 年 6 月現在、インターネット上で有効な最上位ド メイン名は、 2 文字の英字による国コード 最上位ド メイン名 (ccTLD) と、
その他の 14 種の最上位ド メイン名 (arpa はハロー挨拶には使わないので、 この数には含めていない) である。
11
私のサーバでは、 先立つ検査に基づいて送信者をトランザクションの遅延で足留めしていないときだけ、
ハロー挨拶の DNS 検証をする。そして、この検査が失敗したら 、 そこから後の SMTP コマンドごとに
20 秒の遅延をはさんでいる。 また、
「 X-HELO-Warning: 」 ヘッダを用意して 後でメッセージに付加し 、
SpamAssassin の得点を引き上げることで、 メッセージデータを受信した後の拒否が起こりやすくしている。
2.3.2
送信者アドレスの検査
クライアントが MAIL FROM: <アドレス> コマンド を示した後では、 与えられるエンヴェロープ送
信者 [76] アドレスを次のようにして検証できる7 :
2.3.2.1
送信者アドレスの構文検査
与えられたアドレスは <ローカル部@ド メイン > の形式になっているか。 ド メインの部分は、 構文的に
有効な完全修飾ド メイン名 [76] か。
この検査は、MTA の既定動作として実施されるようになっていることも多い。
2.3.2.2
詐称の検査
ユーザが外部へ行くメールすべてをごく限られたサーバからしか送信していない場合、 送信者アドレス
の 「ド メイン 」 が自分自身のものであるメッセージが 他のホストから来たら、拒否してよい。
この検査のより一般的な代替策が 、 [Sender Policy Framework] [17] である。
2.3.2.3
送信者アドレスの簡易な検証法
アドレスがローカルのものであるとき、
「ローカル部」 (@ 記号の前の部分) は、システムにある有効な
メールボックスか。
アドレスがリモートのものであるとき、
「ド メイン部」 (@ 記号の後の部分) は、存在するド メインか。
2.3.2.4
送信者呼出し 確認法
Exim や Postfix のようないくつかの MTA で提案されている。 リモートの送信者アドレスの 「ローカ
ル部」 を確認する機構である。 Postfix の用語では 「送信者アドレス検証」 と言う8 。
サーバは、 送信者アドレスから与えられるド メインの MX と接触し 、 このアドレスにメールを配送す
るかのような 第二の SMTP トランザクションを開始しようと試みる。 ここでは、実際にはメールはなに
も送信しない — 代わりに、 リモートホストが RCPT TO: コマンド を受け入れるか拒否するかすると、
サーバは QUIT を送信する。
Exim は、既定ではこの呼出し確認で空のエンヴェロープ送信者アドレスを使う。 そのため、この送信
者に配送状況通知 [78] を返信したときに 受け付けられるかど うかを確認できる。
いっぼ う Postfix では、アドレスの確認に使う送信者アドレスは既定では <postmaster@ド メイン > と
なる (ド メイン は $myorigin 変数からとる)。 このため、 この送信者アドレスを空のエンヴェロープ送信
者を扱うのと同じように扱うべきだろう (例えば 、[SMTP トランザクションの遅延] [7] や[グレーリスト法]
[15] を行なわないようにするが 、 受信者アドレスには [エンヴェロープ送信者のシグネチャ] [22] が必要な
ようにする)。 これについては、付録の実装でさらに触れる。
7 特別な場合として、空のエンヴェロープ送信者アドレス (つまり MAIL FROM: <>) がある。 これは、配送状況通知 [78] そ
の他の自動的に生成される応答に使う。 このアドレスは、いつも受け付けなければいけない。
8 [訳 注] Postfix 2.1 以 降 で 使 え る 。 Postfix で の こ の 機 構 に つ い て は Postfix アド レ ス 検 証 Howto http://
www.kobitosan.net/postfix/trans-2.1/jhtml/ADDRESS VERIFICATION README.html
(原 文
http://www.postfix.org/
ADDRESS VERIFICATION README.html) を参照。
12
この検査だけでは、 外部から来るメールの拒否のきっかけにならないこともあるだろう。 真っ当なメー
ル (定期的な支払明細のような) を自動化されたサービスで送信するときなどに 無効な返信アドレスを使っ
ていることがある9 。また、 スパムの残念な副作用であるが 、 外部へ行くメールの返信アドレスを隠そう
とするユーザもいる (しかし 、この影響はエンヴェロープ送信者 [76] よりもメッセージの 「 From: 」 ヘッ
ダに現れることのほうが多い)。
さらに、この検査ではアドレスが有効であることを確認できるだけで、 それが特定のメッセージの送り
手であることを請け合うものではない (が 、[エンヴェロープ送信者のシグネチャ] [22] も見てほしい)。
最後に、 「 aol.com 」 のようなサイトでは、 送信者呼出し要求をしているシステムはなんでも機械的に
ブラックリストに入れてしまう、との報告がある。 このようなサイトはたびたびなりすまし メール [78] の
犠牲者となっており、 その結果、土砂降りのような送信者呼出し 要求を浴びている。 このような DDoS
(分散型サービス不能) 攻撃に加わる者は、 実質的にスパム送信者の手先になってしまう10 。
2.3.3
受信者アドレスの検査
こんなことは単純なことだと思うだろう。 受信者アドレスが有効な場合は、メールを配送する。 無効な
場合は、既定では MTA で拒否するように気をつける。
でも、ちょっと考えてみよう。いいかな。
2.3.3.1
開放型リレーの防止
メールはリモート ホスト からリモート アド レスへリレーしてはいけない ! (送信者が認証されていない
限り)。
多くの人は分かりきったことだと思っているだろうが 、 実はこれはしょっちゅう見過ごされていること
なのだ。 それに、電子メールアドレスや配送経路に関わるインターネットのさまざまな標準を、 すべての
ひとが完全に理解しているわけではないようだ (「パーセント書き換えをするド メイン 」、 「バング (!) 経
路」、なども検討しよう)。
自分の MTA が開放型リレー [76] になっていないかど うかがはっきりしないときは、 「 relay-test.mail-
abuse.org 」でテストできる。 自分のサーバのシェルプロンプトで、次のようにタイプする:
telnet relay-test.mail-abuse.org
これは、リモートの電子メールアドレスや 上で述べたようなアドレスの 「ハック」 へ SMTP サーバが
メールを転送してしまわないかど うかを、 さまざ まなテストで調べてくれるサービスだ。
自分のサーバが開放型リレーになるのを防止することは、 極めて重要だ。開放型リレーのサーバがスパ
ム送信者に見つかってしまうと、 たちまち数多の DNS によるブラックリストに登録されてしまう。 他の
いくつかの DNS によるブラックリストのメンテナに見つかってしまうと ( メンテナが自分で調べることも
あるし 、苦情を聞いて見つけることもある) 、 相当長い期間登録されることになる。
2.3.3.2
受信者アドレスの確認
これも、自明なことのように思えるかもしれないが 、かならずしもそうではない。
ユーザのメールアカウントやメールボックスが受入用メール交換機に格納されるのなら、 単に受信者ア
ドレスの 「ローカル部」 が有効なメールボックスにあたるかど うかを検査すればよい。これは問題ない。
受信者アドレスの確認が面倒になるような筋書きは、2 つある:
• その計算機が 、受信者のド メインのバックアップ MX である。
9 [訳注] また、MTA によっては、 RCPT TO: コマンド の引数が自ド メインのアドレスであれば それが実在しようがしまいが
受け付けるものもある。 こういうサイトのアドレスを検査するのは、無駄なことである。 以上のような理由から、 検査をよく詐称
されるド メインのアドレスだけに限定するとよいかもしれない。
10 [訳注] 多くの送信者呼出し確認法の実装では、確認結果をキャッシュすることができるので 確認の頻度を減らせる。使っている
MTA の文書を参照してほしい。
13
• その計算機が 、自分のド メインへのメールを全て他の (たぶん内部の) サーバへ転送している。
このような場合は、受信者アドレスの確認をすることなく、 それぞれのド メインの受信者アドレスを全て
受け付けてしまう。 そうすると、その後目的地のサーバで受信者アドレスが無効と分かったときに、 その
アドレスについての配送状況通知 [78] を生成せざるをえない。 つまるところ、これは巻き添えスパムを発
生させてしまうことになる。
このことを念頭に置きながら、 上に挙げた筋書きでど うやって受信者を確認したらよいかを見ていこう。
受信者呼出し 確認法
Exim や Postfix のようないくつかの MTA で提案されている。 リモートの受信者アドレスの 「ローカ
ル部」 を確認する機構である (これがど うやって動くかの説明は [送信者呼出し確認法] [12] を見てほしい)。
Postfix の用語では 「受信者アドレス検証」 と言う11 。
この場合、 サーバは相手からの RCPT TO: を受け入れる前に、 最終宛先ホストに接触してそれぞれ
の受信者アドレスを検証する。 それから、相手からの RCPT TO: コマンド を受け入れる。
この解決策は、簡易でエレガントなものだ。 これは最終宛先ホストで動作している MTA がどんなもので
も動くだろうし 、 なにか特別なディレクトリサービスなどにアクセスする必要もない。 そのうえこの検査
は、その MTA が受信者アドレスを正確に照合できなくても (Lotus Domino サーバの場合がそうだ ) 、 受
信者アドレスがいつか受け入れられるものかそうでないかを正確に反映する — 後で述べるように、そうで
はない場合もあるにはあるが。
受信者呼出しでは、元のエンヴェロープ送信者 [76] を手付かずで渡すようにする。 そうしないと、宛先
ホストからの応答が正確でなくなるかもしれない。 例えば 、システムユーザやエイリアスへのバウンス (エ
ンヴェロープ送信者のないメール ) は、[実在するユーザへのバウンスだけを受け付ける] [24] で述べるとお
り、拒否されるかもしれない。
主要な MTA のうちでは、Exim と Postfix がこの機構に対応している。
ディレクト リサービス
別の良い解決策は、MTA がディレクトリサービス (例えば 1 つまたはそれ以上の LDAP サーバ ) に問い
合わせられるようにしておくことだろう。 多くの一般的な MTA はすべて LDAP 、NIS 、 その他さまざま
なバックエンドに対応していて、 これらは主にユーザアカウント情報を提供するのに使われている。
しかし 、難点がある。 電子メールの最終宛先ホストでユーザ名をメールボックスに対応づけるのに ディ
レクトリサービスを使っていないときは、 設定するのにかなりの作業が必要になるのだ。
メールボックス一覧を複製する
上の選択肢がいずれも実現不可能なら、 「貧者のデ ィレクトリサービ ス」 に頼ることもできる。 メー
ルボックスが置かれている計算機から MX ホストへ、 現在のメールボックスの一覧を定期的に複写する。
そして MTA では、このリストを見て外部から来るメールの RCPT TO: コマンド を検証する。
メールボックスを持つ計算機が UNIX や Linux の類で動いているのなら 、 まず、こういう一覧を (た
ぶん 、 ローカルの 「 /etc/passwd 」 ファイルから ) 生成してそれを OpenSSH12 スイートに 入っている
「 scp 」 コマンド で MX ホストに複写する スクリプトを書く。 つぎに、
「 cron 」 ジョブを設定 (詳しくは
man cron とタイプしよう) して、 このスクリプトを定期的に実行する。
2.3.3.3
辞書攻撃の防止
辞書攻撃とは、 送信側のホストが一般的な名前 (アルファベット順に 「 aaron 」 から始まることが多い
が 、 アルファベットのもっと後ろのほうから始まったり、 でたらめな順序だったりすることもある) に基
11 [訳 注] Postfix 2.1 以 降 で 使 え る 。 Postfix で の こ の 機 構 に つ い て は Postfix アド レ ス 検 証 Howto http://
www.kobitosan.net/postfix/trans-2.1/jhtml/ADDRESS VERIFICATION README.html
(原 文
http://www.postfix.org/
ADDRESS VERIFICATION README.html) を参照。
12 http://www.openssh.org/
14
づいて RCPT TO: コマンド を発行し続け、 ありそうな受信者アドレスを探る SMTP トランザクション
のことを指す用語だ。 サーバが特定のアドレスを受け付けると、 そのアドレスはスパム送信者の武器庫に
加えられる。
サイトによっては、特に大きいところほど 、 たびたびこのような攻撃の標的になっている。 スパム送信
者から見れば 、ごくわずかのユーザしかいないサイトより 大規模なサイトのほうがある名前が見つかる機
会が増えるからだ。
辞書攻撃と闘う効果的な方法のひとつに、 アドレスが失敗するにつれてトランザクションの遅延を増大
させていく、 というものがある。例えば 、最初の存在しない受信者アドレスを拒否したら 20 秒の遅延、 つ
ぎのアドレスでは 30 秒の遅延、といったふうにできる。
2.3.3.4
受信者が一つの DSN だけを受け付ける
真っ当な配送状況通知 [78] なら、 一つの受信者アドレス — 通知のきっかけとなった元のメッセージの
送信者 — だけに送られるはずだ。 エンヴェロープ送信者 [76] アドレスが空なのに複数の受信者があれば 、
接続を切ってよい。
2.4
グレーリスト 法
グレーリスト 法13 の概念は、 Evan Harris の白書で提示されている: http://projects.puremagic.com/
greylisting/。
2.4.1
どのように動作するか
[SMTP トランザクションの遅延] [7] に似て、グレーリスト法は単純だが 、 ラットウェア [79] を介して
配送されてくるメッセージを極めて効果的に取り除ける機構である。考え方は、 メッセージの送り手と受
け手の間に以前も結びつきが存在していたかど うかを確認する、 というものだ。多くの真っ当なメールは
そう確認でき、配送は正常に進む。
いっぼう、以前に結びつきが存在しなければ 、 配送を一時的に (451 SMTP 応答で ) 拒否する。 真っ当
な MTA であればこの応答を適切に扱い、 すこし後に配送を再試行する14 。いっぽ うラットウェアは、す
ぐに配送の試みを繰り返すか、 あるいは簡単に諦めてしまってアドレスリストのつぎのアドレスに照準を
移す。
配送の試みから 3 点の情報を取り出す。これを三つ組と呼び 、 送り手と受け手の間の関連を一意に識別
するのに使う:
• エンヴェロープ送信者 [76]。
• 送信側のホストの IP アドレス。
• エンヴェロープ受信者 [75]。
配送の試みを一時的に拒否したときに、この三つ組をキャッシュする。 これをまずグレーリストに入れる。
決められた時間 (1 時間としよう) が経った後に 新たに配送の試みがあれば受け付け、三つ組をホワイトリ
ストへ移す。 ただし 、決められた期限切れ (4 時間としよう) までに新たな配送の試みがなければ 、 三つ
組をキャッシュから消す。
ホワイトリストに入った三つ組がさらに長い期間 (月次の支払明細のようなものを考慮して、最低でも
1ヶ月) 現れなかったときは、消す。これで、リストが無制限に膨らむのを防げる。
13 [訳注]
greylisting。
14 まれなことだが 、
「真っ当な」
バルクメール送信者 (groups.yahoo.com のような ) の中には、 一時的に失敗した配送を再試行
しないものもある。 Evan Harris がこういう送信者の一覧をまとめているので、 この方式の適用外にする目的に使える: http://
cvs.puremagic.com/viewcvs/greylisting/schema/whitelist ip.txt?view=markup。
15
この 3 種の期限切れは Evan Harris の元々のグレーリスト法白書 (いや、
「灰書」 と言うべきかな) から
取った。 ある人によれば 、グレーリストに入れた三つ組を消すまでの期限切れを もっと長くする必要があ
り得る。なぜなら ISP によっては (たとえば earthlink.net) 、 配送の再試行を 6 時間くらいごとにしかしな
いからだ 1516 。
2.4.2
複数のメール交換機でのグレーリスト 法
複数の受入用メール交換機を運用していて、 それぞれの交換機が別々のグレーリスト法キャッシュを持っ
ているとする。すると :
• 理論上は、ある送信者からユーザへの初回の配送は 最初の 1 時間の遅延の N 倍だけ遅れることにな
る。 N はメール交換機の数である。 理由は、メッセージの再送は 始めの配送で 451 応答したサー
バとは 別のサーバに対して起こりやすいためだ。 最悪の場合、送信者ホストが最初の交換機へ配送
を再試行しに戻ってくるまでに 4 時間では間に合わなかったり、 グレーリストに入った三つ組が消
えてからになったりする。 このため、配送の試みは幾度も繰り返し拒否されることになり、 送信者
ホストが諦めるまで続く (普通は 4 日くらいかかる)。
実際問題、これは好ましくない。送信者ホストは通常、 配送の試みが一時的に失敗したら即座に別
の MX を使って配送を再試行する。 だから、1 時間後にはどの MX ホストでもメッセージを受け入
れるべきだ。
• 三つ組が MX のどれか一つでホワイトリストに入った後でも、 同じ三つ組の別のメッセージが別の
MX に配送されると、 そこではグレーリストに入ってしまう。
このような理由から、 受入用メール交換機同士で グレーリストに入る三つ組のデータベースを共有できる
ように実装すべきだろう。 しかし 、このデータベースを持っている計算機が唯一の弱点になってしまうの
で、 その計算機が落ちてもうまく動作する (例えば 、全ての配送を受け付けるようにする、など ) ようにし
ておくべきだろう。 あるいは、データベース複製のテクニックを使って、 SMTP サーバが検索のときに替
わりの複製サーバを見にいくようにもできるかもしれない。
2.4.3
結果
私自身の経験では、グレーリスト 法は 不要メール配送数のおよそ 90% を止めることができる。 もちろ
ん、すでに説明したさまざまな[SMTP での検査] [10] を 適用した上でのことだ。 グレーリスト法を最初の
防衛線にすれば 、 外部から来る不要メールをさらに高い率で捕らえてくれそうだ。
逆に、 このテクニックによる偽陽性 [76] は、実質的にゼロである。 主要なメール転送エージェント [79]
は全て、一時的な失敗の後に配送の再試行を実施する。 このため、いつかは配送に成功するのだ。
グレーリスト法の欠点は、 真っ当なメールであっても 特定の受信者に対して過去に電子メールを送った
ことのない人からのものなら 1 時間の遅延 (複数の MX ホストを運用していれば複数時間) を受ける、とい
う点だ。
スパム送信者が適応してきたら ... も見てほしい。
15 大規模なサイトによくあることだが、 外部へ行くメールを複数のサーバで扱っていることがある。 例えば 、一つあるいはいくつ
かのサーバだけを即時の配送につかっていることがある。 このようなサイトでは、最初の配送の試みが失敗すると メールを大きな待
ち行列を扱えるように調整された予備サーバに渡す。 このため、このようなサイトから来るメールでは、 最初の 2 回の配送の試みが
失敗することになろう。
16 [訳注] 実際のグレーリスト法の実装では、一時的に失敗させる期間をもっと短く (例えば 300 秒程度) とっているものが多い。多
くの MTA で、 一時的な失敗の後に再送を開始するまでの時間は 1 時間より短く (例えば qmail では 400 秒、Postfix では既定で
1000 秒) 、 その後は再送の間隔を延ばしていく。 いっぽ う、一時的に失敗させる期間をあまり長くすると、 送信者に再試行中であ
ることを知らせる配送状況通知を送る (だいたい数時間後) よう設定されている送信者サイトでは、真っ当な送信者を困惑させるかも
しれない。
現在存在するグレーリスト法の実装などの情報については、 http://www.greylisting.org/ を参照。
グレーリスト法に似ているがより簡易な方式として、 三つ組の代わりにクライアントの IP アドレスだけを用いるお馴染さん方式
http://moin.qmail.jp/ a4 aa c6 eb c0 f7 a4 b5 a4 f3 ca fd bc b0 がある。
16
送信者認証方式
2.5
送信者の確認のために、さまざ まな方式が開発されている。 これらの方式では、送信者アドレスの有効
性だけでなく、信頼性も検査する。 インターネットド メインの持ち主がなんらかの基準を指定すると、 送
信者からド メイン内への配送はこの基準による信頼性を満たさなければならなくなる。
この種の方式で、初期に提案されていたものが 2 つある:
a vix.com> が発案した。
• MAIL-FROM MX レコード。Paul Vixie <paul°
• 逆メール交換機 (RMX) レコード。これは DNS そのものに追加するもので 、 Hadmut Danisch
a danisch.de> が発案し公表した。
<hadmut°
ど ちらの方式でも、 <ユーザ@ド メイン .com> からのメールは <ド メイン .com> の DNS ゾーンに指定し
てあるホストから来なければいけないことになっていた。
この 2 つの方式が発展してきた。 だが悲しいかな、またもや分裂してしまうのであった。
2.5.1
Sender Policy Framework (SPF)
「 Sender Policy Framework 」 (以前は 「 Sender Permitted From 」 と言った) は、 たぶん最もよく知ら
れた送信者認証の方式だ。 これは上で述べた元の方式にいくらか基づいているが、 ド メインの持ち主がも
う少し柔軟な基準を公告できるようになっている。
SPF 情報は、ド メインの最上位の DNS ゾーンで TXT レコード として公開する。 このレコード で次のも
のを指定できる:
• そのド メインからのメールを送ることを認めるホストはどれか。
• そのド メインから外部へ行くメールが GPG (GNU Privacy Guard) 署名を持たねばならないか。
• その他の基準 — 詳しくは : http://spf.pobox.com/ を見てほしい。
TXT レコード の構造はいまでも開発中だが 、 上記のことを実現するだけの基本的な仕様はもう固まって
いる。 v=spf1 で始まり、次のような修飾子がその後に続く:
• a — ド メイン自身の IP アドレスが 有効な送信者ホストである。
• mx — そのド メインの受入用メール交換機も 有効な送信者ホストである。
• ptr — 送信側のホストの IP アドレスの DNS 逆引きが送信者アドレスのド メイン部分の名前を含め
ば 、有効な送信者ホストである。
それぞれの修飾子の前に、プラス記号 (+) 、 マイナス記号 (-) 、疑問符 (?) 、or チルダ (˜) をつけることが
できる。 これはそれぞれ、信頼できる出所、信頼できない出所、 中立、信頼できそうにない出所、を示す。
修飾子の後には、コロンとそれに続く代替のド メイン名をつけられる。 例えば 、Comcast の契約者であ
れば 、自分の DNS ゾーンに 「 -ptr:クライアント .comcast.net ptr:comcast.net 」 を入れて、 外部へ
行くそのド メインの電子メールは なにか . クライアント .comcast.net に解決されるホストから来ることは
絶対になく、 なにか .comcast.net に解決される別のホストからは来る、ということを示せる。
現在、いくつかの大規模なインターネットド メイン (aol.com 、altavista.com 、dyndns.org 、earthlink.net 、
google.com のような) が 、SPF 情報を公開している。
送信者認証方式は、一般的にそうだが SPF に限ったとしても、 普遍的に受け入れられているわけではな
い。特に、ド メインの持ち主がユーザ/顧客から外部へ行くメールのリレーを容易に独占できてしまう、 と
いう批判がある。
別の批判としては、SPF が伝統的な電子メール転送をぶちこわす、というものがある — 転送元ホスト
が、エンヴェロープ送信者のド メインにある SPF 情報では 転送できるだけの信頼度を得られないことがあ
17
る。 こういったものの一部は、SRS17 や 送信者書き換え方式で扱える。 これらの方法では、メールの転
送元がエンヴェロープ送信者 [76] アドレスを次の形式に改変する:
ユーザ=出所の. ド メイン @転送元の. ド メイン
2.5.2
Microsoft Caller-ID for E-Mail
SPF と同様、受け入れの基準は送り手のド メインの DNS で TXT レコード によって公告する。 しかし
MS CIDE の情報は、簡易なキーワードによってではなく、 XML にエンコード されたまことに巨大な構造
体でできている。 その XML のスキーマは Microsoft の許諾の下に発行されている。
SPF は名前のとおり電子メールのエンヴェロープ送信者 [76] アドレスを検査するのに使うが 、いっぼう
MS CIDE は主にメッセージ自身の RFC 2822 ヘッダを検証するツールである。 そのため、そのような検
査ができる最初の時点は、 メッセージデータが配送された後で、 最後の 250 応答を発行する前となる。
率直に言って、
「仏造って魂入れず」 だ。 特許の問題と送信者側での繁雑さがあだになっている。
とはいえ、最近 http://spf.pobox.com/ に投稿されている SPF ツールは、 SPF に加えて MS Caller-ID
情報も検査する能力がある。
2.5.3
RMX++
(Simple Caller Authorization Framework — SCAF の一部) この方式は Hadmut Danisch が開発した。
彼は、元の RMX の発案者でもある。
RMX++ では、HTTP サーバを通じての動的認証もできる。 ド メインの持ち主は DNS によってサーバ
の場所を公表し 、 受信側のホストはこのサーバに接触することで 認証レコード を獲得する。 これで発信
者の信頼性を確認する。
この方式では、 ド メインの持ち主は (固定的な TXT レコード による SPF 情報のように ) ネットワーク
の構成を一般に知らせることなく、 送信者アドレスの認証に使う基準をよりきめ細かく制御できる。 例え
ば Hadmut による例では、あるアドレスからのメッセージを ビジネスアワーの後は 1 日 5 件以内しか受け
付けず、 上限に達したら警報を発するような認証サーバがある。
しかも、SCAF の用途は電子メールに限られない。他の Voice over IP (VoIP) のようなサービスに呼出
し認証機能を与えることもできる。
a theinternetco.net> が注意しているよ
RMX++ の難点はおそらく、 Rick Stewart <rick.stewart°
うに、 計算機資源やネットワーク資源に悪影響を与えることだろう: HTTP サーバからの応答は DNS で
情報を直接扱うときほど 広範にはキャッシュされないし 、 HTTP 要求の発行は DNS 要求とくらべて著し
く高くつく。
Rick はさらに、RMX++ の動的な性格が誤りの発見を困難にすることも指摘している。 上の例のよう
に 1 日 5 件の上限があるとして、1 つのメッセージが 5 回検査されてしまうと、 単一のメッセージで上限
に達してしまう。 このため、メッセージの再検査が不可能になる。
RMX 、RMX++ 、SCAF についてのさらなる情報は、次を参照: http://www.danisch.de/work/security/
antispam.html。
2.6
メッセージデータの検査
ようやく、メッセージの内容そのものに目を向けるときがきた。 これは従来はスパムやウィルスの検出
ソフトウェアがやっていたことで、 通常はメッセージが受け付けられてからの処理だった。 しかし我々の
場合は、この検査を最後の 250 応答を発行する 前に実施する。 そのため、巻き添えスパム [78] を生成せ
ずにその場でメールを拒否する機会ができる。
17 http://spf.pobox.com/srs.html
18
受入用メール交換機が非常に多忙 (つまりサイトは大規模で計算機は少ない) だと、 メール交換機でこ
こに述べる検査の一部または全部を実施することが あまりに高くつくこともあるかもしれない。 とりわ
け [ウィルス検出ソフトウェア] [21] や[スパム検出ソフトウェア] [21] の実行は、CPU 帯域と時間を相当食う。
もしそうなら、こういう検出作業のために専用の計算機を立ち上げるべきかもしれない。 多くのサーバ
側でのスパム対策やウィルス対策のソフトウェアは、 ネットワークごしに (つまりメール交換機から ) 実行
できる。 以下の章では、この点についてのさまざ まな MTA での実装についても議論する。
2.6.1
2.6.1.1
ヘッダの検査
ヘッダがない
RFC 282218では、メッセージは少なくとも 次のヘッダを含まなければならないと定めている:
From: ...
To: ...
Subject: ...
Message-ID: ...
Date: ...
これらのヘッダのいずれかがなければ 、 メッセージは主流のメール利用者エージェント [79] が生成した
ものではなく、 ゴ ミかもしれないということだ 19 。
2.6.1.2
ヘッダアドレスの構文検査
メッセージヘッダに現れるアドレス (つまり To: 、Cc: 、 From: ... といった項目) は、 構文的に有効な
ものでなければならない。 これはもう説明しなくてもわかるだろうが。
2.6.1.3
ヘッダアドレスの簡易な検証法
メッセージヘッダにあるアドレスそれぞれについて :
• アドレスがローカルのものであるとき、
「ローカル部」 (@ 記号の前の部分) は有効なメールボック
スか。
• アドレスがリモートのものであるとき、
「ド メイン部」 (@ 記号の後の部分) は存在するド メインか。
2.6.1.4
ヘッダアドレス呼出し 確認法
これは [送信者呼出し確認法] [12] や[受信者呼出し確認法] [14] と似た働きをする。 ヘッダのアドレスのう
ちリモートのものについては、 そのド メインのプライマリ MX を呼び出して 配送状況通知 [78] を受け付
けられるかど うか確認する。
2.6.2
不要メールシグネチャ集積システム
18 http://www.ietf.org/rfc/rfc2822.txt
19 一部の特殊化した MTA (ある種のメーリングリストサーバのような ) は、 「バウンスした」 メッセージ (配送状況通知 [78]) の
Message-ID: ヘッダを自動的には生成しない。 このようなメッセージは、空のエンヴェロープ送信者 [76] で区別がつく。
19
不要メールの特性のひとつに、多数のアドレスに送られるということがある。 すでに 50 人の受信者があ
るメッセージをスパムと判定しているときには、 その事実を使って、 自分にそのメッセージが配送されて
きたときに受け取るかど うかを決めてはど うだろうか。 ど うせならスパムトラップ [77] を作って、 スパム
と分かっているものの貯蔵庫に集めてはど うだろうか。
よくぞ聞いてくれました。そういう貯蔵庫は存在することが判明している:
• Razor20
• Pyzor21
• Distributed Checksum Clearinghouse (DCC)22
単純なシグネチャ検査だと、 不要メールと分かっているものとまったく同一のメッセージを受け取ったと
きだけ動くが 、 ここで述べているツールはそれよりも進歩したものだ。 それどころか、メッセージのヘッ
ダや本体のわずかな変異があっても、 よくあるパターンを見抜く。
2.6.3
バイナリゴミデータの検査
メッセージが印字不可文字を含むことはまれだ。 そういうものが見つかったら、メッセージはほぼ確実
にウィルスである。 また、非西洋言語で書かれたスパムで 適切な MIME エンコードがされていないもの
の場合もある。
はっきりしている場合がひとつある。それは、メッセージが NUL 文字 (序数ゼロ) を含んでいる場合だ。
印字不可文字とはど ういう意味かをはっきりさせることは なかなかややこしく23 、さほど 益もないことで
はある。 が 、この文字についてだけは検査を検討したほうがよい。 なぜなら、一部のメール配送エージェ
ント [79] (Cyrus Mail Suite24 のような ) では、これを含むメールは拒否してしまうからだ 25 。 このような
ソフトウェアを使っているのなら、 NUL 文字をなくすことを必ず検討しなければならない。
いっぼう、(いまでは旧式の) RFC 822 仕様では メッセージの NUL 文字を明確には禁止していない。 こ
のため、この文字を含むメールを拒否するのではなく、 Cyrus にメッセージを配送する前にこの文字を取
り除くことも考えられる。
2.6.4
MIME の検査
同様に、外部から来るメッセージの MIME 構造を検証するのも有益だろう。 MIME のデコード でのエ
ラーや不一致は、それほどしょっちゅう起こるものではない — しかし起こるのなら、メッセージは疑いも
なくゴ ミである。 それだけではなく、このようなエラーは [添付ファイルの検査] [20] 、[ウィルス検出ソフ
トウェア] [21] 、 [スパム検出ソフトウェア] [21] のようなこの後に続く検査で 問題をひき起こしかねない。
言い替えると、MIME エンコードが不正なら、メッセージは拒否する。
2.6.5
添付ファイルの検査
Windows スクリーンセーバー (「 .scr 」 ファイル ) や Windows プログラム情報ファイル (「 .pif 」) がど
うしても欲しくて、だれかに送ってもらった、 などということが 、これまでにあっただろうか。
20 http://razor.sf.net/
21 http://pyzor.sf.net/
22 http://rhyolite.com/anti-spam/dcc/
23 [訳注] 非西洋言語地域 (日本を除いてほとんどが 、 近年になってインターネット利用が盛んになってきた地域でもある) の一部
から来るメールには、 本体のテキストに非 ASCII 文字を含んでいても base64 や quoted-printable によるエンコードをしないもの
がしばしば見受けられる。 そのため、非 ASCII 文字であればすなわち印字不可文字とは言えない。 ただし MIME によれば 、 ヘッ
ダは非 ASCII 文字を含む場合にはエンコードしなければならない。 したがって、ヘッダに非 ASCII 文字を含むものはスパムの可能
性が高い。
24 http://asg.web.cmu.edu/cyrus/
25 IMAP プロトコルでは、 NUL 文字をメール利用者エージェントに伝達することを認めていない。 そこで Cyrus の開発者たち
は、それを含むメールは拒否するという、 いちばん簡単な方法をとることにした。
20
「 Windows 実行ファイル」の添付ファイル — つまり、 ファイル名の最後が上に挙げたような ピリオド
とそれに続く 3 文字の組合せになっているファイル名 — をもつメッセージの拒否を検討しよう。 この検
査は、[ウィルス検出ソフトウェア] [21] と比べると サーバの資源はずっとわずかしか消費しないし ウィル
ス検出ソフトウェアにまだシグネチャが存在していないような 新しいウィルスも捕らえることができるか
もしれない。
このような「ファイル名拡張子」のより詳しい一覧は、次を見てほしい: http://support.microsoft.com/
?kbid=29049726 。
ウィルス検出ソフト ウェア
2.6.6
サーバ側でのウィルス検出のためのソフトウェアには、さまざまなものがある。 少しだけ名前を挙げる:
• Sophie27
• KAVDaemon28
• ClamAV29
• DrWeb30
ファイル名だけに基づいて危険そうなファイルを阻止しては困る場面 (「 .zip 」 ファイルをど うするか検討
しよう) では、 このような検出ソフトウェアは役に立つ。 それに、このようなソフトウェアは添付ファイ
ルで伝達されるのではないウィルス (2004 年 3 月に現れた 「 Bagle.R 」 ウィルスのような ) も捕らえるこ
とができる。
多くの場合、ウィルス検出を実行する計算機が メール交換機である必要はない。 こういうウィルス対策
ソフトウェアの多くは、 別のホストからネットワーク接続を介して実行できる。
ウィルス対策ソフトウェアは、 主に既知のウィルスのシグネチャ (ウィルス定義) に基づいてウィルスを
検出している。 新しいウィルスも開発されるため、このシグネチャは常に更新しつづけることが必要だ。
それに、ソフトウェアそのものの正確性を最大限にするためにも、 常に最新の状態にしておかなければい
けない。
2.6.7
スパム検出ソフト ウェア
同様に 、スパム対策ソフトウェアを使えば 、 ヒューリスティック ( メッセージの内容、標準への準拠、
[DNS によるブラックリスト ] [9] や[不要メールシグネチャ集積システム] [19] のようなさまざまなネットワー
ク検査など ) の巨大な集合に基づいてメッセージを選別できる。 このようなソフトウェアでは典型的には、
メッセージごとに総合的な 「得点」 を決定することになる。 これがメッセージのスパムらしさを示し 、 こ
の得点がある閾値を越えたらメッセージをスパムに選別する。
もっともよく普及しているサーバ側でのヒューリスティックスパム対策ソフトウェアを 2 つ挙げる:
• SpamAssassin31
• BrightMail32
このようなツールは、 スパム送信者がさまざまな検査を回避する方法を見つけていくにつれ、 進化し続
けている。 例えば 、 「 GR0W lO 1NCH35 」のような「独創的な」つづりなど 。 そのため、ウィルス対策
26 [訳注]
原文の URL は、翻訳の時点ではアクセスできなくなっていたので修正した。
27 http://www.vanja.com/tools/sophie/
28 http://www.kapersky.com/
29 http://clamav.elektrapro.com/
30 http://www.sald.com/
31 http://www.spamassassin.org/
32 http://www.brightmail.com/
21
ソフトウェアと同じことだが、 スパム対策ソフトウェアを使うのならば 高度な正確性を得るために頻繁に
アップデートしなければいけない。
私は SpamAssassin を使っているが 、計算機資源への影響を少なくするため、 これはもはや私の最初の
防衛線ではなくなっている。 私の個人アドレスには日に約 500 件の不要メール配送の試みが来るが、 その
うちおよそ 50 件が SpamAssassin による検査にかかる (これは主に、私のほかのアカウントから転送され
てくるもので、 上に述べたような検査が効果を挙げないためだ )。 この 50 件のメッセージのうち、私の受
信フォルダにまで届くメッセージは 2 、3 日ごとに 1 件程度だ。
2.7
巻き添えスパムの阻止
巻き添えスパム [78] は、これまでに述べたテクニックだけでは 阻止が難しい。なぜなら、これは真っ当
なサイトから 標準的なメール転送ソフトウェア (Sendmail 、Postfix 、Exim のような) を使って届くから
だ。 あるメッセージが自サイトのユーザ自身が送ったメールに応える有効な配送状況通知 [78] であるかど
うかを決定することは、取り組みがいのある課題だ。 これをする方法をいくつか挙げる:
2.7.1
いんちきウィルス警告を排除する
巻き添えスパムの多くは、 ウィルス対策ソフトウェアが生成するウィルス警告である33 。だから、 こう
いうウィルス警告の Subject: ヘッダの文面やその他の特徴は、 ウィルス対策ソフトウェア自身が与えて
いるものだ。そういうわけで、 よくある特徴の一覧を作成すれば このようないんちきウィルス警告を排除
できるかもしれない。
いやあ、あなたは運がいい — もうやってくれた人がいる。 :-)
a timj.co.uk> がいんちきウィルス警告の一覧をメンテナンスしていて、SpamAssassin
Tim Jackson <tim°
で使えるようにしている。ここで手に入る: http://www.timj.co.uk/linux/bogus-virus-warnings.cf。
2.7.2
自分のド メインの SPF 情報を公開する
[Sender Policy Framework] [17] の目的は、 なりすまし メール [78] — つまり、 有効な電子メールアドレ
スを騙られること — を厳密に防ぐことである。
自分のド メインの DNS ゾーンで SPF レコード を公開すると、 SPF 検査を組み込んでいる受信者ホスト
では そのド メインのアドレスを詐称したメッセージを受け取らなくなる。 そのため、公開したサイトに配
送状況通知 [78] を送ってこなくなる。
2.7.3
エンヴェロープ送信者のシグネチャ
私が現在実験している別のアプローチとして、 外部へ行くメールのエンヴェロープ送信者 [76] アドレス
のローカル部にシグネチャを追加し 、 外部からの配送状況通知 [78] を受け付ける前にエンヴェロープ受信
者 [75] アドレスにあるこのシグネチャを検査する、というものがある。 生成される送信者アドレスは、例
えば次のような形式になろう:
ローカル部=シグネチャ@ド メイン
通常のメッセージ返信に影響はない。返信は メッセージの From: や Reply-To: の項目にあるアドレス
へ行く。 これらの項目は手つかずのままである。
簡単そうに見えるね。だが残念ながら、 この目的に合うようなシグネチャを生成するのは、見た目ほど
簡単なことではない。 これを使えるようにする上で、互いに相反するような検討事項がある。
33 ウィルス対策ソフトウェアの作者はなにを血迷って、 ウィルスを含む電子メールの送信者アドレスを信頼してしまうようなまね
をするのか、 の解明は、むしろ精神分析学の課題だろう。
22
• この手法が効果をあげるためには、 生成したサインつきエンヴェロープ送信者アドレスをスパム送信
者が手に入れても、 役にたたないようにしなければならない。典型的には、 シグネチャに有効期限
をつけられるように タイムスタンプを入れておくことになろう:
送信者=タイムスタンプ =ハッシュ@ド メイン
• [グレーリスト法] [15] を組み込んでいるサイトにメールを送るときは、 エンヴェロープ送信者アドレ
スは特定の受信者に対して一定でなければならない。 そうでないと、メールはいつまでもグレーリス
トに入り続ける。
このことを念頭に置くと、エンヴェロープ送信者 [76] をエンヴェロープ受信者 [75] に基づいて生成
することも 考えられる:
送信者=受信者=受信者の. ド メイン =ハッシュ@ド メイン
このアドレスには有効期限がないものの、 このアドレスに不要メールが送られ始めたら すくなくと
もどこから漏れたのかはわかる — 受信者アドレスに組み込んであるアドレスだ。 さらに、同じ受信
者への通常のメール配送に影響を与えることなく、 特定の受信者アドレスシグネチャを容易に阻止で
きる。
• メーリングリストサーバでは、さらに 2 つの問題が起こる。普通、 リクエストメール (「 subscribe 」/
「 unsubscribe 」 のような ) への返信はエンヴェロープ送信者なしで送られる。
– 一つめの問題は 、 リクエスト メールのエンヴェロープ 送信者 [76] アドレ ス に返信するサー
バ ( <[email protected]> のような ) についてだ。 メーリングリストサーバへのコマンド
(subscribe や unsubscribe のような) は、典型的には、リストへのメールに使うアドレスとは別
の 一つかそれ以上の異なるアドレス (例えば 、 それぞれ <[email protected]>
と <[email protected]>) に送られる、 という問題がある。 このため、購
読者のアドレスは リストそのものに送られたメッセージの送信者アドレスとは — そしてこの
例では、購読停止要求のために生成されるアドレスとも — 異なる。この結果、リストへ投稿し
たり リストを購読停止したりできなくなることがある。
妥協案として、送信者のシグネチャに 受信者のド メインだけを組み込むことにするのもよいか
もしれない。すると送信者アドレスは次のようになる:
購読者名=en.tldp.org=ハッシュ@購読者の. ド メイン
– 二つめの問題は、リクエスト メールのメッセージヘッダにある 返信アドレスに返信するサーバ (
<[email protected]> のような) についてだ。 このアドレスはサイン
つきではないので、 サーバはリストサーバからの応答を阻止してしまう。
これについてできることはあまりない。 そういうやりかたをする特定のサーバを 「ホワイトリ
スト 」に入れ 、 サインなしの受信者アドレスへの返信を受け入れるようにするしかない。
ここまで来ると、このアプローチは切れ味が鈍ってくる。 さらに、元々のメールが自分のサーバから送信
されたのではなければ 、 それに対する真っ当な DSN も拒否される。したがって、 ユーザが移動 [ローミ
ング ] をしない場合、 あるいは逆に、自分で制御できない外部のサーバからユーザが メールを送る場合に
だけ、 実施を検討するべきだ。
とはいえ、上の検討事項がいずれも当てはまらない状況では、 この手法は巻き添えスパムを除去する手
段になるのはもちろん、 サイトの管理者に (おそらく意図せず ) 巻き添えスパムを発生させていることを教
える手段にもなる。 さらに副次効果として、[送信者呼出し確認法] [12] を実行しているサイトでは、 元々
のメールが実際に自分のサイトから送られているときだけ 肯定応答を受け取ることになる。要するに、 ス
パム送信者の送信者アドレス詐称に曝されにくくしていることになる。
23
外部へ行くメールにサインをつけるかど うかを、 ユーザに指定させたいかもしれない。そうであれば 、
サインなし版のアドレスへメールを返送することを認めるホストはどれなのかを 指定しなければならない。
例えば 、 ユーザがメールサーバのシステムアカウントを持っているときは、 ユーザのホームディレクトリ
にあるファイルが存在するかやその内容を検査できるだろう。
2.7.4
実在するユーザへのバウンスだけを受け付ける
エンヴェロープ送信者のシグネチャ検査にも抜け穴があって、 いんちきバウンスを受け付けてしまうこ
とがある。 特に、ユーザがこの方式に自分で加入しなければならないようにしているのなら、 postmaster
や mailer-daemon のような システムエイリアスに送られてくるメールについてはシグネチャを検査する
わけにいかない。 そのうえ、こういうアドレスは外部へ行くメールを生成しない。だから、 こういうアド
レスではどんなバウンスも受け取ってはいけない。
メールがこのようなシステムエイリアスに送られてきたら、拒否してよい。 または、与えられた受信者
アドレスが メールボックスを持っていなければ拒否する、 ということにしてもよい。
24
第 3 章 検討事項
概要
システム全体での SMTP の時点での排除が働くようにする前に、 特に検討すべきことがいくつかある。
複数の受入用メール交換機
3.1
多くのド メインが複数の受入用 メール交換機 [79] (別名 「 MX ホスト 」) を持っている。そうなってい
るのなら、 効果を挙げるために プライマリ MX で行なっている SMTP の時点での排除はほかの MX でも
行なうように 気をつけよう。そうしないと、 送信側のホストはバックアップサーバで再送を試みることで
排除をすり抜けられる。
バックアップサーバを自分で制御できないのなら、 まず、複数の MX が本当に必要なのか自問してみる
ことだ。 こういう状況では、 そのサーバが単に冗長なメールサーバとして働いていて メールをプライマ
リ MX に転送しているだけ、という可能性もある。 もしそうなら、おそらくそういうものは必要ないだろ
う。 ホストがときに短時間落ちたとしても、問題はない — 正しく動作する送信者ホストは、数日のあい
だ配送を再試行してからでないと 配送を諦めたりしない? 。
いくつかのサーバの間で負荷分散を実施するために、複数の MX を必要とする かもしれないという状況
— つまり、一つの計算機だけでは処理できないほどたくさんのメールを受け取っているとき。 この場合、
なにかの処理 (ウィルスや スパムの検出のような ) を他の計算機に移し 、 負荷を下げることによってその
ような必要性を軽減したり除去したりすることも考えてみよう。
それでも複数の MX を使い続けると決めたのなら、 バックアップサーバではプライマリサーバと同等 (以
上) の制限をかける必要がある、 そうしないと、プライマリ MX での排除が役に立たなくなる。
複数の MX ホストに関わるさらなる考慮点として、 [グレーリスト法] [15] についての節も見てほしい。
他の SMTP サーバへのアクセスを阻止する
3.2
自分のド メインの DNS ゾーンで公開のメール交換機 [79] に挙げられていない SMTP サーバは どれも、
インターネットからの外部接続を受け付けてはいけない。 外部から来るメールトラフィックはすべて、受
入用メール交換機を通さなければいけない。
この検討事項は、SMTP サーバに限ったことではない。 サイト内で内部利用目的だけで提供している計
算機は、 ファイアウォールを使ってアクセスを制限しよう。
規則には当然、例外がある。 しかし 、その例外がどんなものか分からない人は、上に書いたことを守る
こと。
3.3
転送されてきたメール
メールが次のような 「友好的」 な出所から転送されてきたときは、 スパム排除の結果で拒否しないよ
うに気をつけよう:
• バックアップ MX ホスト (あれば )。 そこでは、すでにほとんどのゴミを排除しているはずだから ([複
数の受入用メール交換機] [25] を見てほしい)。
25
• 自分のユーザが購読しているメーリングリスト。 こういうメールを排除するのはかまわない (受け付
けたうえで配送せずに捨ててしまったとしても、 さほど 深刻な問題は起きないだろう)。 しかしこう
いうメールを拒否してしまうと、 リストサーバが受信者を自動的に退会させてしまうことになるかも
しれない。
• 受信者がよそのサイトに持っているアカウント。 やはり、拒否は巻き添えスパムを引き起こすか、 あ
るいは、メールを転送しているホストで問題を起こす。
これらの出所のうち、あとの 2 つでは配送上の問題がありそうだ : これらの出所は受信者ごとに特有のもの
だ。 それぞれのユーザに、ホワイトリストに入れるホストをど うやって指定させるか、 そして、そういっ
た個々人のリストをど うやってシステム全体の SMTP の時点での排除に使うか。 メッセージが自分のサイ
トのある受信者に転送されてきているもの ( メーリングリストの場合はたいていがこれに当てはまる) なら、
誰のホワイトリストを使うかをど うやって決定するか。
この問題の解決法に、決定打はない。そこで、 すこしだけ作業をしなければならない。 受信者の誰かの
ホワイトリストにあるホストから送られてくるかぎりは スパム分類の結果に関わらずすべてのメールを受
け入れる、と決めることもできる。 例えば 、それぞれの RCPT TO: コマンド への応答の最中に、 送信側
のホストを関係するユーザのホワイトリストと照合する。 ホワイトリストに見つかればフラグを立て、以
降は拒否しないようにする。 実用上は、それぞれの受信者のホワイトリストを 総合したものを使うといい
だろう。
付録の実装では、この方法をより詳細に説明する。
3.4
ユーザごとの設定とデータ
状況によっては、 サイトのユーザそれぞれの設定やデータに対応したほうがいいだろう。 例えば 、外部
から来るメールを SpamAssassin ([スパム検出ソフトウェア] [21] を見てほしい) で検査しているのなら 、
スパム閾値、受け入れる言語や文字集合、Bayes 式の学習やデータを、 個々人が選べるようにしたほうが
いいだろう。
これの難点は、外部から来るメールの SMTP の時点での排除は メールが特定のユーザに配送される前に
システム段階で行なわれており、 そのため個々人の設定条件を十分に活用できない、という点だ。 一つ一
つのメッセージには、複数の受信者がありうる — そして[転送されてきたメール ] [25] の場合とはちがい、
それぞれの受信者の設定条件を総合するのは、よい選択肢ではない。 異なる言語的背景を持つユーザがい
る場合の筋書きも検討するようにしよう。
だが 、これはやりかた次第では正しくないことが判明している。 外部から来るメッセージの受信者の数
を 1 つに限ってしまう、という手だ。 こうすれば 、メッセージを一人一人のユーザの設定やデータで解析
できる。
これをするには、最初の RCPT TO: は受け付け、残りのコマンドには SMTP 451 (延期) 応答を発行
すればよい。 呼出し側が正しく動作する MTA であれば 、こういう応答の解釈のしかたが分かっているか
ら、 後でまた接続してくる (これで呼出し側が混乱してしまうようなら、 それはおそらく、もともとメー
ルを受け取りたくないような送信者からのものだろうね )。
しかしすぐにわかることだが 、これはその場しのぎの方法でしかない。 サイトの複数のユーザに送られ
るすべてのメールは、 受信者ごとに 30 分かそれ以上遅れていく。 特に法人組織では、 電子メールでの討
論が内部の複数の人々や外部の他の人々との間で進むことはよくあり、 メール配送の迅速さが重視される
ので、これはおそらく良い解決策とは言えないだろう。
主に法人企業や大規模なサイトで起きる問題は他にもある。 しばしば 、外部から来るメールを内部の計
算機に転送してから配送しており、 受信者は通常はメール交換機のアカウントを持っていない、というも
のだ。 こういう状況でも、ユーザ特有の設定やデータに対応することは可能 (例えばデータベース検索や
LDAP 問合せを通じて) だが 、 そこまでする価値があるのかど うか検討は必要だろう。
とはいえ、サイトが小規模で、配送の遅延が起こっても構わないのなら、 ユーザごとに排除の基準を細
かく調整できるようにする方法として受け入れられるかもしれない。
26
第 4 章 質問と回答
概要
本節では、ありそうな質問を検討し 、回答をしてみる。 ここにない疑問をお持ちの方や、本節に付け
加えられることのある方からの フィード バックをお待ちしている。
スパム送信者が適応してきたら
1. Q: スパム送信者が 、この文書で説明しているテクニックに適応して テクニックを回避しようとしてき
たら、ど うなりますか。
A: まあ、状況によるね。:-)
この文書で説明した検査のいくつか ([SMTP での検査] [10] や[グレーリスト法] [15] のような) は、 ラッ
ト ウェアの振舞いに特に狙いをつけている。 十分な数のサイトでこの検査が採用されるようになれば 、 振
舞いが変化することも十分考えられる。 Hatmut Danisch の注釈: ラット ウェアにはバグのある SMTP プ
ロト コルが入っているが、 これは、もっとよいものがさしあたり必要ないからだ。 それで十分用が足りて
いるのに、 さらに時間をかけなければいけない理由があるだろうか ? だがこの間、
「ラット ウェア」 の品
質は高くなってきており、 スパムメッセージの品質も著し く改善されてきている。 出来の悪い SMTP プ
ロト コルを検出することでスパムを拒否する人が十分に増えれば 、 スパムソフト ウェアの作者だってソフ
ト ウェアを改善するだろう。
とはいえ、このようなラットウェアには、まだ試練が立ちはだかっている:
• [SMTP トランザクションの遅延] [7] を回避するには、 受け手の SMTP サーバからの応答をいちいち
待つ必要がある。 この点で、我々は共同して、 あるスパム送信ホストが単位時間あたりに配送可能
なメールの量の 顕著な低下を達成してきている。 スパム送信者が DNS ブロックリストや協調型コ
ンテンツフィルタに追いつかれるまでに できるだけ多くのメールを送ろうと大忙しの間にも、 我々
はこういうツールの有効性を高めていくのである。
効果は、小額課金方式 [77] の結果と似たものになる。この方式では、 送信者はメールの受信者ごと
に計算問題をこなすのに数秒間を費やし 、 結果として受信者を確認するためのシグネチャを電子メー
ルヘッダに加える。 大きな違いは (この方式の複雑さは別にして) 、 小額課金方式では実質的に世界
全体の参加がないとスパムを取り除くのに役立たないのに対して、 SMTP トランザクションの遅延
は それを実装する最初の受信者の計算機ですぐ 役立つという点である。
• [HELO/EHLO 検査] [10] を回避するには、適切な挨拶をする、 つまり、有効な完全修飾ド メイン名
[76] で身許を明かす必要がある。 これは 、(とりわけ、 メッセージの Received: ヘッダに自動的に
DNS 逆引きの結果を挿入しない 受信側メール転送エージェント [79] では ) 追跡可能性を増大させる。
• [送信者アドレスの検査] [12] をすべてかいくぐ るには、 自身の有効な送信者アドレス (か、少なくと
も自身のド メインで有効な送信者アドレスの一つ) を使う必要がある。言うまでもないことだが。
• [グレーリスト法] [15] を回避するには、 一時的に失敗した受信者アドレスへの配送を 1 時間後に (た
だし 4 時間経たないうちに ) 再試行する必要がある。 (実装に関して言えば 、ラットウェアは計算機
資源を最小化するために、 一時的に失敗したメールの写しをひとつひとつ保持するのではなく 一時
的に失敗した受信者の一覧を保持し 、 1 、2 時間経ってからそのアドレスを再度調べるようになるだ
ろう)。
27
たとえそうなっても、 グレーリスト 法は、 スパムトラップ [77] がもたらす[DNS によるブラックリ
スト ] [9] と組み合わせることで、 依然としてかなりの効果を挙げることができる。 なぜならば 、1 時
間の再送遅延が義務づけられているため、 送信側のホストがリストに入る機会が増えるからだ。
[スパム検出ソフトウェア] [21] や[ウィルス検出ソフトウェア] [21] のようなソフトウェアツールは、 たえず
進歩し続けている。 スパム送信者が進歩するにつれ、これらのツールも進歩する (逆も言える)。 これらの
ツールの最新版を使っている限り、それは効果的であり続ける。
最後に、この文書そのものも、変化をまぬがれない。 不要メールの性質が変化していくにつれて、多く
の人々が 、新たな、 独創的な阻止の方法を編み出すことだろう。
28
付録 A
Exim による実装
概要
ここでは、この文書で説明したテクニックやツールの Exim メール転送エージェント [79] への統合に
ついて説明する。
A.1
必須事項
ここでの例には Exim メール転送エージェント [79] が必要だ。 Tom Kistner の Exiscan-ACL パッチが適
用してあることが望ましい。 Linux のよく普及しているディストリビューションや FreeBSD のためのビル
ド ずみ Exim+Exiscan-ACL パッケージもある — 詳しくは Exiscan-ACL1 ホームページを見てほしい23 。
ここでの実装例には、最終的には次のツールも取り込むことになる:
• SpamAssassin4 — よく普及しているスパム排除ツールで、 メールの内容を巨大で高度に洗練された
ヒューリスティックで解析する。
• greylistd5 — 著者が書いた、簡易なグレーリスト法の解決策。 Exim を特に念頭に置いて書いてある。
その他にも、例の全体を通じて、補助的なソフトウェアを使う。
A.2
Exim の設定ファイル
Exim の設定ファイルの最初には、全般的な定義 (これを 首節と呼ぼう) が置かれ、 その後にほかの節が
いくつか続く6 。ほかの節はそれぞれ :
begin 節
で始まる。
主に acl 節 (つまり begin acl の後) に時間をかける — しかし 、 transports 節や routers 節、さら
にファイルの最初にある首節でも、多少の項目を追加したり変更したりする。
A.2.1
アクセス制御リスト
1 http://duncanthrax.net/exiscan-acl/
2 Exim は、とりわけ Debian GNU/Linux http://www.debian.org/ のユーザの間ではおそらく最もよく普及している MTA で、
このディストリビューションの既定の MTA になっている。 Debian (「 Sarge 」かそれ以降) を使っているのなら、exim4-daemon-heavy
パッケージを導入すれば Exim+Exiscan-ACL を使えるようになる: # apt-get install exim4-daemon-heavy
3 [訳注] Exim 4.50 からは、 Exiscan-ACL パッチは Exim に標準で含まれるようになった。
4 http://www.spamassassin.org/
5 http://packages.debian.org/unstable/mail/greylistd
6 Debian ユーザ : exim4-config パッケージでは、 [訳注: パッケージをインストールする際に ] Exim の設定を分割した細かい断
片として /etc/exim4/conf.d 配下のサブデ ィレクトリにおさめるか、 それとも設定全部を単一のファイルにおさめるかを選べる。
前のほ うの選択肢 (こちらがお勧め!) を選んだのなら 、 exim4-config パッケージが 提供する標準の設定を変更せずに保っ
たまま、 それとは別にサブデ ィレ クト リの中に新し いファイルを作成してカスタマイズができる。 例えば 、/etc/exim4/conf.
d/acl/80 local-config rcpt to という名前のファイルを作成して RCPT TO: コマンド のための ACL を定義したりできる (下
記 を見てほしい)。
Exim の 「 init 」 スクリプト (/etc/init.d/exim4) が、 次に (再) 起動するときに、 自動的にこれらのファイルすべてを単一の
巨大な実行時設定ファイルにまとめる。
29
4.xx 版から、 Exim はいわゆるアクセス制御リスト (ACL) を採り入れている。 これはとても洗練され
ていて柔軟な機構で、 SMTP のあらゆる時点で排除を有効にできる。
ACL は、外部から来るメッセージのトランザクションのある状態 (リモートホストからの接続、HELO/EHLO 、
MAIL FROM: 、 RCPT TO: といった SMTP コマンド など ) を、受け付けるか拒否するかを判定する
のに使える。例えば 、 acl rcpt to という名前の ACL で、相手から受信する RCPT TO: コマンド をひ
とつひとつ確認したりもできる。
ACL は、一連の文 (あるいは 規則) から成る。文はそれぞれ、 accept [受け入れ ] 、 warn [警告] 、 require
[要求] 、 defer [延期] 、 deny [拒否] のような動作語7で始まり、 その後に条件、オプション 、 その他その
文に関係する設定が続く。 各々の文は記述された順序どおりに適用され、 動作が決まるとそこで実行は終
る (warn は別)。ACL の終りには暗黙の deny があるものとされる。
上記の acl rcpt to ACL の文は、 たとえばこんなふうになる:
deny
message
= relay not permitted
!hosts
= +relay_from_hosts
!domains = +local_domains : +relay_to_domains
delay
= 1m
この文では、
「 +relay from hosts 」 のホストリストにあるホストから配送されておらず、 受信者のド メ
インが 「 +local domains 」 か 「 +relay to domains 」 のド メインリストにない場合、 RCPT TO: コマ
ンド を拒否する。 ただし 、サーバはこのコマンドに 「 550 」 SMTP 応答を発行する前に 1 分間待つ。
メッセージトランザクションのある段階に特定の ACL を適用するには、 Exim の方針制御子8 のどれか
一つをその ACL に向ける必要がある。 例えば 、上で触れた acl rcpt to ACL を使って RCPT TO: に
適用するには、Exim 設定ファイルの首節 (全ての begin キーワード より前) に次のものを含める:
acl_smtp_rcpt = acl_rcpt_to
このような方針制御子の完全な一覧は、 Exim specifications の 14.11 節を参照してほしい。
A.2.2
展開
さまざまな展開要素9を使える。 これには実行時変数、検索関数、文字列/正規表現操作、ホスト /ド メイ
ンリスト、 などなどがある。最新の x.x0 リリース版 (つまり 4.20, 4.30..) での網羅的なリファレンスは、
「 spec.txt 」 ファイルにある — ACL は 38 節 [訳注: 4.50 版では 39 節] で説明してある。
特に、Exim には 20 種の汎用展開変数があり、ACL 文の中でこれに値を代入できる:
• $acl c0 から $acl c9 までは、 ある SMTP 接続が続く間は持続的に値を保持できる。
• $acl m0 から $acl m9 までは、 メッセージを受け取っている間は値を保持できるが その後に初期化
される。これらはまた HELO 、 EHLO 、 MAIL 、 RSET の各コマンド でも初期化される。
A.3
オプションと設定
Exim 設定ファイルの首節 (最初の begin キーワード より前) は、さまざまなマクロ、 方針制御子、その
他の一般設定を含む。まず、後で使うマクロをいくつか 定義しておこう:
# メッセージサイズの限度を定義する --- これは DATA ACL で使う.
MESSAGE_SIZE_LIMIT = 10M
7 [訳注]
verb。
policy control。
9 [訳注] expansion item 。
8 [訳注]
30
# スパムやウィルスの検出を実行するメッセージサイズの最大.
# これで、極めて大きなメッセージでサーバに負荷がかかってしまうことを減らせる.
MESSAGE_SIZE_SPAM_MAX = 1M
# さまざ まなハッシュを生成するための秘密の文字列を定義するマクロ.
# *必ず変えてほしい*.
SECRET = some-secret
一般的な Exim の設定をまとめておこう:
# DNS の失敗 (SERVFAIL) を検索失敗とみなす.
# これは , 存在しないド メインやネームサーバが存在しないド メインの
# 送信者アドレスを , 後で拒否するためである.
dns_again_means_nonexist = !+local_domains : !+relay_to_domains
# すべてのホストに対して, ACL にある HELO 確認を有効にする.
helo_try_verify_hosts = *
# 外部から一度に受け付けられる接続最大数の制限をすべてなくす. これは
# あとでスパム送信者に SMTP トランザクションの遅延をはさんでいる間も新たな
# 接続を拒絶しないためである.
smtp_accept_max = 0
# .. ただし , システム負荷が 10 を超せば接続を拒絶する.
smtp_load_reserve = 10
# ESMTP の "PIPELINING" を , どのホストにも広告しない.
# これは , いつでもパイプラインを試すようなラットウェアをけつまずかせるためだ .
pipelining_advertise_hosts = :
最後に、Exim の方針制御子をこれから作成する 5 つの ACL に向け、 外部から来る SMTP トランザク
ションのさまざ まな段階で適用できるようにする。
acl_smtp_connect = acl_connect
acl_smtp_helo
= acl_helo
acl_smtp_mail
= acl_mail_from
acl_smtp_rcpt
acl_smtp_data
A.4
= acl_rcpt_to
= acl_data
ACL の構築 — 第一段階
acl 節 (begin acl に続く箇所) では、 以下の ACL を定義する必要がある。これによって、 この文書
の前のほうで述べた基本的な [テクニック ] [7] をいくつか組み込むことができる — [DNS による検査] [8]
と [SMTP での検査] [10] である。
この段階では、[acl rcpt to] [32] で検査のほとんどを行ない、 他の ACL はほとんど 空にしておく。なぜ
なら、よく使われているラットウェアのほとんどは、 SMTP トランザクション初期に拒否しても気づかな
いからだ — 送信を試しつづける。 いっぼうラットウェアクライアントのほとんどは、 RCPT TO: が失
敗すると諦める。
しかし 、これらの ACL すべてを作成しておく。後で使うことになるからだ。
31
A.4.1
acl connect
# このアクセス制御リストは , 外部からの接続の開始の際に使う.
# 検査は順に実行され , 接続を受け付けるか拒否するまで続く.
acl_connect:
# 現段階では , ここでなんの検査も実施しない.
accept
A.4.2
acl helo
# このアクセス制御リストは , 外部から来る SMTP トランザクションの HELO コマンド や
# EHLO コマンド で使う. 検査は順に実行され . 挨拶を受け付けるか拒否するまで続く.
acl_helo:
# 現段階では , ここでなんの検査も実施しない.
accept
A.4.3
acl mail from
# このアクセス制御リストは , 外部から来る SMTP トランザクションの MAIL FROM:
# コマンドに使う. テストは順に実行され , 送信者アドレスが受け付けられるか拒否
# されるかすると , そこで終る.
#
acl_mail_from:
# コマンド を受け付ける.
accept
A.4.4
acl rcpt to
# このアクセス制御リストは , 外部からの SMTP メッセージの RCPT コマンドごと
# に使う. テストは順に実行され , 受信者アドレスが受け付けられるか拒否される
# かすると , そこで終る.
acl_rcpt_to:
# ローカルの SMTP 経由 (つまり TCP/IP 経由でない) で受け取ったメールを受
# け付ける. 空の送信側ホスト項目でこれをテストする.
32
# また, メールのリレーのためのホストからのメールも受け付ける.
#
# 受信者確認はここではしない. しばしば , クライアントが低能な MUA で ,
# こういったものは SMTP エラー応答にうまく対応できないためだ .
#
accept
hosts
= : +relay_from_hosts
# メッセージが認証された接続を通じて届いたら , どのホストからでも受け付ける.
# ここでも, こういったメッセージは普通は MUA からなので , 受信者確認はしない.
#
accept
authenticated = *
######################################################################
# DNS による検査
######################################################################
#
# 以下の検査の結果はキャッシュされるので , 複数の受信者があっても
# 複数の DNS 検索は発生しない.
#
# 接続してきているホストが特に選別した DNSbl に登録されていれば ,
# メッセージを拒否する. リストの選別には注意を要する --- 多くのものが ,
# 大量の偽陽性を発生させるし , また, リストからの削除について明確な方針が
# なかったりする.
#
deny
dnslists
= dnsbl.sorbs.net : \
dnsbl.njabl.org : \
cbl.abuseat.org : \
message
bl.spamcop.net
= $sender_host_address is listed in $dnslist_domain\
${if def:dnslist_text { ($dnslist_text)}}
# 送信者ホストの DNS 逆引きが失敗したら (つまり, 逆引きエントリがないか , 逆引き
# の結果の名前の正引きが元の IP アドレスに一致しなかったら ), メッセージを拒否する.
#
deny
message
!verify
= Reverse DNS lookup failed for host $sender_host_address.
= reverse_host_lookup
######################################################################
33
# ハローの検査
######################################################################
# リモートホストが IP アドレスで挨拶してきたら , メールを拒否する.
#
deny
message
= message was delivered by ratware
log_message = remote host used IP address in HELO/EHLO greeting
condition
= ${if isip {$sender_helo_name}{true}{false}}
# 相手が自分の名前のどれかで挨拶してきたときも同様
#
deny
message
= message was delivered by ratware
log_message = remote host used our name in HELO/EHLO greeting.
condition
= ${if match_domain{$sender_helo_name}\
{$primary_hostname:+local_domains:+relay_to_domains}\
{true}{false}}
deny
message
= message was delivered by ratware
log_message = remote host did not present HELO/EHLO greeting.
condition
= ${if def:sender_helo_name {false}{true}}
# HELO の確認が失敗したら , X-HELO-Warning: ヘッダをメッセージに追加する.
#
warn
message
= X-HELO-Warning: remote host $sender_host_address \
${if def:sender_host_name {($sender_host_name) }}\
incorrectly presented itself as $sender_helo_name
log_message = remote host presented unverifiable HELO/EHLO greeting.
!verify
= helo
######################################################################
# 送信者アドレスの検査
######################################################################
# 送信者アドレスが確認できなければ , メッセージを拒絶する.
#
# "callout" [呼出し ] オプションを削除してもよい. 特に ,
# 外部へ行くメールをスマートホストを通じて送っているのなら , これは有用な情報を
# なにも与えてくれない.
#
34
# 呼出し確認が 550 応答で失敗する場合について --- これをしないためには ,
# "sender/callout" を "sender/callout,no_details" に変える.
#
deny
message
!verify
= <$sender_address> does not appear to be a \
valid sender address.
= sender/callout
######################################################################
# 受信者アドレスの検査
######################################################################
# ローカル部が @ や % や / や | や ! を含んでいれば拒絶.
# こういったものは , 本物のローカル部にはまず現れないが , リレー制限の抜け穴
# を探す輩がよく試すものだ .
#
# ド ットで始まるローカル部なら , これも拒絶. 空のコンポーネントは厳密には
# RFC 2822 違反だが , これはよくあるので Exim では受け入れる. しかし ,
# ド ットで始まっているものは , ローカル部がファイル名として使われる場合
# (例えば メーリングリストのために ) にトラブルを起こすかもしれない.
#
deny
local_parts = ^.*[@%!/|] : ^\\.
# エンヴェロープ送信者が空なのに受信者アドレスが複数あれば , 接続を切る.
# 真っ当な DSN は , 1 つより多くのアドレスに送ったりしない.
#
drop
message
= Legitimate bounces are never sent to more than one \
recipient.
senders
condition
= : postmaster@*
= $recipients_count
# 我々が メールを扱うド メインにない受信者アドレスなら拒否する.
#
deny
message
!domains
= relay not permitted
= +local_domains : +relay_to_domains
# 有効なメールボックスでない受信者は拒絶する.
# メールボックスが我々のシステムにないのなら (例えば受信者ド メインの
# バックアップ MX であるのなら ), 呼出し確認を実施する --- しかし ,
# もしも目的のサーバが応答しなければ , 受信者はいずれにせよ受け付ける.
35
#
deny
message
!verify
= unknown user
= recipient/callout=20s,defer_ok
# さもなければ , 受信者アドレスは問題ない.
#
accept
A.4.5
acl data
# このアクセス制御リストは , SMTP を通じて受け取るメッセージデータに使う.
# テストは順に実行され , 受信者アドレスが受け付けられるか拒絶されたところ
# で終る.
acl_data:
# 自身のホストから受け取ったメッセージに Message-ID がなければ追加する.
warn
condition
= ${if !def:h_Message-ID: {1}}
hosts
message
= : +relay_from_hosts
= Message-ID: <E$message_id@$primary_hostname>
# ローカルの SMTP 経由 (つまり TCP/IP 経由でない) で受け取ったメールを受け付ける.
# 空の送信側のホスト項目をテストすることで , これを行なう.
# また, メールのリレーに使うホストから受け取ったメールも受け付ける.
#
accept
hosts
= : +relay_from_hosts
# メッセージが認証された接続を通じて届いたら , どんなホストでも受け付ける.
#
accept
authenticated = *
# メッセージサイズの限度を課す
#
deny
message
condition
= Message size $message_size is larger than limit of \
MESSAGE_SIZE_LIMIT
= ${if >{$message_size}{MESSAGE_SIZE_LIMIT}{true}{false}}
# アドレスリストのヘッダが構文的に正しくなければ拒絶する.
36
#
deny
message
= Your message does not conform to RFC2822 standard
log_message = message header fail syntax check
!verify
= header_syntax
# Message-ID や Date のない非ローカルメッセージは拒絶する
#
# 一部の特殊化された MTA (ある種のメーリングリストサーバのような ) は ,
# バウンスの Message-ID を自動的に生成しないことに注意.
# そのため, 空でない送信者の検査も追加する.
#
deny
message
= Your message does not conform to RFC2822 standard
log_message = missing header lines
!hosts
!senders
= +relay_from_hosts
= : postmaster@*
condition
= ${if or {{!def:h_Message-ID:}\
{!def:h_Date:}\
{!def:h_Subject:}} {true}{false}}
# 少なくとも "Sender:", "Reply-To:", "From:" のヘッダのいずれかに
# 確認できる送信者アドレスがなければ , 警告する.
#
warn
message
= X-Sender-Verify-Failed: No valid sender in message header
log_message = No valid sender in message header
!verify
= header_sender
# メッセージを受け付ける.
#
accept
A.5
A.5.1
SMTPト ランザクションの遅延を追加する
簡易な方法
SMTP トランザクションの遅延を追加するいちばん簡単な方法は 、 定義した ACL それぞれの最後の
accept 文に delay 制御子を追加することだ。次のようにする:
accept
delay = 20s
加えて、 [acl rcpt to] [32] 中で deny 文に、 無効な受信者に関する文 (「 unknown user 」) ごとに増加
37
していく遅延を追加することもできよう。これは辞書攻撃を遅める。 例えば :
deny
message
!verify
= unknown user
= recipient/callout=20s,defer_ok,use_sender
delay
= ${eval:$rcpt_fail_count*10 + 20}s
[acl data] [36] の中でメッセージデータを受け取ってしまった後には、 遅延をはさめるところはないこと
に注意しなければならない。 ラットウェアはしばしば 、サーバからの応答を受信する前でも、ここで切断
する。 Exim は、クライアントがここで切断してもしなくても関係なくいつでも、 メッセージの配送を続
行する。
A.5.2
選択的な遅延
SMTP トランザクションの遅延を、どのホストではさむか選べるようにしたくないだろうか。 例えば 、
この文書の前のほうで述べたように、 DNS によるブラックリストで一致するものや EHLO/HELO 挨拶で
の確認ができないものは、 それだけでは拒否してよいと断定できる条件ではないと言えそうだ — しかし 、
こういったものはトランザクションの遅延には充分な契機となる。
選択的な遅延を実施するために、以前は [acl rcpt to] [32] でしていた検査を、 SMTP トランザクション
の初期に移動する。 これは、問題の徴候が見つかったらできるだけ早く遅延をはさみはじめられるように
し 、 そうすることでラットウェアが同期エラーその他の問題を起こす機会を増やすためだ。
具体的には、次のようにしたい:
• DNS による検査を [acl connect] [60] へ移動する。
• ハローの検査を [acl helo] [61] へ移動する。 例外が一つある: そこでは、ハロー挨拶がないことの検
査はまだできない。 なぜならその ACL は、 EHLO コマンド や HELO コマンド への応答の際に 処理
されるからだ。この検査は [acl mail from] [62] ACL でする。
• 送信者アドレスの検査を [acl mail from] [62] へ移動する。
ただし 、上で述べた理由から、RCPT TO: コマンド より後になるまでは実際にメールを拒否したくはな
い。 かわりに、ACL のはじめのほうのさまざ まな deny [拒絶] 文を warn [警告] 文に変更し 、 Exim の汎
用 ACL 変数にエラーメッセージや警告を格納しておいて、 RCPT TO: コマンド の後で使うことにする。
以下のようにしてできる:
• 配送を拒否すると判断したら、後の 550 応答で使うメッセージを $acl c0 か $acl m0 に格納する:
– メール配送が始まるより前 (つまり [acl connect] [60] か [acl helo] [61] の中で ) に条件を満たし
たら、 接続の間維持される変数 $acl c0 を使う
– メールトランザクションが始まってし まったら (つまり MAIL FROM: コマンド より後) 、
$acl c0 の内容はなんでも、 メッセージごとの変数 $acl m0 に複写し 、 以降は後者を使う。 こ
れにより、特定のメッセージが満たす条件は、 以後同じ接続で受け取るメッセージには影響し
ない。
また、関連する 記録メッセージ を $acl c1 か $acl m1 に、同様のやりかたで格納する。
• 即座に拒否してよいと断定できない条件に出くわしたときは、 $acl c1 か $acl m1 に警告メッセー
ジを格納するだけにして、 メールトランザクションが始まってから (つまり [acl mail from] [62] の
中で ) 、 この変数の内容をメッセージヘッダに追加する。
• 以降の検査 (SpamAssassin による検出のような ) の結果に関わらずメッセージを受け付けることに
なったら、 $acl c0 か $acl m0 にフラグをセットするが 、 $acl c1 や $acl m1 は空にする。
38
• すべての ACL の最初と [acl mail from] [62] で、$acl m2 に現在のタイムスタンプを記録する。 ACL
の最後では、$acl c1 か $acl m1 が存在すれば 、 合計 20 秒が経過するまで SMTP トランザクショ
ンの遅延をする。
以下に、変数の用法をまとめておく:
Table A.1: ACL での接続/ メッセージ変数の用法
変数:
$acl [cm]0 未代入
$acl [cm]0 代入ずみ
$acl [cm]1 未代入
(未定)
メールを受け付け
$acl [cm]1 代入ずみ
ヘッダに警告を追加
メールを拒否
このアプローチの例として、ハロー挨拶への応答のときに行なう 2 つの検査を考えてみよう — ひとつ
は、相手が IP アドレスで挨拶したらメールを拒否し 、 もうひとつは、挨拶に無効な名前があれば警告す
る。 以前は、ど ちらの検査も [acl rcpt to] [32] で行なっていた — 今度はこれらを [acl helo] [61] ACL へ
移動する:
acl_helo:
# 以降の遅延の継続期間を計算するために , 現在のタイムスタンプを記録する
warn
set acl_m2 = $tod_epoch
# ローカルの SMTP 経由 (つまり TCP/IP 経由ではない) で受信したメールを受け入れる.
# 空の送信側ホスト項目をテストすることでこれを行なう.
# また, メールをリレーするためのホストから受信したメールも受け入れる.
#
accept
hosts
= : +relay_from_hosts
# リモートホストが IP アドレスで挨拶したら , $acl_c0 に拒否メッセージを ,
# $acl_c1 に記録用メッセージを用意する. これらは後で "deny" 文の中で使う.
# しばらくの間, これらの存在で送信者を足止めしておかなければならないことを示す.
#
warn
condition
set acl_c0
= ${if isip {$sender_helo_name}{true}{false}}
= Message was delivered by ratware
set acl_c1
= remote host used IP address in HELO/EHLO greeting
# HELO の確認が失敗したら , acl_c1 に警告メッセージを用意する.
# このメッセージは , 後でメールヘッダに追加する.
# しばらくの間, これの存在で送信者を足止めしておかなければならないことを示す.
#
warn
condition
!verify
= ${if !def:acl_c1 {true}{false}}
= helo
set acl_c1
= X-HELO-Warning: Remote host $sender_host_address \
39
${if def:sender_host_name {($sender_host_name) }}\
incorrectly presented itself as $sender_helo_name
log_message = remote host presented unverifiable HELO/EHLO greeting.
#
# ... さらなる検査. この例では略す ...
#
# 接続を受け付ける. ただし , 前に $acl_c1 にメッセージを生成しているのなら ,
# 20 秒が経過するまで送信者を足止めする.
accept
set acl_m2
delay
= ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
= ${if >{$acl_m2}{0}{$acl_m2}{0}}s
そして [acl mail from] [62] では 、 $acl c{0,1} に入っているメッセージを $acl m{0,1} へ伝達する。
また、 $acl c1 の内容をメッセージヘッダに追加する。
acl_mail_from:
# 以降の遅延の継続期間を計算するために , 現在のタイムスタンプを記録する
warn
set acl_m2 = $tod_epoch
# ローカルの SMTP 経由 (つまり TCP/IP 経由ではない) で受信したメールを受け入れる.
# 空の送信側ホスト項目をテストすることでこれを行なう.
# また, メールをリレーするためのホストから受信したメールも受け入れる.
#
accept
hosts
= : +relay_from_hosts
# ACL 変数 $acl_c0 と $acl_c1 がもしあれば , 拒否や警告のメッセージを含んでいる
# ので , この SMTP トランザクションでの配送の試みひとつひとつにこれを適用する.
# これらの変数をメッセージごとの $acl_m{0,1} 変数に代入し , $acl_m1 の警告メッ
# セージをメッセージヘッダに追加する (拒否の場合は , $acl_m1 には記録用メッセージ
# が入っていることになるが , かまわない. ヘッダを追加するはずのメッセージはど うせ
# 破棄するのだから ).
#
warn
set acl_m0
set acl_m1
= $acl_c0
= $acl_c1
message
= $acl_c1
#
# ... さらなる検査. この例では略す ...
#
40
# 送信者を受け付ける. ただし , 前に $acl_c1 にメッセージを生成しているのなら ,
# 20 秒が経過するまで送信者を足止めする.
accept
set acl_m2
delay
= ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
= ${if >{$acl_m2}{0}{$acl_m2}{0}}s
後の[できあがった ACL] [60] では、このような変更がすべてしてある。
A.6
グレーリスト 法への対応を追加する
Exim でのグレーリスト法の実装にはいくつか選択肢がある。 ここでは、そのうちの 2 つについて説明
する。
A.6.1
greylistd
これは、著者が開発した Python での実装である (そういうわけで、後の[できあがった ACL] [60] にはこ
の実装を含めてある)。 これは独立したデーモンとして動作し 、外部データベースを用いない。 効率のた
めに、グレーリストのデータを単純な 32 ビットハッシュに蓄える。
これは http://packages.debian.org/unstable/mail/greylistd にある。 Debian のユーザなら 、
APT を通じて手に入る:
# apt-get install greylistd
greylistd を使うには、 先ほど 定義した [acl rcpt to] [64] ACL で、最後の accept 文の直前に、2 つの
文を入れる:
# "greylistd" を使って、この特定の相手/送信者/受信者の三つ組に対するグレーリス
# トの状態を得る.
#
# 送信者が空のメッセージはグレーリストしない. なぜなら送信者呼出し確認が失敗
# する (そのため, 呼出しを実施しているホストへメールを送れなくなりかねない) から
# だ.
#
defer
message
= $sender_host_address is not yet authorized to deliver mail \
from <$sender_address> to <$local_part@$domain>. \
Please try later.
log_message = greylisted.
domains
!senders
= +local_domains : +relay_to_domains
= : postmaster@*
set acl_m9
set acl_m9
condition
= $sender_host_address $sender_address $local_part@$domain
= ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
= ${if eq {$acl_m9}{grey}{true}{false}}
いんちきな配送状況通知 [78] を阻止するためにエンヴェロープ送信者のシグネチャを組み込んでいるの
でない限り、 [acl data] [69] にも同様の文を追加して、 送信者が空のメッセージもグレーリストしたほう
がよいかもしれない。
acl data でグレーリスト法のために使うデータは、上のものと少し異なる。 ここでは $sender address
が空であり、そのうえ $local part や $domain を定義していない。かわりに、すべての受信者アドレス
41
のカンマ区切りリストを 含む変数 $recipients がある。 真っ当な DSN では、アドレスが一つだけでな
ければならない。
# ここでは , エンヴェロープ送信者のないメッセージにグレーリスト法を実施する.
# RCPT TO: の後ではこういったものをグレーリスト法にかけていない.
# 送信者呼出しをしているリモートホストの邪魔になるからだ .
#
defer
message
なぜなら
= $sender_host_address is not yet authorized to send \
delivery status reports to <$recipients>. \
Please try later.
log_message = greylisted.
senders
set acl_m9
= : postmaster@*
= $sender_host_address $recipients
set acl_m9
condition
= ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
= ${if eq {$acl_m9}{grey}{true}{false}}
A.6.2
MySQL による実装
a sipsolutions.net> から提供されたもので、一部は次の
以下の実装は、 Johannes Berg <johannes°
ものに基づいている:
a theinternetco.net> による成果。 http://theinternetco.net/
• Rick Stewart <rick.stewart°
projects/exim/greylist で公開されている。これはさらに、次のものに基づいている
a raw.no> による、Postgres での実装。 http://raw.no/personal/blog/
• Tollef Fog Heen <tfheen°
tech/Debian/2004-03-14-15-55 greylisting で手に入る
これには、外部プログラムが要らない — 実装は、 以下の設定の断片と MySQL データベースだけに基づ
いている。
設定の断片の最新版に加え README ファイルも含むアーカイブが、次の場所で手に入る: http://johannes.sipsolutions.net/
Projects/exim-greylist10 。
システムに MySQL をインストールしてある必要がある。MySQL のプロンプトで、 exim4 データベー
ス、そして 2 つのテーブル exim greylist と exim greylist log を作成する。以下のようにする:
CREATE DATABASE exim4;
use exim4;
CREATE TABLE exim_greylist (
id bigint(20) NOT NULL auto_increment,
relay_ip varchar(80) default NULL,
sender varchar(255) default NULL,
recipient varchar(255) default NULL,
block_expires datetime NOT NULL default ’0000-00-00 00:00:00’,
record_expires datetime NOT NULL default ’9999-12-31 23:59:59’,
create_time datetime NOT NULL default ’0000-00-00 00:00:00’,
type enum(’AUTO’,’MANUAL’) NOT NULL default ’MANUAL’,
passcount bigint(20) NOT NULL default ’0’,
blockcount bigint(20) NOT NULL default ’0’,
10 [訳注]
原文の URL はアクセスできなくなっていたので修正した。
42
PRIMARY KEY
(id)
);
CREATE TABLE exim_greylist_log (
id bigint(20) NOT NULL auto_increment,
listid bigint(20) NOT NULL,
timestamp datetime NOT NULL default ’0000-00-00 00:00:00’,
kind enum(’deferred’, ’accepted’) NOT NULL,
PRIMARY KEY (id)
);
Exim 設定ファイルの首節で、 以下のマクロを定義する。
# まだデータベースサーバの定義がなければ , ここで定義する
hide mysql_servers = localhost/exim4/ユーザ/パスワード
# オプション
# 次のものは , mysql で DATE_ADD(..,INTERVAL xxx) の xxx に書けるものである
# 必要がある. 例えば , 複数形は書けない: "2 HOURS" ではなく "2 HOUR"
GREYLIST_INITIAL_DELAY = 1 HOUR
GREYLIST_INITIAL_LIFETIME = 4 HOUR
GREYLIST_WHITE_LIFETIME = 36 DAY
GREYLIST_BOUNCE_LIFETIME = 0 HOUR
# テーブル名は変えてもよい
GREYLIST_TABLE=exim_greylist
GREYLIST_LOG_TABLE=exim_greylist_log
# 次の行をコメントアウトすれば , グレーリスト法を (一時的に ) 無効にできる
GREYLIST_ENABLED=
# 次の行のコメントを外すと, 記録が有効になる
#GREYLIST_LOG_ENABLED=
# 通常, これ以降はなにも変更する必要がない
.ifdef GREYLIST_ENABLED
# データベースのためのマクロ
GREYLIST_TEST = SELECT CASE \
WHEN now() > block_expires THEN "accepted" \
ELSE "deferred" \
END AS result, id \
FROM GREYLIST_TABLE \
WHERE (now() < record_expires) \
AND (sender
= ’${quote_mysql:$sender_address}’ \
OR (type=’MANUAL’ \
AND (
sender IS NULL \
OR sender = ’${quote_mysql:@$sender_address_domain}’ \
) \
43
) \
) \
AND (recipient
= ’${quote_mysql:$local_part@$domain}’ \
OR (type = ’MANUAL’ \
AND (
recipient IS NULL \
OR recipient = ’${quote_mysql:$local_part@}’ \
OR recipient = ’${quote_mysql:@$domain}’ \
) \
) \
) \
AND (relay_ip
= ’${quote_mysql:$sender_host_address}’ \
OR (type=’MANUAL’ \
AND (
relay_ip IS NULL \
OR relay_ip = substring(’${quote_mysql:$sender_host_address}’, \
1,length(relay_ip)) \
) \
) \
) \
ORDER BY result DESC LIMIT 1
GREYLIST_ADD = INSERT INTO GREYLIST_TABLE \
(relay_ip, sender, recipient, block_expires, \
record_expires, create_time, type) \
VALUES ( ’${quote_mysql:$sender_host_address}’, \
’${quote_mysql:$sender_address}’, \
’${quote_mysql:$local_part@$domain}’, \
DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_DELAY), \
DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_LIFETIME), \
now(), \
’AUTO’ \
)
GREYLIST_DEFER_HIT = UPDATE GREYLIST_TABLE \
SET blockcount=blockcount+1 \
WHERE id = $acl_m9
GREYLIST_OK_COUNT = UPDATE GREYLIST_TABLE \
SET passcount=passcount+1 \
WHERE id = $acl_m9
GREYLIST_OK_NEWTIME = UPDATE GREYLIST_TABLE \
SET record_expires = DATE_ADD(now(), \
INTERVAL GREYLIST_WHITE_LIFETIME) \
WHERE id = $acl_m9 AND type=’AUTO’
GREYLIST_OK_BOUNCE = UPDATE GREYLIST_TABLE \
SET record_expires = DATE_ADD(now(), \
INTERVAL GREYLIST_BOUNCE_LIFETIME) \
44
WHERE id = $acl_m9 AND type=’AUTO’
GREYLIST_LOG = INSERT INTO GREYLIST_LOG_TABLE \
(listid, timestamp, kind) \
VALUES ($acl_m9, now(), ’$acl_m8’)
.endif
そして、ACL 節 (begin acl の後) で、 「 greylist acl 」 という名の ACL を新たに作成する:
.ifdef GREYLIST_ENABLED
# この ACL は deny [拒否] か accept [受け入れ ] を返す.
# defer [延期] 文の中で acl = greylist_acl として使う.
# 受け入れると条件が真となるので延期し , 拒否すると条件が偽となるので延期しない
greylist_acl:
# 通常の配送では , グレーリスト検査をする.
# グレーリストの三つ組を検査し , acl_m8 に "accepted", "deferred",
# "unknown" のいずれかを , また acl_m9 にレコード ID を返す.
warn set acl_m8 = ${lookup mysql{GREYLIST_TEST}{$value}{result=unknown}}
# acl_m8 = "result=x id=y" になる
set acl_m9 = ${extract{id}{$acl_m8}{$value}{-1}}
# ここで acl_m9 にはレコード ID (または -1) が入る
set acl_m8 = ${extract{result}{$acl_m8}{$value}{unknown}}
# ここで acl_m8 には unknown/deferred/accepted のいずれかが入る
# 既知の三つ組かど うか検査し , そうでなければ メッセージを追加して延期する
accept
# 上の検査が unknown (レコードがまだない) を返したら
condition = ${if eq{$acl_m8}{unknown}{1}}
# レコード の追加もする
condition = ${lookup mysql{GREYLIST_ADD}{yes}{no}}
# ここで , 結果が何かにかかわらず記録する
# 三つ組が未知なら , 上記の作成時刻からわかるので , エントリを記録する必要はない
# (ので , エントリを取得しない).
.ifdef GREYLIST_LOG_ENABLED
warn condition = ${lookup mysql{GREYLIST_LOG}}
.endif
# 三つ組がまだ阻止中かど うか検査する
accept
# 上の検査が deferred を返したら延期し
condition = ${if eq{$acl_m8}{deferred}{1}}
# そのことを記録する
condition = ${lookup mysql{GREYLIST_DEFER_HIT}{yes}{yes}}
45
# 見つかったレコード の数を記録するのに warn 動作語を使う
warn condition = ${lookup mysql{GREYLIST_OK_COUNT}}
# warn 動作語を使い, メールがバウンスでなかったときに限り自動記録の新たな消去
# 期限をセットする. バウンスであったときは now() をセットする.
warn !senders = : postmaster@*
condition = ${lookup mysql{GREYLIST_OK_NEWTIME}}
warn senders = : postmaster@*
condition = ${lookup mysql{GREYLIST_OK_BOUNCE}}
deny
.endif
この ACL を [acl rcpt to] [64] に入れると、 送信者アドレスが空でない三つ組をグレーリストする。 送
信者呼出し確認法ができるようにするには、次のようにする:
.ifdef GREYLIST_ENABLED
defer !senders = : postmaster@*
acl
message
= greylist_acl
= greylisted - try again later
.endif
また、[acl data] [36] 部にもこれを入れるが 、 今度は送信者アドレスが空のときだけ働く。 これは、ス
パム送信者が送信者アドレスを空にすることで グレーリスト法を回避するのを防ぐためだ。
.ifdef GREYLIST_ENABLED
defer senders = : postmaster@*
acl
message
= greylist_acl
= greylisted - try again later
.endif
A.7
SPF の検査を追加する
ここでは、Exim を使って[Sender Policy Framework] [17] レコード を検査する方法を 2 つ説明する。 こ
こで説明する機構のほかに、 SpamAssassin スイートには近いうちに (2.70 版あたりで ) 、 洗練された SPF
検査がとりいれられるはずだ。これは、 さまざ まな SPF の結果に重みづけのある得点を割り振れる。
この検査を、[acl mail from] [62] ACL のかなりはじめのほうで実施することもできたのだが この判断に
影響を与える問題点がある: SPF は伝統的な電子メール転送と互換性がない。 転送元のホストが SRS11を
実装していないかぎり、 転送されてきたメールでも エンヴェロープ送信者 [76] アドレスのド メインの SPF
方針によって送信を認証されていないホストから届いたという理由で拒否してしまうだろう。
これを避けるために、 転送されてきたメールを受け付けなければならないホストの一覧を、 ユーザごと
に参照する必要がある (以下の[転送されてきたメールを通す] [58] で説明する)。 これは、受信者のユーザ
名がわかる RCPT TO: より後でのみ可能になる。
そこで、[acl rcpt to] [64] の中で、 どのグレーリスト法や最後の accept 文よりも前に、この検査を追
加する。
A.7.1
Exiscan-ACL による SPF の検査
11 http://spf.pobox.com/srs.html
46
Tom Kistner の Exiscan-ACL パッチ ([必須事項] [29] を見てほしい) の最近の版には、 組み込みの SPF
対応がある12 。 使いかたはとても簡単だ。 spf という ACL 条件が追加される。 この条件の結果を pass 、
fail 、 softfail 、 none 、 neutral 、 err perm 、 err temp といったキーワード で調べる。
[acl rcpt to] [64] で、 すべてのグレーリスト法検査や最後の accept 文よりも前に、以下の断片を挿入
する:
# 送信者アドレスのド メインについての SPF 情報を問い合わせ, もしあれば ,
# 送信側のホストがそのメールの配送を認証されているか調べる.
# 認証されていなければ , そのメールは拒否する.
#
deny
message
= [SPF] $sender_host_address is not allowed to send mail \
from $sender_address_domain
log_message = SPF check failed.
spf
= fail
# メッセージに SPF-Received: ヘッダを追加する
warn
message
= $spf_received
この文では、 送信者アドレスのド メインの持ち主が呼出し側のホストからの配送を認めていなければ 、
そのメールを拒否する。 ただこのやりかたは、ド メインの持ち主が公告する情報にいささか頼りすぎてい
るため、 必要なメールまで拒否してしまう場合もあるかもしれない。 お勧めの対案は、SPF 検査を送信者
呼出し確認法のような他の検査と組み合わせることだ (だがその前に注意しておいてほしいが 、 外部へ行
くメールをスマートホストを通じて送っているのなら、 これはできない):
# 送信者アドレスを呼出し確認できず , 送信側ド メインの SPF 情報が送信側
# のホストに明らかな権限を与えていなければ , メールを拒否する.
#
deny
message
= The sender address does not seem to be valid, and SPF \
information does not grant $sender_host_address explicit \
authority to send メール from $sender_address_domain
log_message = SPF check failed.
!verify
= sender/callout,random,postmaster
!spf
= pass
# メッセージに SPF-Received: ヘッダを追加する
warn
message
A.7.2
= $spf_received
Mail::SPF::Query による SPF の検査
Mail::SPF::Query は、SPF の公式なテストスイートである。http://spf.pobox.com/downloads.html
で手に入る。 Debian ユーザなら、libmail-spf-query-perl をインストールする。
12 Debian ユーザ: 2004 年 7 月 14 日の時点では、 exim4-daemon-heavy パッケージに入っている Exiscan-ACL の版にはまだ
SPF 対応がない。 しばらくの間は、ほかの SPF の実装を使ってもいいだろう — libmail-spf-query-perl をインストールする。
47
Mail::SPF::Query パッケージには、デーモン (spfd) がついてくる。 これは UNIX ド メインソケット
で要求を listen する。 残念ながら、このデーモンを自動的に開始させる 「 init 」 スクリプトはついてこな
い。 そこで以下の例では、SPF 要求をするのにスタンド アロンの spfquery ユーティリティを使う。
上のように、以下のものを、[acl rcpt to] [32] のどのグレーリスト法の検査よりも前、 最後の accept 文
より前に挿入する:
# "spfquery" を使ってこの特定の送信者/ホストの SPF 状況を得る.
# このコマンドが返すコードが 1 なら , これは認証された送信者である.
#
deny
message
= [SPF] $sender_host_address is not allowed to send mail \
from $sender_address_domain.
log_message = SPF check failed.
set acl_m9 = -ipv4=$sender_host_address \
set acl_m9
-sender=$sender_address \
-helo=$sender_helo_name
= ${run{/usr/bin/spfquery $acl_m9}}
condition
= ${if eq {$runrc}{1}{true}{false}}
A.8
MIME とファイル型の検査を追加する
ここでの検査は、Tom Kistner の Exiscan-ACL パッチにある仕様に依存している — 詳細は [必須事項]
[29] を見てほしい。
Exiscan-ACL には、MIME のデコードとファイル名接尾辞の検査 (または、Windows 界の誤用では「ファ
イル拡張子」 の検査) への対応が含まれる。 この検査だけでも Windows のウィルスのほとんどを阻止で
きる - しかし 、 .ZIP 書庫で伝達されるものや、 Outlook/MSIE の HTML レンダ リングの脆弱性を突く
ものは阻止できない - [ウィルス検出ソフトウェア] [21] についての議論を見てほしい。
これらの検査は、[acl data] [36] の中で 最後の accept 文の前に来なければならない:
# 重大な MIME エラーがあるメッセージは拒否する.
#
deny
message
demime
condition
= Serious MIME defect detected ($demime_reason)
= *
= ${if >{$demime_errorlevel}{2}{1}{0}}
# MIME コンテナを解き、ワームが使うファイル拡張子は拒否する.
# これは demime 条件をもう一度呼び出すが 、キャッシュした結果が返る.
# 拡張子の一覧は完全なものではないことに注意.
#
deny
message
demime
= We do not accept ".$found_extension" attachments here.
= bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url
上の例では、demime 条件が 2 度呼び出されることに気づいただろう。 しかし 、結果はキャッシュされる
ので、実際にはメッセージが 2 度処理されることはない。
48
ウィルス対策ソフト ウェアを追加する
A.9
Exiscan-ACL は 、さまざ まに異なるウィルス検出ソフトウェアと直接結合できるし 、 他の検出ソフト
ウェアでも cmdline バックエンド を通じてコマンド ラインから実行できる。
この仕様を使うには、 Exim 設定ファイルの首節に、 使うウィルス検出ソフトウェアの種類をその検出
ソフトウェアに渡したいオプションとともに 指定しなければならない. 基本の構文は :
av_scanner = 検出ソフトウェアの種類:オプション 1:オプション 2:...
例えば :
av_scanner = sophie:/var/run/sophie
av_scanner = kavdaemon:/opt/AVP/AvpCtl
av_scanner = clamd:127.0.0.1 1234
av_scanner = clamd:/opt/clamd/socket
av_scanner = cmdline:/path/to/sweep -all -rec -archive %s:found:’(.+)’
...
次に、DATA ACL で malware 条件を使って実際の検出を実施するとよいだろう:
deny
message
demime
malware
= This message contains a virus ($malware_name)
= *
= */defer_ok
exiscan-acl-spec.txt ファイル [訳注: Exim 4.50 版では spec.txt の 40 節] に、 使用法についての情
報がすべてある。
A.10
SpamAssassin を追加する
Exim では、SMTP の時点で SpamAssassin を実行する方法が主に 2 つある:
• Exiscan-ACL が提供する spam 条件によって。 これが 、ここで説明する機構である。
a merlins.org>) が書いた別のユーティリ
• SA-Exim によって。 これは 、 Marc Merlins ( <marc°
ティで 、 Exim で SpamAssassin を SMTP の時点で実行するためのものである。 このプログラム
は Exim の local scan() インタフェースを通じて動作する。つまり、Exim のソースコードに直接
パッチを当てるか、 Marc による dlopen() プラグ インを介して動作させる (なお、これは Debian
の exim4-daemon-light パッケージや exim4-daemon-heavy パッケージには入っている)。
SA-Exim はまた、ほかの仕様も提供する。つまり、 グレーリスト 法 と タール坑法 である。しかし
ながら、 これらの仕様は 2 つともメッセージデータを受け取った後に検出を行なうので、 SMTP ト
ランザクションの初期に行なう場合ほどには有用でないだろう。
SA-Exim は、次の場所で見つかる: http://marc.merlins.org/linux/exim/sa.html。
A.10.1
Exiscan から SpamAssassin を呼び出す
Exiscan-ACL の「 spam 」条件では、 メッセージを SpamAssassin か Brightmail のいずれかに渡し 、 メッ
セージにゴ ミの徴候があれば文を実行する。 これは既定では、 localhost で実行している SpamAssassin
デーモン (spamd) に接続する。 ホストとポートは、Exim 設定ファイルの首節に spamd address 設定を
追加すれば変更できる。 さらなる情報は 、パッチに入っている exiscan-acl-spec.txt ファイル [訳注:
Exim 4.50 版では spec.txt の 40 節] を見てほしい。
49
この実装では、スパムに選別されたメッセージを拒否している。 しかし 、このようなメッセージの写し
を、少なくともしばらくの間は、 別のメールフォルダに保存しておくとよい。 これは、 偽陽性 [76] がな
いかをユーザがときどき調べられるようにするためだ。
Exim には、受け付けたメッセージに適用できる制御子がある。 freeze といったものだ。 Exiscan-ACL
パッチでは、もうひとつ制御子が増える。 fakereject だ。 これは、以下のような SMTP 応答をさせる:
550-FAKEREJECT id= メッセージ ID
550-Your message has been rejected but is being kept for evaluation.
550 If it was a legit message, it may still be delivered to the target recipient(s).
以下の設定の断片を [acl data] [36] の中の最後の accept 文より前に挿入すれば 、この仕様を採り入れら
れる:
# SpamAssassin を呼び出して, $spam_score と $spam_report を得る.
# 選別結果に応じて, $acl_m9 に "ham" か "spam" をセットする.
#
# メッセージが spam に選別されたら , 拒否したふりをする.
#
warn
set acl_m9
spam
= ham
= mail
set acl_m9
control
logwrite
= spam
= fakereject
= :reject: Rejected spam (score $spam_score): $spam_report
# メッセージに適切な X-Spam-Status: ヘッダを追加する.
#
warn
message
= X-Spam-Status: \
${if eq {$acl_m9}{spam}{Yes}{No}} (score $spam_score)\
${if def:spam_report {: $spam_report}}
logwrite
= :main: Classified as $acl_m9 (score $spam_score)
この例では、はじめ $acl m9 を 「 ham 」 にセットしてある。SpamAssassin を mail ユーザで呼び出す。
メッセージがスパムに選別されたら $acl m9 に 「 spam 」 をセットし 、 上記の FAKEREJECT 応答を発行す
る。 最後に、X-Spam-Status: ヘッダをメッセージに追加する。 これは何かというと、 メール配送エー
ジェント [79] や受信者のメール利用者エージェント [79] がこのヘッダを使って 不要メールを別のフォルダ
へ移動できるようにするためのものだ。
A.10.2
SpamAssassin の設定
既定では、SpamAssassin は詳細な表形式で報告を出す。 これはメッセージの本体に入れたり添付した
りするのにはかなり向いている。 ここでは、報告は上の例の X-Spam-Status: ヘッダに向くような簡潔な
ものであってほしい。このようにするには、 サイト独自の設定ファイル (/etc/spamassassin/local.cf 、
/etc/mail/spamassassin/local.cf など ) に、つぎの断片を追加する:
### 報告の雛型
clear_report_template
report "_TESTSSCORES(, )_"
50
また、Bayes 式得点づけの仕様があって、 既定では有効になっている。これは通常は無効にしたい。な
ぜなら、 これにはユーザそれぞれに特化した学習が必要で、 システム全体の SMTP の時点での排除には
向かないからだ :
### Bayes 式得点づけを無効にする
use_bayes 0
以上の変更が効くようにするには、 SpamAssassin デーモン (spamd) を再起動しなければならない。
A.10.3
ユーザごとの設定とデータ
SpamAssassin で個人的な設定 (スパム判定の閾値、受け入れる言語や文字集合、 送信者のホワイトリ
ストやブラックリストなど ) を指定したいというユーザも、若干はいるだろう。 また、SpamAssassin 組み
込みの Bayes 式得点づけを わざわざ 使いたいというユーザもいるかもしれない (私には理由がわからない
が 13 )。
この文書の前のほうの[ユーザごとの設定とデータ] [26] の節で述べたように、 こうなるようにする方法は
ある。 外部から来るメールの配送ごとに、受信者の数を 1 件に限るのだ。 発信者が発行する RCPT TO:
コマンド のうち最初のものだけを受け付け、 以降のものは 451 SMTP 応答を使って延期する。 グレーリ
スト法と同じく、 送り手が正しく動作する MTA ならばこの応答の解釈のしかたはわかるから、 後で再試
行してくる。
A.10.3.1
Exim が配送ごとに一つの受信者しか受け付けないようにする
[acl rcpt to] [64] の、受信者アドレスの確認の後、 リモートホストからローカルユーザの認証されてい
ない配送に関する文の前 (つまり、どのグレーリスト検査、エンヴェロープシグネチャ検査、 など よりも
前) に、以下の文を挿入する:
# 外部から来るメッセージごとの受信者の数を 1 件に限って, ユーザごとの設定と
# データ (例えば SpamAssassin のための) に対応する.
#
# 注意: 自分のサイトの複数のユーザに送られるメールは , 受信者ごとに 30 分ま
たはそれ以上遅れていく. これは , 内部と外部の関係者にまたがるよう
#
#
なやりとりのペースを著しく遅める.
#
defer
message
condition
A.10.3.2
= We only accept one recipient at a time - please try later.
= $recipients_count
SpamAssassin に受信者のユーザ名を渡す
[acl data] [69] で、 前節で追加した spam 条件を変更して、 受信者アドレスのローカル部で決まるユー
ザ名を SpamAssassin に渡すようにする。
# SpamAssassin を呼び出して, $spam_score と $spam_report を得る.
# 選別結果に応じて, $acl_m9 に "ham" か "spam" をセットする.
#
# 受信者アドレスが示すユーザ名を渡す, つまり, どの ’=’ 文字や ’@’
13 Bayes 式学習が各々のユーザに特化したものになるのは確かだが 、 SpamAssassin の Bayes 式選別機能は (これは私の意見だ
が ) どんな場合でもそれほど有能ではないことに注意しなければならない。 スパム送信者がでたらめな辞書単語や文章をメールの中に
(例えば HTML メッセージのメタデータに ) 入れ込んでこういうシステムを打ち破るテクニックを学んでしまっている場合は、 特に
そうなるようだ。
51
# 文字よりも前の部分を , 小文字に変換して渡す. 複数の受信者が現れて
# はいけない. さっき, 配送を一度に一受信者に限ったのだから .
#
# メッセージがスパムに選別されたら , 拒否したふりをする.
#
warn
set acl_m9
spam
= ham
= ${lc:${extract{1}{=@}{$recipients}{$value}{mail}}}
set acl_m9
control
logwrite
= spam
= fakereject
= :reject: Rejected spam (score $spam_score): $spam_report
Exim の ${local part:...} 関数を使ってユーザ名を得るのではなく、 すべての 「 @ 」 文字や 「 = 」
文字よりも前の部分を展開するようにしていることに注意。 理由は、後のエンヴェロープシグネチャ方式
でこの 「 = 」 文字を利用するからだ。
A.10.3.3
SpamAssassin でユーザごとの設定を有効にする
では、再び SpamAssassin を見てみよう。最初に、 サイト全体の設定ファイルで use bayes 0 を削除す
ることにしたかもしれないが、 今はどんな場合でも、 この設定を上書きするかど うかを各々のユーザが自
分で決めることができる。
システムのメールボックスが ホームデ ィレクトリのあるローカルの UNIX アカウントに直接対応して
いるのなら 、 もうやることはない。既定では 、 SpamAssassin デーモン (spamd) は 渡したユーザ名で
setuid() を実施し 、 ユーザのデータや設定をそのユーザのホームデ ィレクトリの中に格納する。
そうでない場合 (例えば 、メールアカウントを Cyrus SASL などのサーバで管理している場合) 、 各ユー
ザの設定とデータファイルの場所の見つけかたを SpamAssassin に教えてやらなければならない。 また、
存在しないユーザに対しては spamd が setuid() しようとするのではなく、 特定のローカルユーザとし
て実行するようにする必要がある。
このようにするには、 spamd の起動の際に次のようなオプションを指定する:
• Debian システムでは、 /etc/default/spamassassin の OPTIONS= の設定を変更する。
• RedHat システムでは、 /etc/sysconfig/spamassassin の SPAMDOPTIONS= 設定を変更する。
• 他のシステムでも、推して知るべし 、だ。
必要なオプションは :
• -u ユーザ名 — spamd を実行するユーザを指定する (例えば mail)
• -x — ユーザのホームデ ィレクトリの設定ファイルを無効にする。
• --virtual-config-dir=/var/lib/spamassassin/%u — ユーザごとの設定とデータを格納する場
所を指定する。 「 %u 」 は呼び出したユーザ名に置き換わる。 spamd は、 このデ ィレクトリを作
成したり変更したりできなければならない:
# mkdir /var/lib/spamassassin
# chown -R mail:mail /var/lib/spamassassin
言うまでもなく、以上のような変更をした後は、 spamd を再起動する必要がある。
52
A.11
エンヴェロープ送信者のシグネチャを追加する
ここでは、外部へ行くメールの[エンヴェロープ送信者のシグネチャ] [22] を実装し 、 外部からの 「バウ
ンス」 (つまりエンヴェロープ送信者のないメール ) を受け付ける前にこのシグネチャを検査する。
自ホストから外部へ行くメールのエンヴェロープ送信者アドレスを、 以下のように変更する:
送信者=受信者=受信者の. ド メイン =ハッシュ@送信者の. ド メイン
ただし 、この方式は好まし くない結果を生むことがあるので (例えば メーリングリストサーバの場合) 、
ユーザごとに選択できるようにする。 送信者のホームディレクトリに 「 .return-path-sign 」 という名前の
ファイルがあるときだけ、 かつ送り先のド メインがそのファイルの内容と一致するときだけ、 外部へ行く
メールのエンヴェロープ送信者アドレスにサインする。 ファイルが存在しているが空ならば 、どのド メイ
ンとも一致することにする。
同様に、このファイルが受信者のホームディレクトリにあるときは、 外部からの 「バウンス」 メッセー
ジ (つまり エンヴェロープ送信者のないメッセージ ) にだけ受信者アドレスのサインが要る。 ユーザは特
定のホワイトリストを使って特定のホストがこの検査をうけないようにできる。 [転送されてきたメールを
通す] [58] で述べるようにすればできる。
なお、この方式には ACL に加えてルータやトランスポートの変更も伴うので、 後の[できあがった ACL]
[60] には含めていない。 これらの節に関する説明のとおりにやるのなら、 ここで述べる ACL 節も追加し
なければならない。
A.11.1
送信者アドレスに署名するためのト ランスポート を作成する
まず、Exim のト ランスポート をひとつ作成する。 これは、リモート配送でエンヴェロープ送信者にサイ
ンするのに使う:
remote_smtp_signed:
debug_print
= "T: remote_smtp_signed for $local_part@$domain"
driver
= smtp
max_rcpt
return_path
= 1
= $sender_address_local_part=$local_part=$domain=\
${hash_8:${hmac{md5}{SECRET}{${lc:\
$sender_address_local_part=$local_part=$domain}}}}\
@$sender_address_domain
送信者アドレスの 「ローカル部」 は、つぎの部品を等号 (「 = 」) で区切ったものになる:
• 送信者のユーザ名、つまり元のローカル部と、
• 受信者アドレスのローカル部と、
• 受信者アドレスのド メイン部と、
• この送信者/受信者の組合せに特有の文字列。次のもので生成する:
– 先に書き換えた送信者アドレスの 3 つの部分を、Exim の ${hmac{md5}...} 関数を使って、 首節
で定義した SECRET とともに暗号化し 14 、
14 これはこりすぎだと思う人もいるかもしれないし 、 見かけの上では私も賛成だ。この文書の前の版では 、 シグネチャの最後
の部分を生成するのに ${hash 8:SECRET=....} を使っていた。 しかしこれでは 、いくらか Exim の ${hash...} 関数を分析し 、
別々の受信者に送られた外部へ行くメールのサンプルを手に入れれば 、 シグネチャを偽造することが技術的には可能になり得る。
a
Matthew Byng-Maddic <mbm°colondot.net>
の注: 書いた文書は、多くの人々に複写されて送られることがあり得る。 そうな
ると、 Kerckhoff の原則 [訳注: 暗号化に使用するアルゴリズムは 解読を試みる者にとっては既知のものであると仮定しなければな
らない、 という原則] が適用されることになり、守秘性は鍵のみに依存してしまう。 鍵が復元できれば 、 スパム送信者は そのド メ
インからの有効な返送経路にメールを送り込むことができるようになる。 [...] 最初から強力なものにしておくのがいいと思う。
53
– Exim の ${hash...} 関数を使って、 結果を小文字 8 文字のハッシュにする。
「 スマートホスト 」 への配送を認証する必要があるときは、 ここで適切な hosts try auth 行も追加する
(すでにあるスマートホストのトランスポートから取ってくる)。
A.11.2
リモート 配送のためのルータを新たに作成する
現在外部へ行くメールを扱っているルータ (複数あるかもしれない) の前に、新たにルータを追加する。
このルータは、リモート配送には上記のトランスポートを使うが 、 送信者のホームディレクトリにファイ
ル 「 .return-path-sign 」 が存在し 、 かつ、受信者のド メインがこのファイルの内容に一致するときだけで
ある。 例えば メールをインターネットを通じて最終目的地に送っているのなら :
# 送信者のホームデ ィレクトリにファイル ".return-path-sign" があり, さらに
# リモートのド メインがそのファイルの内容と一致すれば , エンヴェロープ送信者のアド
# レス (返送経路) にリモートのド メイン向けのサインをする. ファイルが存在している
# が空なら , 必ずエンヴェロープ送信者にサインする.
#
dnslookup_signed:
debug_print
= "R: dnslookup_signed for $local_part@$domain"
driver
transport
senders
domains
= dnslookup
= remote_smtp_signed
= ! : *
= ! +local_domains : !+relay_to_domains : \
${if exists {/home/$sender_address_local_part/.return-path-sign}\
{/home/$sender_address_local_part/.return-path-sign}\
{!*}}
no_more
あるいは、スマートホストを使っているのなら :
# 送信者のホームデ ィレクトリにファイル ".return-path-sign" があり, さらに
# リモートのド メインがそのファイルの内容と一致すれば , エンヴェロープ送信者のアド
# レス (返送経路) にリモートのド メインへの配送のためのサインをする. ファイルが存
# 在しているが空なら , 必ずエンヴェロープ送信者にサインする.
#
smarthost_signed:
debug_print
= "R: smarthost_signed for $local_part@$domain"
driver
transport
= manualroute
= remote_smtp_signed
senders
= ! : *
route_list
= * スマートホストのアドレス
host_find_failed = defer
domains
= ! +local_domains : !+relay_to_domains : \
${if exists {/home/$sender_address_local_part/.return-path-sign}\
{/home/$sender_address_local_part/.return-path-sign}\
{!*}}
no_more
その他、適当なオプションを追加する (例えば same domain copy routing = yes)。 たぶんすでに存在
するルータの後にある。
54
エンヴェロープ送信者アドレスのないメールには、このルータを使わないことに注意 — これらのものは
改竄しない15 !
A.11.3
ローカル配送のための転向ルータを新たに作成する
次に、上の形式に一致する外部からの受信者アドレスを、 最初の等号 (「 = 」) より前の部分で特定され
るメールボックスに配送するよう、 Exim に教える必要がある。 この目的のためには 、 設定ファイルの
routers 節の最初のほう — ローカル配送 (システム エイリアス ルータのような ) に関するどのルータよ
りも前 — に、redirect [転向] ルータを挿入するといい:
hashed_local:
debug_print
driver
= "R: hashed_local for $local_part@$domain"
= redirect
domains
= +local_domains
local_part_suffix = =*
data
= $local_part@$domain
等号を含む受信者アドレスを書き換えて、ローカル部の等号に続く部分を取り去る。 それから、再び全
てのルータで処理する。
A.11.4
ACL シグネチャの検査
この方式の最後の部分では、有効な受信者アドレスに配送するメールはシグネチャが 必ず受け付けられ
るものでなければならないこと、 いっぽ うエンヴェロープ送信者が空のメッセージは 受信者がこの方式に
自分で加入していれば拒否しなければならないことを、 Exim に教える。 ど ちらの場合にも、グレーリス
ト法を行なってはならない。
以下の断片は、[acl rcpt to] [64] で、どの SPF 検査やグレーリスト法よりも前、 最後の accept 文より
も前に置かなければならない:
# 受信者アドレスに自分自身のシグネチャが入っていれば , 受け付ける.
# このことは , 以前にここから送ったこれが メッセージへの応答 (DSN,
# 送信者呼出し確認法...) であるという意味である.
#
accept
domains
condition
= +local_domains
= ${if and {{match{${lc:$local_part}}{^(.*)=(.*)}}\
{eq{${hash_8:${hmac{md5}{SECRET}{$1}}}}{$2}}}\
{true}{false}}
# そうでないとき, メッセージがバウンスとみなされる (つまりエンヴェロープ送信者
# がない) のに受け手がエンヴェロープ送信者のシグネチャを使って検査すると決めて
# いるのなら , 拒否する.
#
deny
message
= This adress does not match a valid, signed \
return path from here.\n\
You are responding to a forged sender address.
log_message = bogus bounce.
15 上記の例では、 senders 条件が実際には重複している。 ファイル /home//.return-path-sign は存在しないかもしれないた
めだ。 しかし 、明確化のために強いてこの条件を作った。
55
senders
domains
set acl_m9
= : postmaster@*
= +local_domains
= /home/${extract{1}{=}{${lc:$local_part}}}/.return-path-sign
condition
= ${if exists {$acl_m9}{true}}
メッセージのヘッダのアドレス (自ホストから外部へ行くメールの From: にあるもののような ) に対し
て呼出し確認法を実施しているホストへメールを送るときには、問題がある。 deny [拒絶] 文が 、 このよ
うな確認の試みに対して否定的な応答をしてしまう。
このため、最後の deny 文を warn 文に変更し 、拒否メッセージを $acl m0 に保管しておき、 実際の拒
否は DATA コマンド の後で実施する、というようにしたほうがよいかもしれない。 これは、先に説明し
たのと似たやりかただ :
# そうでないとき, メッセージがバウンスとみなされる (つまりエンヴェロープ送信者
# がない) のに受け手がエンヴェロープ送信者のシグネチャを使って検査すると決めて
# いるのなら , 拒否メッセージを $acl_m0 に , 記録メッセージを $acl_m1 に入れる.
# これは , 後でメールを拒否するのに使う. しばらくの間, これらの存在によって, 送
# 信者を足止めしておかなければならないことを示す.
#
warn
senders
domains
= : postmaster@*
= +local_domains
set acl_m9
condition
= /home/${extract{1}{=}{${lc:$local_part}}}/.return-path-sign
= ${if exists {$acl_m9}{true}}
set acl_m0
= The recipient address <$local_part@$domain> does not \
match a valid, signed return path from here.\n\
You are responding to a forged sender address.
set acl_m1
= bogus bounce for <$local_part@$domain>.
なお、受信者は、 エンヴェロープ送信者のシグネチャを外部へ行くメールで使うことにしているときで
も、 特定のホストを外部から来るメールにこのシグネチャをつけることから除きたがるかもしれない。 こ
れは、特殊なメーリングリストサーバで必要になるかもしれない。 詳しくは、[エンヴェロープ送信者のシ
グネチャ] [22] の議論を見てほしい。
A.12
実在するユーザへのバウンスだけを受け付ける
[実在するユーザへのバウンスだけを受け付ける] [24] で述べたように、 エンヴェロープ送信者のシグネ
チャ検査にはまだ抜け穴がある。システムユーザや (postmaster のような ) エイリアスにいんちきな配送
状況通知 [78] が届くのを防がなければならない。 ここでは、 外部へ行くメールを実際に送信するユーザへ
のバウンスだけを受け付けるようにするための方法を、 2 通り説明する。
A.12.1
受信者のメールボックスの検査
最初の方式は、 [acl rcpt to] [64] ACL で実施するものだ。 この方法では、 受信者アドレスがローカル
のメールボックスに対応づけられるかど うかを検査する:
# 送信者アドレスが与えられなければ , メールボックスのないユーザ (つまり postmaster,
# webmaster...) へのメールを拒絶する. こういったユーザは外部へ行くメールを送ること
# はないので , 返送されてくるメールを受け取るはずがない.
#
deny
56
message
= This address never sends outgoing mail. \
You are responding to a forged sender address.
log_message = bogus bounce for system user <$local_part@$domain>
senders
= : postmaster@*
domains
= +local_domains
!mailbox check
困ったことに、mailbox check の箇所を実際にど う実施するかは、 メールをど う配送しているかに依存
してしまう (なおその前に、受信者アドレスの最初の 「 = 」 記号より前の部分を展開して、 エンヴェロー
プ送信者のシグネチャに役立つようにしておく):
• メールボックスが自サーバのローカルのユーザアカウントに対応しているのなら、 受信者名がシス
テムの 「通常の」 ユーザにあたるユーザ ID に対応している (例えば 500 から 60000 の範囲にある)
かど うかを検査すればいい:
set acl_m9 = ${extract{1}{=}{${lc:$local_part}}}
set acl_m9 = ${extract{2}{:}{${lookup passwd {$acl_m9}{$value}}}{0}}
condition
= ${if and {{>={$acl_m9}{500}} {<${acl_m9}{60000}}} {true}}
• メールを Cyrus16 IMAP スイートへ配送しているのなら、それに入っている mbpath コマンド ライ
ン ユーティリティを使って メールボックスの存在を検査することができる。 Exim ユーザが メール
ボックスを検査できる権限をもつようにしたほうがいいだろう (例えば 、このユーザを cyrus グルー
プに入れる: # adduser exim4 cyrus)。
set acl_m9 = ${extract{1}{=}{${lc:$local_part}}}
condition = ${run {/usr/sbin/mbpath -q -s user.$acl_m9} {true}}
• メールをすべてリモートの計算機へ転送してそこで配送しているのなら、 [受信者呼出し確認法] [14]
を実施して、 その計算機が メールを受け付けるかど うか判断する必要があるかもしれない。 呼出
し 17 の際は、 元のエンヴェロープ送信者を手付かずにしておく必要がある:
verify = recipient/callout=use_sender
このメールボックス検査は、 メールを内部的に配送している場合にはルータで実施する処理の一部と重複
するし 、 サイトのメール配送機構によっても違ってくるので、 完全主義者の皆さんにはぶざまに見えるか
もしれない。 そこで、別の方法も紹介しておこう。
A.12.2
エイリアスルータでの空送信者の検査
たぶん 、 system aliases というような名前のルータがあるだろう。これは メールを postmaster や
mailer-demon のようなユーザに転向させる。 一般に、こういうエイリアスは外部へ行くメールの送信者
アドレスには使わない。 だから、 外部から来た配送状況通知 [78] がこのルータを通らないようにできる。
ルータに以下の条件を追加する:
!senders = : postmaster@*
エイリアスルータは、たとえばこんなふうになる:
16 http://asg.web.cmu.edu/cyrus/
17 [訳注]
callout。
57
system_aliases:
driver
domains
= redirect
= +local_domains
!senders
allow_fail
allow_defer
= : postmaster@*
data
user
= ${lookup{$local_part}lsearch{/etc/aliases}}
= mail
group
= mail
file_transport = address_file
pipe_transport = address_pipe
これで、 システムエイリアスの一部へ行くバウンスは阻止できるが、 他のエイリアスでは実在するシス
テムユーザ (「 root 」、 「 daemon 」 などのような ) が隠れてしまう。 accept driver を通じてローカルで
メールを配送し 、 check local user で受信者アドレスを確認しているときは、 こういったシステムアカ
ウントへはメールを直接ルーティングしたいだろう。
この問題を直すために 、ローカルのメールを扱うルータ (例えば local user) にさらに条件を追加して、
受信者が存在するだけでなく 「普通の」 ユーザでもあるようにしたい。 例えば 、上で述べたのと同じよ
うに、ユーザ ID が 500 から 60000 の範囲にあるかど うかを検査する:
condition
= ${if and {{>={$local_user_uid}{500}}\
{<{$local_user_uid}{60000}}}\
{true}}
ローカル配送のルータは、たとえばこんなふうになる:
local_user:
driver
= accept
domains
= +local_domains
check_local_user
condition
= ${if and {{>={$local_user_uid}{500}}\
{<{$local_user_uid}{60000}}}\
{true}}
transport
= transport
この方式を実装するときは、 システムユーザ宛のいんちきバウンスメールへのサーバからの拒否応答が
受信者が不明のとき (ここでは 550 Unknown User) と同じになるよう気をつけよう。
A.13
転送されてきたメールを通す
これで SMTP トランザクションでの検査はすべて追加したが、 ここでひとつ気づいたことがある。 メー
リングリストや他のサイトのメールアカウントのような信頼できる出所 から転送されてきたメールを拒否
しているために、 間接的に巻き添えスパムを発生させているのだ (詳しくは、[転送されてきたメール ] [25]
についての議論を見てほしい)。 こういうホストはホワイトリストに入れて、SMTP での拒否 — 少なくと
も、スパムやウィルスの排除によって起こる拒否だけでも — から除外する必要がある
以下の例では、RCPT TO: コマンド ごとに応答する際に、 2 つのファイルを参照することにする:
• サイト全体のホワイトリスト /etc/mail/whitelist-hosts。 これには、バックアップ MX ホスト
と、 その他ホワイトリストに入れる送信者?を記述する。それと、
58
• ユーザ固有のリスト /home/ユーザ/.forwarders。 これには、それぞれのユーザが転送されてきた
メールを受け取るホスト (例えばメーリングリストサーバ、よそのアカウントの送出用メールサーバ...)
を記述する。
メールユーザにローカルのユーザアカウントもホームディレクトリもなければ 、 ファイルのパスや検索機
構をなにかもっと自分のシステムにあうもの (例えばデータベース検索や LDAP 問合せ) に変えるとよい
かもしれない。
送信者ホストがこれらのホワイトリストのどれかに見つかったら、 先の[選択的な遅延] [38] の節で説明
したように、 $acl m0 に 「 accept 」 という語を保存し 、 $acl m1 の内容を消去する。 これによって、引
き続く文でメールを拒否してはいけないことを示す。
[acl rcpt to] [64] で、受信者アドレスの確認の後、 ただし リモートホストからローカルユーザへの認証
されていない配送に関する accept 文より前に (つまりグレーリストの検査、エンヴェロープシグネチャの
検査、などより前に ) 、 以下の文を挿入する:
# 送信側のホストが全体のホワイトリストファイルの内容と一致すれば , 受け
# 入れる. 一時的に $acl_m9 をセットして, このファイルを指すようにす
# る. ホストが見つかったら , $acl_m0 のフラグをセットして $acl_m1
# を消し , このメールは今後拒否してはいけないということを示す.
#
accept
set acl_m9
= /etc/mail/whitelist-hosts
hosts
set acl_m0
= ${if exists {$acl_m9}{$acl_m9}}
= accept
set acl_m1
=
# 送信側のホストが受信者のホームデ ィレクトリの ".forwarders" ファイルの内容
# と一致すれば , 受け入れる. 一時的に $acl_m9 をセットして, このファイルを指
# すようにする. ホストが見つかったら , $acl_m0 のフラグをセットして $acl_m1
# を消し , このメールは今後拒否してはいけないということを示す.
#
accept
domains
= +local_domains
set acl_m9
hosts
set acl_m0
= /home/${extract{1}{=}{${lc:$local_part}}}/.forwarders
= ${if exists {$acl_m9}{$acl_m9}}
= accept
set acl_m1
=
[acl data] [69] ACL にあるさまざ まな文では、 $acl m0 の内容を検査して、上のようにセットしてあれ
ば 、 メールを拒否しないようにする。例えば 、 RFC2822 ヘッダがないメールがホワイトリストにあるホ
ストから来たら、 拒否しないようにする:
deny
message
= Your message does not conform to RFC2822 standard
log_message = missing header lines
!hosts
!senders
condition
= +relay_from_hosts
= : postmaster@*
= ${if !eq {$acl_m0}{accept}{true}}
condition
= ${if or {{!def:h_Message-ID:}\
{!def:h_Date:}\
{!def:h_Subject:}} {true}{false}}
59
書き換えた検査は、次節の[できあがった ACL] [60] に入れてある。
A.14
できあがった ACL
よーし 、起きる時間だよ。ずいぶん長い読み物になってしまったが 、とうとう出来上がりだ !
以下の ACL には、この実装で説明してきた検査がすべて入っている。 しかし 、コメントアウトしてあ
るものもいくつかある。次のような理由からだ :
• グレーリスト法。これには、 追加のソフトウェアのインストールか、 Exim の設定ファイルへのかな
り複雑な設定や ACL の追加が要る。 だが 、これは強くお勧めする。
• ウィルス検出。 スパムの同定に使われている SpamAssassin のような、 だれでもがほぼ普遍的に使っ
ている検出ソフトウェアがない。 いっぼ う、Exiscan-ACL についてくる文書を見れば簡単に実施で
きる。
• SpamAssassin のユーザごとの設定。 これは、どれくらい多くのひとにとって受け入れられるかとの
トレード オフになる。 最初の受信者以外は次第にメールが遅れていくためだ。
• エンヴェロープ送信者のシグネチャ。 例えば 、ローミングをするユーザには悪影響がある。 また、
ACL だけでなくルータとトランスポートの設定も必要になってくる。 詳細は上節を見てほしい。
• 実ユーザ宛のバウンスのみの受け入れ。 これをする方法はいくつかあり、ユーザが実在かど うか決定
する方法は メールの配送のしかたによって違ってくる。
問題になるのはこれだけだ。さて、待ちに待った最終結果を披露しよう。
A.14.1
acl connect
# このアクセス制御リストは , 外部からの接続の開始の際に使う.
# 検査は順に実行され , 接続を受け付けるか拒否するまで続く.
acl_connect:
# 以降の遅延の継続期間を計算するために , 現在のタイムスタンプを記録する
warn
set acl_m2
= $tod_epoch
# ローカルの SMTP 経由 (つまり TCP/IP 経由ではない) で受信したメールを受け入れる.
# 空の送信側ホスト項目をテストすることでこれを行なう.
# また, メールをリレーするためのホストから受信したメールも受け入れる.
accept
hosts
= : +relay_from_hosts
# 接続してきているホストが DNSbl のどれかに登録されていれば ,
# $acl_c1 に警告メッセージを用意する. このメッセージは , 後でメールヘッダに
# 追加する. 送信者を足止めしなければいけないことを, しばらくの間これの存在で
# 示す.
#
60
warn
!hosts
dnslists
= ${if exists {/etc/mail/whitelist-hosts} \
{/etc/mail/whitelist-hosts}}
= list.dsbl.org : \
dnsbl.sorbs.net : \
dnsbl.njabl.org : \
bl.spamcop.net : \
dsn.rfc-ignorant.org : \
sbl-xbl.spamhaus.org : \
l1.spews.dnsbl.sorbs.net
set acl_c1
= X-DNSbl-Warning: \
$sender_host_address is listed in $dnslist_domain\
${if def:dnslist_text { ($dnslist_text)}}
# 同様に , 送信者のホストの DNS 逆引きが失敗したら (つまり, DNS 逆引きエントリ
# がないか , ホスト名の正引きの結果が元の IP アドレスに一致しなければ ), $acl_c1
# に警告メッセージを生成する. このメッセージは , 後でメールヘッダに追加する.
warn
condition
= ${if !def:acl_c1 {true}{false}}
!verify
set acl_m9
= reverse_host_lookup
= Reverse DNS lookup failed for host $sender_host_address
set acl_c1
= X-DNS-Warning: $acl_m9
# 送信者を受け付ける. ただし , 前に $acl_c1 にメッセージを生成しているのなら ,
# 20 秒が経過するまで送信者を足止めする.
accept
set acl_m2
delay
A.14.2
= ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
= ${if >{$acl_m2}{0}{$acl_m2}{0}}s
acl helo
# このアクセス制御リストは , 外部から来る SMTP トランザクションの MAIL FROM:
# コマンドに使う. テストは順に実行され , 送信者アドレスが受け付けられるか拒否
# されるかすると , そこで終る.
acl_helo:
# 以降の遅延の継続期間を計算するために , 現在のタイムスタンプを記録する
warn
set acl_m2
= $tod_epoch
# ローカルの SMTP 経由 (つまり TCP/IP 経由ではない) で受信したメールを受け入れる.
# 空の送信側ホスト項目をテストすることでこれを行なう.
# また, メールをリレーするためのホストから受信したメールも受け入れる.
61
#
accept
hosts
= : +relay_from_hosts
# リモートホストが IP アドレスで挨拶したら , $acl_c0 に拒否メッセージを ,
# $acl_c1 に記録用メッセージを用意する. これらは後で "deny" 文の中で使う.
# しばらくの間, これらの存在で送信者を足止めしておかなければならないことを示す.
#
warn
condition
set acl_c0
set acl_c1
= ${if isip {$sender_helo_name}{true}{false}}
= Message was delivered by ratware
= remote host used IP address in HELO/EHLO greeting
# サーバ自身の名前のどれかで相手が挨拶したときも同様
#
warn
condition
= ${if match_domain{$sender_helo_name}\
{$primary_hostname:+local_domains:+relay_to_domains}\
{true}{false}}
set acl_c0
set acl_c1
= Message was delivered by ratware
= remote host used our name in HELO/EHLO greeting.
# HELO の確認が失敗したら , acl_c1 に警告メッセージを用意する.
# このメッセージは , 後でメールヘッダに追加する.
# 送信者を足止めしておかなければならないことを, しばらくの間これの存在で示す.
#
warn
condition
!verify
set acl_c1
= ${if !def:acl_c1 {true}{false}}
= helo
= X-HELO-Warning: Remote host $sender_host_address \
${if def:sender_host_name {($sender_host_name) }}\
incorrectly presented itself as $sender_helo_name
log_message = remote host presented unverifiable HELO/EHLO greeting.
# 接続を受け付ける. ただし , 前に $acl_c1 にメッセージを生成しているのなら ,
# 20 秒が経過するまで送信者を足止めする.
accept
set acl_m2
delay
A.14.3
= ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
= ${if >{$acl_m2}{0}{$acl_m2}{0}}s
acl mail from
# このアクセス制御リストは , 外部から来る SMTP トランザクションの MAIL FROM:
62
# コマンドに使う. テストは順に実行され , 送信者アドレスが受け付けられるか拒否
# されるかすると , そこで終る.
#
acl_mail_from:
# 以降の遅延の継続期間を計算するために , 現在のタイムスタンプを記録する
warn
set acl_m2
= $tod_epoch
# ローカルの SMTP 経由 (つまり TCP/IP 経由ではない) で受信したメールを受け入れる.
# 空の送信側ホスト項目をテストすることでこれを行なう.
# また, メールをリレーするためのホストから受信したメールも受け入れる.
#
# 送信者確認はここではしない. しばしば , クライアントが低能な MUA で ,
# こういったものは SMTP エラー応答にうまく対応できないためだ .
#
accept
hosts
= : +relay_from_hosts
# メッセージが認証された接続を通じて届いたら , どのホストからでも受け付ける.
# ここでも, こういったメッセージは普通は MUA からのものだ .
#
accept
authenticated = *
# ACL 変数 $acl_c0 と $acl_c1 がもしあれば , 拒否や警告のメッセージを含んでいる
# ので , この SMTP トランザクションでの配送の試みひとつひとつにこれを適用する.
# これらの変数をメッセージごとの $acl_m{0,1} 変数に代入し , $acl_m1 の警告メッ
# セージをメッセージヘッダに追加する (拒否の場合は , $acl_m1 には記録用メッセージ
# が入っていることになるが , かまわない. ヘッダを追加するはずのメッセージはど うせ
# 破棄するのだから ).
#
warn
set acl_m0
set acl_m1
= $acl_c0
= $acl_c1
message
= $acl_c1
# 送信者が HELO/EHLO 挨拶をまったくしなければ , $acl_m0 に拒否メッセージを ,
# $acl_m1 に記録メッセージを用意する. これらは後で "deny" 文で使う.
# 送信者を足止めしておかなければならないことを, しばらくの間これらの存在で示す.
#
warn
condition
set acl_m0
= ${if def:sender_helo_name {0}{1}}
= Message was delivered by ratware
63
set acl_m1
= remote host did not present HELO/EHLO greeting.
# 送信者アドレスが確認できなければ , $acl_m1 に警告メッセージを作成して,
# メールヘッダに追加する.
# 送信者を足止めしておかなければならないことを, しばらくの間これの存在で示す.
#
# "callout" [呼出し ] オプションを省くことにしてもよい.
特に , 外部へ行くメー
# ルをスマートホストを通じて送っているときは , これは有用な情報をなにも与えて
# くれない.
#
warn
condition
!verify
set acl_m1
メッセージ
= ${if !def:acl_m1 {true}{false}}
= sender/callout
= Invalid sender <$sender_address>
= X-Sender-Verify-Failed: $acl_m1
log_message = $acl_m1
# 送信者を受け付ける. ただし , 前に $acl_c1 にメッセージを生成しているのなら ,
# 20 秒が経過するまで送信者を足止めする.
accept
set acl_m2
delay
A.14.4
= ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
= ${if >{$acl_m2}{0}{$acl_m2}{0}}s
acl rcpt to
# このアクセス制御リストは , 外部からの SMTP メッセージの RCPT コマンドごと
# に使う. テストは順に実行され , 受信者アドレスが受け付けられるか拒否される
# かすると , そこで終る.
acl_rcpt_to:
# ローカルの SMTP 経由 (つまり TCP/IP 経由でない) で受け取ったメールを受
# け付ける. 空の送信側ホスト項目でこれをテストする.
# また, メールのリレーのためのホストからのメールも受け付ける.
#
# 受信者確認はここではしない. しばしば , クライアントが低能な MUA で ,
# こういったものは SMTP エラー応答にうまく対応できないためだ .
#
accept
hosts
= : +relay_from_hosts
# メッセージが認証された接続を通じて届いたら , どのホストからでも受け付ける.
# ここでも, こういったメッセージは普通は MUA からなので , 受信者確認はしない.
#
64
accept
authenticated = *
# ローカル部が @ や % や / や | や ! を含んでいれば拒絶.
# こういったものは , 本物のローカル部にはまず現れないが , リレー制限の抜け穴
# を探す輩がよく試すものだ .
#
# ド ットで始まるローカル部なら , これも拒絶. 空のコンポーネントは厳密には
# RFC 2822 違反だが , これはよくあるので Exim では受け入れる. しかし ,
# ド ットで始まっているものは , ローカル部がファイル名として使われる場合
# (例えば メーリングリストのために ) にトラブルを起こすかもしれない.
#
deny
local_parts = ^.*[@%!/|] : ^\\.
# 以前に $acl_m0 に拒絶する理由を入れてあれば拒絶. また, 送信者をさらに 20 秒
# 足止めする.
#
deny
message
= $acl_m0
log_message = $acl_m1
condition
delay
= ${if and {{def:acl_m0}{def:acl_m1}} {true}}
= 20s
# 受信者アドレスが我々の扱うド メインのものでなければ , 送信者を足止めしてから
# 拒否.
#
deny
message
!domains
= relay not permitted
= +local_domains : +relay_to_domains
delay
= 20s
# アドレスがローカルのド メインのものかリレーするド メインのものであるのに
# 無効なものなら , 足止めして拒否.
#
deny
message
!verify
delay
= unknown user
= recipient/callout=20s,defer_ok,use_sender
= ${if def:sender_address {1m}{0s}}
# エンヴェロープ送信者が空なのに受信者アドレスが複数あれば , 接続を切る.
# 真っ当な DSN は , 1 つより多くのアドレスに送ったりしない.
65
#
drop
message
= Legitimate bounces are never sent to more than one \
senders
condition
recipient.
= : postmaster@*
= $recipients_count
delay
= 5m
# -------------------------------------------------------------------# 外部から来るメッセージごとの受信者の数を 1 件に限って, ユーザごとの設定と
# データ (例えば SpamAssassin のための) に対応する.
#
# 注意: 自分のサイトの複数のユーザに送られるメールは , 受信者ごとに 30 分ま
#
たはそれ以上遅れていく. これは , 内部と外部の関係者にまたがるよう
#
なやりとりのペースを著しく遅める.
#
#defer
# message
= We only accept one recipient at a time - please try later.
# condition
= $recipients_count
# --------------------------------------------------------------------
# 送信側のホストが受信者のホームデ ィレクトリの ".forwarders" ファイルの内容
# と一致すれば , 受け入れる. 一時的に $acl_m9 をセットして, このファイルを指
# すようにする. ホストが見つかったら , $acl_m0 のフラグをセットして $acl_m1
# を消し , このメールは今後拒否してはいけないということを示す.
#
accept
domains
set acl_m9
= +local_domains
= /home/${extract{1}{=}{${lc:$local_part}}}/.forwarders
hosts
set acl_m0
= ${if exists {$acl_m9}{$acl_m9}}
= accept
set acl_m1
=
# 送信側のホストが全体のホワイトリストファイルの内容と一致すれば , 受け
# 入れる. 一時的に $acl_m9 をセットして, このファイルを指すようにす
# る. ホストが見つかったら , $acl_m0 のフラグをセットして $acl_m1
# を消し , このメールは今後拒否してはいけないということを示す.
#
accept
set acl_m9
hosts
set acl_m0
set acl_m1
= /etc/mail/whitelist-hosts
= ${if exists {$acl_m9}{$acl_m9}}
= accept
=
66
# -------------------------------------------------------------------# エンヴェロープ送信者のシグネチャの検査.
# これは既定ではコメントアウトしてある. なぜなら設定に ’transports’ 節と
# ’routers’ 節の追加が必要だからだ .
#
# 受信者アドレスに自分自身のシグネチャが入っていれば , 受け付ける.
# このことは , 以前にここから送ったこれが メッセージへの応答 (DSN,
# 送信者呼出し確認法...) であるという意味である.
#
#accept
# domains
= +local_domains
#
#
= ${if and {{match{${lc:$local_part}}{^(.*)=(.*)}}\
{eq{${hash_8:${hmac{md5}{SECRET}{$1}}}}{$2}}}\
condition
#
{true}{false}}
#
# そうでないとき, メッセージがバウンスとみなされる (つまりエンヴェロープ送信者
# がない) のに受け手がエンヴェロープ送信者のシグネチャを使って検査すると決めて
# いるのなら , 拒否する.
#
#deny
# message
#
#
= This address does not match a valid, signed \
return path from here.\n\
You are responding to a forged sender address.
#
#
#
log_message = bogus bounce.
senders
= : postmaster@*
domains
= +local_domains
#
#
set acl_m9
condition
= /home/${extract{1}{=}{${lc:$local_part}}}/.return-path-sign
= ${if exists {$acl_m9}{true}}
# --------------------------------------------------------------------
# -------------------------------------------------------------------# 送信者アドレスが与えられなければ , メールボックスのないユーザ (つまり postmaster,
# webmaster...) へのメールを拒絶する. こういったユーザは外部へ行くメールを送ること
# はないので , 返送されてくるメールを受け取るはずがない.
#
# 注意: これは既定ではコメントアウトしてある. なぜなら , メールをど う配送する
#
かによって条件が変わってくるからだ . この検査を有効にしたいときは , 下
#
#
#deny
記の条件のどれかひとつだけ , コメントをはずすこと .
#
#
message
= This address never sends outgoing mail. \
You are responding to a forged sender address.
#
#
#
log_message = bogus bounce for system user <$local_part@$domain>
senders
= : postmaster@*
domains
= +local_domains
#
#
set acl_m9
= ${extract{1}{=}{${lc:$local_part}}}
67
# --- 受信者にローカルのアカウントがあるのなら , 以下の 2 行のコメントをはずす:
# set acl_m9 = ${extract{2}{:}{${lookup passwd {$acl_m9}{$value}}}{0}}
# !condition = ${if and {{>={$acl_m9}{500}} {<${acl_m9}{60000}}} {true}}
#
# --- メールを Cyrus に配送しているのなら , 以下の行のコメントをはずす:
# condition = ${run {/usr/sbin/mbpath -q -s user.$acl_m9} {true}}
# --------------------------------------------------------------------
# 送信者アドレスのド メインについての SPF 情報を問合わせ, もしあれば ,
# 送信側のホストがそのメールの配送を認証されているか調べる.
# されていなければ , そのメールは拒否する.
#
deny
message
= [SPF] $sender_host_address is not allowed to send mail \
from $sender_address_domain
log_message = SPF check failed.
spf
= fail
# メッセージに SPF-Received: ヘッダを追加する
warn
message
= $spf_received
# -------------------------------------------------------------------# この特定の相手/送信者/受信者の三つ組に対するグレーリストの状態を検査する.
# この文のコメントをはずす前に , "greylistd" をインストールする必要がある.
# http://packages.debian.org/unstable/main/greylistd を見てほしい.
#
# 送信者が空のメッセージはグレーリストしないことに注意. なぜなら送信者
# 呼出し確認が失敗する (そのため, 呼出しを実施しているホストへメールを送れ
# なくなりかねない) からだ .
#
#defer
#
#
message
= $sender_host_address is not yet authorized to deliver mail \
from <$sender_address> to <$local_part@$domain>. \
#
#
#
Please try later.
log_message = greylisted.
domains
= +local_domains : +relay_to_domains
#
#
!senders
set acl_m9
= : postmaster@*
= $sender_host_address $sender_address $local_part@$domain
#
#
#
set acl_m9
condition
delay
= ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
= ${if eq {$acl_m9}{grey}{true}{false}}
= 20s
# --------------------------------------------------------------------
68
# 受信者を受け付ける.
accept
A.14.5
acl data
# このアクセス制御リストは , SMTP を通じて受け取るメッセージデータに使う.
# テストは順に実行され , 受信者アドレスが受け付けられるか拒絶されたところ
# で終る.
acl_data:
# 一部のヘッダ行を記録する
warn
logwrite
= Subject: $h_Subject:
# 自ホストから届いたメッセージに Message-ID がなければ追加する.
warn
condition
hosts
message
= ${if !def:h_Message-ID: {1}}
= +relay_from_hosts
= Message-ID: <E$message_id@$primary_hostname>
# ローカルの SMTP 経由 (つまり TCP/IP 経由でない) で受け取ったメールを受け付ける.
# 空の送信側のホスト項目をテストすることで , それを調べる.
# また, メールのリレーに使うホストから受け取ったメールも受け付ける.
#
accept
hosts
= : +relay_from_hosts
# メッセージが認証された接続を通じて届いたら , どんなホストでも受け付ける.
#
accept
authenticated = *
# 以前に $acl_m0 に拒絶する理由を入れてあれば拒絶. また, 送信者をさらに 20 秒
# 足止めする.
#
deny
message
= $acl_m0
log_message = $acl_m1
condition
delay
= ${if and {{def:acl_m0}{def:acl_m1}} {true}{false}}
= 20s
# メッセージサイズの限度を課す
#
69
deny
message
condition
= Message size $message_size is larger than limit of \
MESSAGE_SIZE_LIMIT
= ${if >{$message_size}{MESSAGE_SIZE_LIMIT}{yes}{no}}
# アドレスリストのヘッダが構文的に正しくなければ拒絶する.
#
deny
message
= Your message does not conform to RFC2822 standard
log_message = message header fail syntax check
!verify
= header_syntax
# Message-ID:, Date:, Subject: のない非ローカルメッセージを拒絶するには ,
# 以下のもののコメントをはずす.
#
# 一部の特殊化された MTA (ある種のメーリングリストサーバのような ) は ,
# バウンスの Message-ID を自動的に生成しないことに注意.
# そのため, 空でない送信者の検査も追加する.
#
#deny
# message
= Your message does not conform to RFC2822 standard
#
#
#
log_message = missing header lines
!hosts
= +relay_from_hosts
!senders
= : postmaster@*
#
#
condition
condition
#
#
= ${if !eq {$acl_m0}{accept}{true}}
= ${if or {{!def:h_Message-ID:}\
{!def:h_Date:}\
{!def:h_Subject:}} {true}{false}}
# 少なくとも "Sender:", "Reply-To:", "From:" のヘッダのいずれかに
# 確認できる送信者アドレスがなければ , 警告する.
#
warn
message
= X-Sender-Verify-Failed: No valid sender in message header
log_message = No valid sender in message header
!verify
= header_sender
# -------------------------------------------------------------------# ここでは , エンヴェロープ送信者のないメッセージにグレーリスト法を実施する.
# RCPT TO: の後ではこういったものをグレーリスト法にかけていない. なぜなら
# 送信者呼出しをしているリモートホストの邪魔になるからだ .
# 送信者アドレスが空であることに注意. そのため送信者アドレスは使わない.
#
70
# この文のコメントをはずす前に , "greylistd" をインストールする必要がある.
# http://packages.debian.org/unstable/main/greylistd を見てほしい.
#
#defer
# message
#
= $sender_host_address is not yet authorized to send \
delivery status reports to <$recipients>. \
#
#
Please try later.
log_message = greylisted.
#
#
#
senders
condition
set acl_m9
= : postmaster@*
= ${if !eq {$acl_m0}{accept}{true}}
= $sender_host_address $recipients
#
#
set acl_m9
condition
= ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
= ${if eq {$acl_m9}{grey}{true}{false}}
# delay
= 20s
# --------------------------------------------------------------------
# --- ここから EXISCAN 設定 --# 重大な MIME エラーがあるメッセージは拒否する.
#
deny
message
demime
condition
= Serious MIME defect detected ($demime_reason)
= *
= ${if >{$demime_errorlevel}{2}{1}{0}}
# MIME コンテナを解き、ワームが使うファイル拡張子は拒否する.
# これは demime 条件をもう一度呼び出すが 、キャッシュした結果が返る.
# 拡張子の一覧は完全なものではないことに注意.
#
deny
message
demime
= We do not accept ".$found_extension" attachments here.
= bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url
# MESSAGE_SIZE_SPAM_MAX より大きいメッセージは , スパムやウィルスの検出を
# せず受け付ける
accept
condition
= ${if >{$message_size}{MESSAGE_SIZE_SPAM_MAX} {true}}
logwrite
= :main: Not classified \
(message size larger than MESSAGE_SIZE_SPAM_MAX)
# -------------------------------------------------------------------# ウィルス検出
# これには , 首節で ’av_scanner’ の設定が要る.
71
#
#deny
# message
= This message contains a virus ($malware_name)
# demime
= *
# malware = */defer_ok
# --------------------------------------------------------------------
# SpamAssassin を呼び出して, $spam_score と $spam_report を得る.
# 選別結果に応じて, $acl_m9 に "ham" か "spam" をセットする.
#
# メッセージが spam に選別され , 以前に $acl_m0 をセットして必ず受け付けるこ
# ことを示していなければ , 拒否したふりをする.
#
warn
set acl_m9 = ham
# -----------------------------------------------------------------# SpamAssassin でユーザごとの設定をさせたければ , 以下の行のコメントを
# はずし , "spam = mail" をコメントアウトする.
# ユーザ名として, 受信者アドレスで指定されたもの, つまり どの ’=’ 文字や
# ’@’ 文字 よりも前のものを , 小文字に変換して使う, 受信者は複数現れるは
# ずがない. なぜなら以前に , 配送を一度にひとつの受信者に限っているから .
#
# spam
= ${lc:${extract{1}{=@}{$recipients}{$value}{mail}}}
# -----------------------------------------------------------------spam
set acl_m9
= mail
= spam
condition
control
logwrite
= ${if !eq {$acl_m0}{accept}{true}}
= fakereject
= :reject: Rejected spam (score $spam_score): $spam_report
# メッセージに適切な X-Spam-Status: ヘッダを追加する.
#
warn
message
logwrite
= X-Spam-Status: \
${if eq {$acl_m9}{spam}{Yes}{No}} (score $spam_score)\
${if def:spam_report {: $spam_report}}
= :main: Classified as $acl_m9 (score $spam_score)
# --- ここまで EXISCAN 設定 ---
# メッセージを受け付ける.
#
72
accept
73
用語集
概要
ここでは、この文書全体で使う単語や用語の定義を述べる。
ラテン字
Bayes 式フィルタ [Bayesian Filters]
18
メッセージ間の語 (最近では語の組合せや句のこともある) の再現
性に基づいて、 メッセージがスパムである確率を決定するフィルタ。
最初に、不要メール (スパム) と分かっているメッセージと真っ当なメール (非スパム) と分かってい
るメッセージを与えて、フィルタを鍛える。 各メッセージの語 (または句) ごとに、 特定の語句が非
スパムとスパムのどちらにより多く現れるかを示す Bayes 式得点が決まる。語は得点とともに Bayes
式インデクスに蓄えられる。
このようなフィルタは、人間のプログラマが手作業で作成した キーワードに基づくフィルタでは見落
とされてしまうようなスパムのしるしを 見つけ出すこともある。すくなくとも、そういう作業を自動
化できる。
Bayes 式語句インデクスは、明らかに、 鍛えるときに使ったメッセージの言語に特化してしまう。 さ
らに、ユーザ個々人にも特化してしまう。したがっておそらく、 システム全体の SMTP の時点での
排除よりも、個人用のコンテンツフィルタ (例えば メール利用者エージェント [79] での) に適してい
るであろう。
そのうえ、スパム送信者は 簡易な Bayes 式フィルタを打ち破るテクニックを開発してきている。 で
たらめな辞書単語や短いストーリーをメッセージに入れておくのである。 これは、Bayes 式フィルタ
で決定されるスパム確率を下げるし 、 長い目で見れば Bayes 式インデクスの質を落すことになる。
http://www.everything2.com/index.pl?node=Bayesian も見よ。
Request for Comments (略称: RFC) http://www.rfc-editor.org/ より: 「 Request for Comments
(RFC) 文書集は、 インターネットについての技術面や組織面の記述の集合である [...]。 RFC 集の覚
書では、コンピュータネットワーキングのさまざ まな側面 (プロトコル、手続き、プログラム、概念
などを含む) について論じられており、 さらに会議の記録、意見、あとたまに冗談などもある。」
これらの文書が 、 プロトコルやデータ形式の記述も含めたインターネット運営上の 「掟」 となって
いる。 メール配送に関わるものとしては、つぎのものがある:
• RFC 282119 ”簡易メール転送プロトコル ” [Simple Mail transfer Protocol] と、
• RFC 282220 ” インターネット メッセージの形式” [Internet Message Format]。
あ
エンヴェロープ受信者 [Envelope Recipient] メッセージが送られる先の電子メールアドレス。 SMTP トラ
ンザクションの間に、RCPT TO: コマンド を使って与えられる。 これは、メッセージそのものの
「 To: 」 ヘッダや 「 Cc: 」 ヘッダにあるアドレスとは違うこともある。
18 [訳注]
事後確率に関する 「 Bayes の定理」 (1764) の応用であるため、 こう呼ばれる。
19 http://www.ietf.org/rfc/rfc2821
20 http://www.ietf.org/rfc/rfc2822
75
[SMTP トランザクション ] [4] も見よ。
エンヴェロープ送信者 [Envelope Sender] メッセージの送信者である電子メールアドレス。 SMTP トラン
ザクションの間に、MAIL FROM: コマンドを使って与えられる。 これは、メッセージそのものの
「 From: 」 ヘッダにあるアドレスとは違うこともある。
特殊な場合として、配送状況通知 [78] (バウンスしたメッセージ、 受け取り通知、不在メッセージ ...)
がある。このようなメールでは、 エンヴェロープ送信者 [76] は空である。 これはメールループ [79]
を防止するためであり、 また一般にこういったものを 「通常の」 メールと区別できるようにするた
めである。
[SMTP トランザクション ] [4] も見よ。
か
開放型プロキシ [Open Proxy] どこからの TCP/IP 接続でも受け付け、 それをどこへでも転送できるプロ
キシ [78]。
スパム送信者やウィルスが悪用する。自分の IP アドレスを隠すのに使ったり、 複数のホストやネッ
トワークを通じて転送負荷を分散させるのである。
ゾンビホスト [77] も見よ。
開放型リレー [Open Relay] どこからのメールでも受け付け、 それをどこへでも転送できるリレー [79]。
1980 年代には 、公開されている SMTP サーバは 、 実質的にはどれもが開放型リレー [76] だった。
メッセージはしばしば 、 複数の第三者の計算機を渡り歩いてから目指す受信者にたどり着いていた。
今日では、真っ当なメールはほぼ例外なく、送信者の側の送出用メール転送エージェント [79] から受
信者のド メインの側の受入用メール交換機 [79] へ 直接送られている。
逆に、 いまだにインターネット上に存在する開放型リレー [76] サーバは ほぼ例外なく、スパム送信
者が自分の身許を隠したり 何万というメッセージを送る作業で負荷分散を実行したりするために悪
用されている。 おそらくこれは、 DNS ブロックリストがこういった計算機をすべて登録してしまう
までは続くであろう。
[開放型リレーの防止] [13] についての議論も見よ。
完全修飾ド メイン名 [Fully Qualified Domain Name] (別名 「 FQDN 」) 完全で、全地球的に一意な、 DNS
ド メインを含むインターネットでの名前。例えば : 「 www.yahoo.com 」
。
FQDN がかならず単一のホストを指しているとは限らない。 例えば 、
「 www 」 のような一般的なサー
ビスの名前はしばしば 複数の IP アドレスを指している。これはサーバ間での負荷分散のためである。
とはいえ、どの計算機ではプライマリホスト名は かならずその計算機に固有のものである — 例えば :
「 p16.www.scd.yahoo.com 」
。
FQDN はかならずピリオド (”.”) を含む。 最初のピリオド よりも前の部分が非修飾名で、 これは全
地球的に一意ではない。
偽陰性 [False Negative] 不要メール (スパム、ウィルス、マルウェア) が、 誤って真っ当なメールに選別さ
れてしまった (そしてそのために、排除されなかった) もの。
偽陽性 [False Positive] 真っ当なメールが 、誤って不要メールに選別されてしまった (そしてそのために 、
阻止されてしまった) もの。
巻き添え被害 [78] も見よ。
76
さ
小額課金方式 [Micropayment Schemes] (別名 元払い方式 [sender pay schemes])。 メッセージの送信者は、
メッセージの受信者各々について、 いくらか計算機の資源を費やして仮想的な切手を作成する — 通
常は、大量のメモリ読み書きを要するが CPU 速度は相対的に速いような 数学的な問題を解くことに
なる。そして、この切手をメッセージのヘッダに付加する。 受信者のほうでは、この切手をより簡単
なデコード 操作で検証できるようになっている。
このアイデ ィアではメッセージのすべての受信者アドレスごとに切手が必要になるので、 何千もの
ユーザに一度に送ろうとすると途方もなく ”高くつく” ことになる。
このようなシステムが 2 つある:
• Camram21
• Microsoft’s Penny Black Project22
スパムト ラップ [Spam Trap] 公開の場でアドレスを収集しているロボットをおびき寄せて [DNS によるブ
ラックリスト ] [9] や[不要メールシグネチャ集積システム] [19] のような 協調型ツールで捕らえるため
の、 撒き餌にする電子メールアドレス。
このアドレスに送られてくるメールは通常、スパムかマルウェアである。 しかし 、そのうちのある
ものは巻き添えスパム — つまり偽装された送信者アドレスに送られる配送状況通知 [78] — である。
したがって、 スパムトラップがこのようなメッセージを無視する安全装置を具えていなければ 、 結
果としてツールは完全に信頼できるものではなくなるであろう。
ゾンビホスト [Zombie Host] インターネット接続している計算機で、 大量メール送信型のウィルスやワー
r Windows°
r
ムに感染しているもの。 このような計算機は、かならずと言っていいほど Microsoft°
オペレーティングシステムの類を実行しているし 、 ほぼかならず 「常時接続」 IP アドレスブロック
にある。 持ち主は、計算機が感染していることに気づいていないか、 そもそもそんなことは気にし
ていないし 、 しばしば ISP の側も、それをシャットダウンさせるための行動を起こさない。
幸いなことに、
「 dul.dnsbl.sorbs.net 」 のようなさまざ まな DNS ブロックリストがあって、 このよ
うな ”常時接続” アドレスブロックを収集している。 こういうブロックリストを使うと外部から来る
メールを拒否することができる。 常時接続ユーザからの真っ当なメールは、通常、 ISP の 「スマー
トホスト 」 を通じてやって来るものである。
た
ド メインネームシステム [Domain Name System] (略称: DNS) インターネットのド メイン名についての情
報を取得するための、事実上の標準。 このような情報の例としては、サーバの IP アドレス (いわゆ
る A レコード ) 、 受入用メール交換機の割り当て (MX レコード ) 、一般的なサーバの情報 (SRV レ
コード ) 、 その他のテキスト情報 (TXT レコード ) がある。
DNS は 、階層型で分散型のシステムである — 各々のド メイン名は 、 一つまたはその以上の DNS
サーバの組と関連づけられており、 この DNS サーバがド メインについての情報 (自身のサブド メイ
ンについてのネームサービスの委任状況も含む) を提供する
例えば 、最上位ド メイン 「 org 」 は The Public Interest Registry が運用している — このド メインの
DNS サーバはド メイン名 「 tldp.org 」 についての問い合わせを The Linux Documentation Project
21 http://www.camram.org/
22 http://research.microsoft.com/research/sv/PennyBlack/
77
の特定のネームサーバに委任する。 そして、TLDP のネームサーバ (実は UNC が運用している) は
第 3 階層のド メイン名 (「 www.tldp.org 」 のような ) についての問い合わせを、委任したりしなかっ
たりする。
DNS 検索は普通、転送ネームサーバを使って行なう。 このようなものはインターネットサービスプ
ロヴァイダが (例えば DHCP によって ) 提供する。
な
なりすまし メール [Joe Job] 別人の有効なアドレスから来たかのように見えるように作ってあるスパム。 こ
れはしばしば 、苦情の行き先を第三者に逸らしたり そのアドレスの持ち主にほかにも損害を与えよ
うとする、 悪質な企みによるものである。
http://www.everything2.com/index.pl?node=Joe%20Job も見よ。
は
配送状況通知 [Delivery Status Notification] (略称: DSN) 送信者に送信したメッセージの状況について知
らせるために MTA や MDA が自動的に作成するメッセージ (普通は、DSN の中に元のメッセージが
含まれている)。 DSN では例えば 、 元メッセージが一時的あるいは恒久的な問題のために配送でき
なかったことや、 配送の試行がどのくらいの間続くのか、あるいは続かないのかを 送信者に知らせ
ることができる。
配送状況通知は空のエンヴェロープ送信者 [76] アドレスから送られる。
プロキシ [Proxy] 他の計算機に代わって働く計算機。 通常は、インターネットに向けて、あるいはインター
ネットから、 HTTP 要求や TCP/IP 接続などを転送したりする。 例としては、よく企業 — ときに
は国家全体 — で 「 Web プロキシ サーバ」 を使って、 内部のネットワークから外部へ行く HTTP
要求を、通したり通さなかったりしている。 これは、エンド ユーザから見て透過的なこともそうでな
いこともある。
開放型プロキシ [76] 、リレー [79] も見よ。
ま
巻き添えスパム [Collateral Spam]
23
送信者アドレスが偽装されているメッセージ (多くがスパムやマル
ウェア) に対して、自動的に応答して送られるメッセージ。 巻き添えスパムの典型的な例としては、
ウィルス検出報告 (「 You have a virus 」) やその他の配送状況通知 [78] がある。
巻き添え被害 [Collateral Damage] 真っ当な送信者ホストが、DNS ブロックリストへ登録されたために メッ
セージが阻止されてしまうこと。
一部のブロックリスト (SPEWS のような ) は、 ISP が苦情に反応しないようだと その ISP の IP ア
ドレス空間全体を機械的に登録してしまうので、 その ISP の顧客全員が影響を被ることになる。
偽陽性 [76] も見よ。
23 [訳注]
backscatter mail (後方散乱メール — とばっちりメール ) とも言う。
78
メール交換機 [Mail Exchanger] (略称: MX) インターネットド メインのメールを (送ったり) 受け取ったり
するための専用の計算機。
通常、インターネットド メインの DNS ゾーン情報には そのド メインの受入用メール交換機として働
く完全修飾ド メイン名 [76] の一覧が含まれている。 このような一覧の各々を 「 MX レコード 」 と呼
ぶ。 各々のレコードは、複数の 「 MX レコード 」 の間での 「優先度」 を示す数値を含む。最小の
数値のものが最優先となり、 そのド メインの 「プライマリのメール交換機」 とみなされる。
メール転送エージェント [Mail Transport Agent] (略称: MTA) インターネットド メインのメール交換機な
どのように、 メールサーバで動作しているソフトウェア。 メールを他のホストへ送信したり、他の
ホストから受信したりする。 よく普及している MTA としては、Sendmail, Postfix, Exim, Smail が
ある。
メール配送エージェント [Mail Delivery Agent] (略称: MDA) ユーザのメールボックスが置かれている計算
機で動作するソフトウェアで、 メールをそのメールボックスへ配送するもの。 MTA メール転送エー
ジェント [79] が配送を直接実行していることもよくあるが、 そういう MTA は MDA の役割も兼ね具
えていることになる。 独立したメール配送エージェントの例としては、Deliver, Procmail, Cyrmaster
および Cyrdeliver (Cyrus IMAP スイートに入っている) がある。
メール利用者エージェント [Mail User Agent] (略称: MUA; 別名 メールリーダ [Mail Reader]) メールに
アクセスし 、ダウンロードし 、読み、送るためのユーザソフトウェア。 例としては Microsoft Out-
look/Outlook Express, Apple Mail.app, Mozilla Thunderbird, Ximian Evolution がある。
メールループ [Mail Loop] 自動的に送られたあるメッセージが他のメッセージを発生させ、 そうした他の
メッセージが直接あるいは間接に最初のメッセージを再び発生させ、 ということが続く状況。
メーリングリストで、 購読者のひとつがそのリストそのもののアドレスである場合を考えてみるとよ
い。 リストサーバはこのような状況に陥らないようにするため、よく メッセージヘッダに 「 X-Loop: 」
といったヘッダをつけ加えて すでにこのヘッダがあるメールは処理しないようにする。
同義語はリンギング [Ringing] である。
ら
ラット ウェア [Ratware] スパム送信者が使っている大量メール送信型のウィルスや電子メールソフトウェ
ア。 大量のメールを極めて短時間で送るれるように特別に作ってある。
多くのラットウェアの実装には、 最良の筋書きにそってメールを配送できるだけの SMTP クライア
ントのコードしか入っていない。 SMTP 通信の中で、受信側ホストに偽の、あるいは不正確な情報を
与えようとする。 コマンド を発行する前に受け手からの応答を待とうとしないし 、 何秒か応答を受
信できないと接続を切る。 一時的なエラーの場合に、通常の再送機構にのっとった振舞いをしない。
リレー [Relay] 電子メールをインターネットから、あるいはインターネットへ転送する計算機。 リレーの
例のひとつに 「スマートホスト 」 がある。 これは、ISP が顧客に、外部へ行くメールを送信するた
めに提供するものである。
開放型リレー [76] 、プロキシ [78] も見よ。
79
付録 B
GNU General Public License
[訳注: 本付録は訳さない。]
B.1
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By
contrast, the GNU General Public License is intended to guarantee your freedom to share and change
free software - to make sure the software is free for all its users. This General Public License applies
to most of the Free Software Foundation’s software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by the GNU Library General Public
License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses
are designed to make sure that you have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it if you want it, that you can change
the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or
to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the
recipients all the rights that you have. You must make sure that they, too, receive or can get the source
code. And you must show them these terms so they know their rights.
We protect your rights with two steps:
1. copyright the software, and
2. offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author’s protection and ours, we want to make certain that everyone understands that
there is no warranty for this free software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so that any problems introduced by
others will not reflect on the original authors’ reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger
that redistributors of a free program will individually obtain patent licenses, in effect making the program
proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone’s free
use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
B.2
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
81
B.2.1
Section 0
This License applies to any program or other work which contains a notice placed by the copyright
holder saying it may be distributed under the terms of this General Public License. The ”Program”,
below, refers to any such program or work, and a 「 work based on the Program 」 means either the
Program or any derivative work under copyright law: that is to say, a work containing the Program or a
portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter,
translation is included without limitation in the term 「 modification 」.) Each licensee is addressed as
「 you 」.
Activities other than copying, distribution and modification are not covered by this License; they are
outside its scope. The act of running the Program is not restricted, and the output from the Program is
covered only if its contents constitute a work based on the Program (independent of having been made
by running the Program). Whether that is true depends on what the Program does.
B.2.2
Section 1
You may copy and distribute verbatim copies of the Program’s source code as you receive it, in any
medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the
absence of any warranty; and give any other recipients of the Program a copy of this License along with
the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer
warranty protection in exchange for a fee.
B.2.3
Section 2
You may modify your copy or copies of the Program or any portion of it, thus forming a work based
on the Program, and copy and distribute such modifications or work under the terms of Section 1 above,
provided that you also meet all of these conditions:
1. You must cause the modified files to carry prominent notices stating that you changed the files and
the date of any change.
2. You must cause any work that you distribute or publish, that in whole or in part contains or is
derived from the Program or any part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
3. If the modified program normally reads commands interactively when run, you must cause it,
when started running for such interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a notice that there is no warranty (or
else, saying that you provide a warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this License.
Exception:
If the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
82
These requirements apply to the modified work as a whole. If identifiable sections of that work are
not derived from the Program, and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those sections when you distribute them as
separate works. But when you distribute the same sections as part of a whole which is a work based on
the Program, the distribution of the whole must be on the terms of this License, whose permissions for
other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely
by you; rather, the intent is to exercise the right to control the distribution of derivative or collective
works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a
work based on the Program) on a volume of a storage or distribution medium does not bring the other
work under the scope of this License.
B.2.4
Section 3
You may copy and distribute the Program (or a work based on it, under Section 2 in object code or
executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software
interchange; or,
2. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge
no more than your cost of physically performing source distribution, a complete machine-readable
copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above
on a medium customarily used for software interchange; or,
3. Accompany it with the information you received as to the offer to distribute corresponding source
code. (This alternative is allowed only for noncommercial distribution and only if you received the
program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For
an executable work, complete source code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to control compilation and installation of the
executable. However, as a special exception, the source code distributed need not include anything that is
normally distributed (in either source or binary form) with the major components (compiler, kernel, and
so on) of the operating system on which the executable runs, unless that component itself accompanies
the executable.
If distribution of executable or object code is made by offering access to copy from a designated place,
then offering equivalent access to copy the source code from the same place counts as distribution of the
source code, even though third parties are not compelled to copy the source along with the object code.
B.2.5
Section 4
You may not copy, modify, sublicense, or distribute the Program except as expressly provided under
this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and
will automatically terminate your rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses terminated so long as such parties
remain in full compliance.
83
B.2.6
Section 5
You are not required to accept this License, since you have not signed it. However, nothing else grants
you permission to modify or distribute the Program or its derivative works. These actions are prohibited
by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any
work based on the Program), you indicate your acceptance of this License to do so, and all its terms and
conditions for copying, distributing or modifying the Program or works based on it.
B.2.7
Section 6
Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further restrictions on the recipients’ exercise of the
rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
B.2.8
Section 7
If, as a consequence of a court judgment or allegation of patent infringement or for any other reason
(not limited to patent issues), conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of
this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License
and any other pertinent obligations, then as a consequence you may not distribute the Program at all.
For example, if a patent license would not permit royalty-free redistribution of the Program by all those
who receive copies directly or indirectly through you, then the only way you could satisfy both it and
this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the
balance of the section is intended to apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims
or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the
free software distribution system, which is implemented by public license practices. Many people have
made generous contributions to the wide range of software distributed through that system in reliance
on consistent application of that system; it is up to the author/donor to decide if he or she is willing to
distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of
this License.
B.2.9
Section 8
If the distribution and/or use of the Program is restricted in certain countries either by patents or by
copyrighted interfaces, the original copyright holder who places the Program under this License may add
an explicit geographical distribution limitation excluding those countries, so that distribution is permitted
only in or among countries not thus excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
B.2.10
Section 9
The Free Software Foundation may publish revised and/or new versions of the General Public License
84
from time to time. Such new versions will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of
this License which applies to it and ”any later version”, you have the option of following the terms and
conditions either of that version or of any later version published by the Free Software Foundation. If the
Program does not specify a version number of this License, you may choose any version ever published
by the Free Software Foundation.
B.2.11
Section 10
If you wish to incorporate parts of the Program into other free programs whose distribution conditions
are different, write to the author to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this.
Our decision will be guided by the two goals of preserving the free status of all derivatives of our free
software and of promoting the sharing and reuse of software generally.
B.2.12
NO WARRANTY Section 11
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ”AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
B.2.13
Section 12
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED
BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
B.3
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best
way to achieve this is to make it free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each
85
source file to most effectively convey the exclusion of warranty; and each file should have at least the
”copyright” line and a pointer to where the full notice is found.
<one line to give the program’s name and a brief idea of what it does.> Copyright (C) <year> <name
of author>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not,
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive
mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY
NO WARRANTY; for details type ‘show w’. This is free software, and you are welcome to redistribute
it under certain conditions; type ‘show c’ for details.
The hypothetical commands ‘show w’ and ‘show c’ should show the appropriate parts of the General
Public License. Of course, the commands you use may be called something other than ‘show w’ and
‘show c’; they could even be mouse-clicks or menu items–whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a
”copyright disclaimer” for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program ‘Gnomovision’ (which makes
passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs.
If your program is a subroutine library, you may consider it more useful to permit linking proprietary
applications with the library. If this is what you want to do, use the GNU Library General Public License
instead of this License.
86