WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

独自ドメインのメール送信を SPF に対応させる方法

最近受け取るメールのヘッダを見ていて気付いたのですが、 SPF や DomainKeys といった送信ドメイン認証を施したメールがずいぶん増えてきましたね。すでにメジャーな企業やプロバイダのほとんどは対応しているようです。 OP25B が普及して動的 IP 接続による自宅サーバーでは満足にメールが送れなくなって久しいですが、このままだと送信ドメイン認証なしのメールも使えなくなりそうな勢いです。微妙に危機感を覚えたので、そのあたりのことを少し調べてみました。

送信ドメイン認証というと SMTP サーバーにいろいろな設定を施さないといけない印象があります。実際 DomainKeys などの方式は送信側・受信側ともに SMTP サーバーの対応が必要になります。しかし、 SPF という方式を使うと、送信側に限っては DNS の設定変更だけで対応できることがわかりました。これならレンタルの SMTP サーバーを使っていても簡単に対応できますので、本日はこの SPF についてご紹介します。

なお、以下の説明はわかりやすさを優先させたため、正確さや網羅性はいまいちです。さらなる詳細をお望みの方は、正式な仕様である RFC 4408 をご参照ください。


Google Apps で DKIM を設定する方法 も掲載しました。 Google Apps をご利用の方は、こちらもあわせて設定することをお勧めします。

SPF の概要

SPF は「Sender Policy Framework」の略で、メールの送信元アドレスの詐称を防ぐための、いわゆる送信ドメイン認証技術のひとつです。 DNS の TXT レコードに正当な SMTP サーバーの情報を列挙するだけという素朴な方法で送信ドメインの検証を行います。 SPF を利用したメールの検証手順はだいたい以下のようになります。

  1. 送信元 SMTP サーバーが受信先 SMTP サーバーに接続する。
  2. 受信先サーバーは、送信元サーバーから与えられたドメインの TXT レコードを取得する。
  3. TXT レコードの内容に従い、送信元サーバーが正当なサーバーであるかどうかを検証する。
  4. 検証結果によって、受信先サーバーはそのメールを配信するか、拒否するかなどを決定する。

このように、すべての検証作業は受信先の SMTP サーバーが行い、送信元 SMTP サーバーの動作は SPF がない場合となんら変わりがありません。従って、 DNS の TXT レコードに適切な情報をさえ格納すれば、それだけで SPF に対応したメール送信が実現できます。この手軽さが SPF の最大の利点です。

SPF の設定方法

SPF の設定は DNS 正引きゾーンデータベースの TXT リソースレコードに記述します。例えば BIND で webos-goodies.jp ドメインに対して SPF を設定する場合は以下のような記述になります。

webos-goodies.jp. TXT "v=spf1 a:mail.webos-goodies.jp ~all"

VALUE DOMAIN のレンタル DNS サーバーで同じ設定をするとこんな感じです。

txt webos-goodies.jp. v=spf1 a:mail.webos-goodies.jp ~all

このように、 DNS のデータベースにたった 1 行加えるだけでメールサーバーの正当性を証明することができます。これは簡単ですね。以下で、具体的な TXT レコードの内容(以下、 SPF レコードと呼びます)の記述方法をご紹介しますので、ご自分の環境に合った SPF レコードを設定してください。

SPF レコードの記述方法

それでは、 SPF レコードの記述方法を見ていきましょう。 SPF レコードは必ず "v=spf1" という文字列で始まり、以降は空白区切りで複数のディレクティブ、もしくは Modifier が並ぶという構成になっています。例えば、 "mail.webos-goodies.jp" のみが正当な SMTP サーバーで、それ以外はすべて不当であるという場合は、以下のように記述します。

v=spf1 +a:mail.webos-goodies.jp ~all

"+a:mail.webos-goodies.jp" や "~all" がディレクティブです。先頭の "+", "~" は Qualifier と呼ばれ、マッチするホストからのメールをどのように扱うかを示しています。それ以降の文字列は Mechanism で、ホストのマッチングルールになっています。マッチングは最初のディレクティブから順番に行われ、最初にマッチしたディレクティブの Qualifier が適用されて処理を終了します。もしマッチする項目がひとつもなければ、 SPF レコードが存在しない場合と同じように扱われます。このため、上記の例では最後に "~all" を記述し、それまでにマッチしなかったすべてのホストを不当なものとして扱うようにしています。

上記以外にもさまざまな Qualifier / Mechanism があります。

Qualifier

Qualifier はディレクティブの先頭の 1 文字で、マッチするホストからのメールをどのように扱うかを指定します。省略も可能で、その場合は "+" が指定されたものとして扱われます。利用可能な Qualifier には以下のものがあります。

Qualifierステータスメールの扱い
+Pass正当なメールとして配信される
-Fail不当なメール(拒否される場合がある)
~SoftFail不当なメール(配信は行われる)
?NeutralSPF 指定がないものとして扱われる

上記の「ステータス」というのは、メール配信時に付加される "Received-SPF:" ヘッダに表記される文字列です。 Received-SPF ヘッダに関する詳細は後述します。また、「メールの扱い」はあくまで代表的な例ですので、すべてのサーバーが上記のような動作をするとは限りません。最終的には受信側サーバーの裁量にいかんです。

Mechanism

Mechanism はディレクティブの Qualifier を除く部分で、ホストのマッチングルールを指定します。多くの指定方法がありますので、それぞれ個別にご紹介します。

ip4 : IP アドレスによるマッチ

"ip4" は送信元 IP アドレスが指定された IP アドレスと一致するかを確認する Mechanism です。書式は以下のようになります。

ip4:<IPアドレス>

例えば、 "+210.251.253.231" というディレクティブは、送信元の IP アドレスが 210.251.253.231 のときに "Pass" の結果と共に処理を終了し、それ以外の場合は次のディレクティブの処理に移ります。もし IPv6 のアドレスを指定する場合は、 "ip4" の代わりに "ip6" を使ってください。

a : ドメイン名に対応する IP アドレスとのマッチ

"a" は、 DNS から取得した IP アドレスと送信元 IP アドレスを比較する Mechanism です。指定されたドメイン名(省略時は送信元のドメイン名)の IP アドレスを DNS で取得し、それが送信元の IP アドレスと同じであればマッチします。対象ドメイン名に複数の IP アドレスがマッピングされている場合は、そのいずれかひとつと同じであればマッチします。書式は以下のようになります。

a[:<ドメイン名>]

例えば、 "+a:mail.webos-goodies.jp" なら、送信元の IP アドレスが mail.webos-goodies.jp のアドレスのいずれかひとつと同じであれば "Pass" します。

mx : MX レコードとのマッチ

"mx" は MX レコードに列挙されているホストの IP アドレスと送信元 IP アドレスを比較する Mechanism です。指定されたドメイン名(省略時は送信元のドメイン名)の MX レコードを DNS で取得し、そのいずれかが送信元の IP アドレスと同じであればマッチします。書式は以下のようになります。

mx[:<ドメイン名>]

例えば、単に "+mx" と記述すると、送信元の IP アドレスが送信元ドメインの MX レコードに含まれていれば "Pass" します。

ptr : 逆引きで得たドメイン名とのマッチ

"ptr" は送信元 IP アドレスを逆引きして取得したドメイン名と指定されたドメイン名を比較する Mechanism です。書式は以下のようになります。

ptr[:<ドメイン名>]

処理内容はだいたい以下のようになります。

  1. 送信元 IP アドレスを DNS で逆引きし、対応するドメイン名を得る(対応するドメイン名は複数になる可能性もある)。
  2. 取得したドメイン名に対応する IP アドレスを DNS で取得し、送信元 IP アドレスがそれに含まれていることを確認する。もし含まれていなければ、そのドメイン名はリストから外す。
  3. 残ったドメイン名のいずれかが指定されたドメイン名(省略時は送信元ドメイン名)のサブドメインであれば Mechanism はマッチし、 Qualifier で指定された結果で終了する。そうでなければ次のディレクティブの処理に移る。

このように処理が複雑で多数の DNS クエリーを実行するため、この Mechanism の利用はあまり推奨されていないようです。

all : すべてのホストを表す

さきほども出てきましたが、すべてのホストにマッチする Mechanism が "all" です。主に最後のディレクティブに指定して、デフォルト動作を変更するのに使用します。

include : 他のドメインの SPF レコードを参照

"include" は他のドメインに記述してある SPF レコードで判定を行い、その結果が "Pass" であればマッチする Mechanism です。書式は以下のようになります。

include:<ドメイン名>

例えば、 "?include:webos-goodies.com" と記述した場合、 "webos-goodies.com" に記述された SPF レコードで判定を行い、その結果が "Pass" であれば "Neutral" の結果を適用して終了、それ以外であれば次のディレクティブに移るという動作になります。

exist : 指定したドメインの存在確認

"exist" は指定したドメイン名に対応する A レコードが存在することを確認する Mechanism です。書式は以下のようになります。

exist:<ドメイン名>

ドメイン名にはマクロ展開などを使うのが一般的なようです。この Mechanism の使い方は、私もあまりよく理解できていません。詳細は RFC 4408 をご参照ください。

ネットマスクの指定

"ip4", "ip6", "a", "mx" のパラメータには "/nn" 形式のネットマスクの指定を付加できます。例えば、以下のディレクティブは送信元 IP アドレスの上位 24bit が "webos-goodies.jp" に対応するいずれかの IP アドレスと同じであれば "Pass" します。

+a:webos-goodies.jp/24

メールサーバーの数が多い場合は、これを利用して指定を簡略化できます。

Modifier

ここまででご紹介した通常のディレクティブのほかに、 "redirect" と "exp" という特殊な指定があり、これらを Modifier と呼びます。 Modifier もディレクティブと同様に記述しますが、ホストとのマッチングではなく特定の動作を指定します。

redirect : 他のドメインに委譲

"redirect" Modifier を使うと、すべてのディレクティブがマッチしなかった場合に指定したドメインの SPF レコードに処理を委譲することができます。書式は以下のようになります。

redirect=<ドメイン名>

"redirect" は記述位置にかかわらずすべてのディレクティブが評価された後に適用されます。従って、混乱を避けるために最後に記述することが推奨されています。また、 "all" Mechanism との併用は意味がありませんので注意してください。

exp : Received-SPF ヘッダに表示するコメントを指定

結果が "Fail" だった場合に、送信元の SMTP サーバーに返すメッセージを指定する Modifier です。書式は以下のようになります。

exp=<ドメイン名>

実際のメッセージはドメイン名に対応する TXT レコードの内容が使用されます。マクロ展開で送信元の IP アドレスなどを含めることもできます。詳細は RFC 4408 をご参照ください。

Received-SPF ヘッダについて

ここで少し受信側にも触れておきましょう。 SPF に対応した SMTP サーバーは、 SPF レコードの存在するドメインのメールを受け取ると、そのメールに "Received-SPF:" ヘッダを付加します。例えば Gmail で受信したメールのソースを見ると、多くのメールに以下のような "Received-SPF:" ヘッダが付いていると思います。

Received-SPF: pass (google.com: domain of ... )

この "pass" という部分が、前述の Qualifier の表にあるステータスです。上記の場合は "pass" となっていますので、正当な SMTP サーバーから送信されたメールということが確認できます。メールクライアントのフィルター機能でこのヘッダを識別することで、不当なサーバーからのメールを振り分けることができるわけです。もっとも Gmail 自身のスパムフィルターは、この情報をほとんど使っていないようです。スパムフィルターの精度に自信があるから、送信ドメイン認証なんてイラネ、ってことでしょうかね(w

Gmail と VALUE DOMAIN を併用する際の設定方法

最後に実例として、 VALUE DOMAIN (XREA) の SMTP サーバーと Gmail の両方を正当なサーバーとして扱う設定をご紹介しましょう。 XREA には複数のサーバーがありますが、私は s176.xrea.com を使っているので、それを前提にします。

DNS の設定を変更する

まず gmail.com の TXT レコードを覗いてみると、以下のように設定されています。

"v=spf1 redirect=_spf.google.com"

どうやら gmail.com の SPF レコードは _spf.google.com に丸投げしているだけのようです。そして、 _spf.google.com の SPF レコードには各 SMTP サーバーのアドレスが列挙されています。リダイレクトをネストさせても規格上は問題ないはずですが、受信側の SMTP サーバーにあまり負荷をかけるのも考えものです。ここは直接 _spf.google.com を参照するように設定することにしましょう。それに s176.xrea.com も加えると、結果的に以下の設定を施せhttp://127.0.0.1:3000/sites/1/articles/389/editばいい... DOMAIN のレンタル DNS サーバーの文法で書いてあります)。

txt @ v=spf1 +a:s176.xrea.com include:_spf.google.com ~all

最後は _spf.google.com へのリダイレクトにしても良いのですが、指定したメールサーバー以外からのメールは SoftFail にしたかったのでこうしてみました。 _spf.google.com の SPF レコードは最後が "?all" になっているので、リダイレクトだと不当なサーバーからのメールでも Neutral 扱いになってしまいます。まあ、このあたりは運用方針によって変更してください。

動作を確認する

設定を行ったら、 SPF が正しく動作するかを確認しましょう。設定を間違えて、自分自身が送ったメールが SPAM 扱いされては目もあてられませんからね(笑)。いろいろと方法があるようですが、 "Email Service Provider Coalition" というサイトを利用するのがお勧めです。

http://www.espcoalition.org/senderid/

基本的には、 check-auth[at]verifier.port25.com というアドレス([at]はアットマークに置き換えてください)にメールを送るだけで、各種ドメイン認証技術での検証結果を記載したメールが返信されます。「Summary of Results」の「SPF check」に「pass」と記載されていれば OK です。 SPF だけでなく DomainKeys や SenderID なども同時に検証できるので、ドメイン認証のチェックにはとても便利です。

以上、本日はメールの送信ドメイン認証技術のひとつである SPF の送信側の設定方法をご紹介しました。ここまで読み進めていただいた方にはおわかりのとおり、設定はとても簡単で、その気になれば数分でできてしまいます。出所不明なメールへの風当たりは今後も強くなる一方なので、独自ドメインのメールアドレスをご利用の方は、設定しておくことをお勧めします。

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles