レンタルサーバーの使用に気後れしているエンジニアがタグ付けされたことによってバッシングされそうなタイトルだが、タイトルありきで作成した記事なので、そのまま突き進むことにする。

普段レンタルサーバーを使用しているエンジニアが、Webサイトのフォームから送信したメールが迷惑メールに入らないようにするための忘備録である。
レンタルサーバーではたいていDKIMの設定を代行してくれるため、その詳細な設定は省きつつ必要な知識をまとめている。

SPF (Sender Policy Framework)

受信メールサーバーが、エンベロープFromのメールアドレスのドメインのDNSサーバーに問い合わせ、TXTレコードであるSPFレコードに送信元メールサーバーのIPアドレスが記載されているかを確認することで送信元メールサーバーの正当性を検証するための送信ドメイン認証技術(メールの送信元が正当なものであることを確認する技術)のひとつである。

SPFレコードは次のような形式である。

example.com.    IN    TXT    ”v=spf1 +ip4:192.168.10.1 +a:example.com +mx +include:spf.sender.xserver.jp ~all”

抽象化すると次のようになる。

example.com.    IN    TXT    ”<SPF version> <qualifier><mechanism>:<mechanismの値> ... ~all”

<SPF version>...「v=spf1」
<qualifier>...「+」「-」「~」「?」などの記号
<mechanism>:<mechanismの値>...「ip4:192.168.10.1」など

SPF versionの「v=spf1」は必須で、SPFレコード全体は255文字以下に収める必要がある。

SPFレコードを確認する場合は、以下のようなコマンドを使用する(DKIMやDMARCも同様)。

$ dig example.com txt +short

Mechanisms(メカニズム)

次のようなMechanismsがあり、<mechanism>:<mechanismの値>の形式で記述する。
その条件に一致した場合はその前に指定するqualifiersによって処理される。

  • ip4
    指定したIPv4アドレスと一致するかどうか
  • ip6
    指定したIPv6アドレスと一致するかどうか
  • a
    ドメインのAレコードまたはAAAAレコードが指定されたIPアドレスと一致するかどうか(FQDNで指定)
  • mx
    ドメインのMXレコードに記載されたホストのIPアドレスと一致するかどうか(値は必要ない)
  • include
    指定したドメインのSPFレコードをインポートする(ネストは最大10回まで有効)
  • all
    すべての送信元に一致するかどうか(値は必要ない)。
    基本的には最後に使い、その他のMechanismsに当てはまらないIPアドレスを制御する目的で使用

Qualifiers(修飾子)

あとに続くmechanismとその値に適合した場合、どのように処理するかを設定します。具体的には以下のような意味を持ちますが、受信側のメールサーバーの設定に依存するため、すべてのメールサーバーで処理内容を一律に設定することはできない。

  • 「+」:Pass – 明示的に許可(正常なメールとして処理)
  • 「-」:Fail – 拒否・強制的にブロック(不正メールとして処理され、配信拒否)
  • 「~」:SoftFail – 拒否はしないが警告(不正メールとして処理されるが、配信)
  • 「?」:Neutral – 成否を示さない・無視(SPF指定なしとして処理)

qualifierは省略することが可能で、省略した場合は「+」として処理される。

SPFレコードの末尾は運用の初期段階では「~all」とすることが推奨され、運用が安定してからは「-all」に変更することが推奨される。

メールを使用しない場合は、以下のようなSPFレコードを設定することでなりすましの被害を未然に防止することができる。

XXX.co.jp.   IN   TXT   ” v=spf1  -all”

DKIM(ディーキム、Domain Keys Identified Mail)

送信メールサーバーで作成した電子署名をもとに、受信メールサーバーが署名の検証を行うことで、メールの内容が改ざんされていないかを検証するための送信ドメイン認証技術のひとつである。
2024年2月以降、Googleアカウント宛に1日5000通以上送信するメールアカウントはSPFとDKIM、また後述のDMARCの導入が義務化された。

DKIM 認証処理の流れ

送信メールサーバー側の準備

  1. メールサーバー の管理者が公開鍵・秘密鍵のペアを作成
  2. 公開鍵はDNSサーバーのTXTレコードにDKIMレコードとして設定

メール送信時

  1. 送信メールサーバーはメールのヘッダー(From、Subject、Dateなど)と本文情報をもとにハッシュを作成
  2. そのハッシュを秘密鍵で電子署名(暗号化)する
  3. その結果をメールヘッダーに「DKIM-Signature」ヘッダーとして付与
    ※署名ヘッダーには以下の情報が含まれる
    • d=:署名者のドメイン名
    • s=:セレクタ名(DNS上の公開鍵の場所)
    • h=:署名対象にしたヘッダー一覧
    • b=:署名本体(Base64でエンコードされた署名)

メール受信時

  1. 受信側メールサーバーはメールを受け取った際に「DKIM-Signature」ヘッダーを検知すると、ヘッダー中の d=(ドメイン)と s=(セレクタ)を使って、送信者ドメインのDNSに問い合わせをし、公開鍵を取得
  2. 受信側メールサーバーが(送信メールサーバーと同様に)メールのヘッダー(From、Subject、Dateなど)と本文情報をもとにハッシュを作成
  3. 取得した公開鍵で b= の署名を復号し、そのハッシュと一致するかを確認
  4. 一致すれば DKIM認証が成功し、メールが改ざんされていないと判断される

DKIM署名が行われるのは、通常ヘッダーFromのドメインに対応する鍵ペアがサーバーに設定されている場合のみであり、ヘッダーFromのドメインと署名時のセレクタ(d=)が一致している必要がある(ただし攻撃者のサーバーの場合、ヘッダーFromが異なっていても署名するよう設定している可能性があるため、後述するDKIMアライメントでヘッダーFromとDKIMシグネチャーのd=が一致するかどうかを検証する必要がある)。
そのため、ヘッダーFromを別ドメインにしたメールを送信すると、送信メールサーバーでDKIMシグネチャーヘッダーが付与されないため、DKIM認証は有効にならない。
ただし、別ドメインの鍵ペアをサーバーに用意していれば、署名されるようになる。
※一部のMTA(Postfix + opendkimなど)では、送信者ドメインとDKIM署名対象ドメインが一致しない場合は署名を付けない設定になっていることがある

DKIMの種類

DKIMの電子署名には、メール送信者のメールサーバーで電子署名を付与する「作成者署名」と第三者のドメインで電子署名を付与する「第三者署名」があるが、「第三者署名」はそのままだと後述するDMARCでのDKIMアライメントのチェックに失敗するため、サーバーの調整が必要になる。

DMARC(ディーマーク、Domain-based Message Authentication, Reporting & Conformance)

SPFとDKIMの認証結果とその整合性チェック(アライメント – Alignment)を利用して、送信元ドメインの所有者が認証失敗したメールの取り扱いを定義する送信ドメイン認証技術のひとつである。
送信元メールアドレスのドメインの所有者が、自身のドメインを使ったメールが認証に失敗した場合にどう処理してほしいかを、受信側のメールサーバーに指示するためのポリシーであり、そのドメイン宛のメールに対する受信ポリシーではない。
ただし、受信側のメールサーバーやメールアドレスの設定によっては、指定されたポリシーに従われない可能性がある。

また、受信側のメールサーバーがDMARCチェックを行ったメールについて、集計結果をドメイン所有者に報告するDMARCレポート(Aggregate Reports/集計レポート)があり、受信メールサーバー(メールプロバイダー、たとえばGmail、Yahoo!、Microsoftなど)ごとに個別にXML形式で送付される。
送信頻度は受信側のメールサーバーで設定されており、デフォルトでは24時間に1回、UTCの0時(JST、日本時間では午前9時)ごろを基準に集計期間を区切ってレポートを送信している。

間違われやすいのが、DMARCは導入によって新しい認証処理(署名生成やDNS照会)が追加されるわけではなく、あくまでポリシーとアライメントを加えるレイヤーという位置づけであり、「判断基準」が追加されるという意味で、セキュリティの強化につなげる技術である。
そのため、SPFとDKIIMの使用が前提のため、単体では機能しない(少なくともどちらかが実装されている必要がある)。

より具体的には以下のような流れとなる。

  1. SPFやDKIMの結果確認
    既存のSPF/DKIMの認証結果の確認
  2. ドメインの整合性(アライメント -Alignment)の確認
    ヘッダーFromのドメインと、SPF/DKIMで認証されたドメイン(または設定によりサブドメイン)が一致しているかのチェック(これはSPF/DKIMにはないDMARC独自のチェックといえる)
  3. ポリシー適用
    none(監視のみ)/ quarantine(迷惑メール)/ reject(拒否)など、認証失敗時にどう扱うかの方針を受信側に示す
  4. レポート生成
    受信側サーバーが、SPF/DKIMの合否や整合性の結果を含んだレポートを送信する(rua/rufに記載のメールアドレスに送付)

実装方法

実装としては、DNSサーバーのTXTレコードに以下のような形式のDMARCレコードを追記するだけである。

_dmarc.example.com IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com;"

このようにDNSレコードにメールアドレスが記載されるため、外部から参照されても問題ないアドレスを指定する必要がある。
メールの送信先を複数指定したい場合はカンマ(,)で区切る必要がある。

一般的にはDMARCポリシーの開始時は

  • ポリシー(p)にnone(何もしない)を選択
  • rua(Reporting URI for Aggregate reports)で集計レポート、またはruf(Reporting URI for Failure data)でフォレンジックレポート(Forensic Reports – 失敗メールの詳細情報)、あるいは両方の送付先を設定

し、各レポートの内容をもとにして段階的にポリシーを厳しく(quarantine、reject)していくことが推奨されている。

フォレンジックレポートは失敗理由などの情報に加えて、そのメッセージ全体がレポートに含まれる場合がある。集約レポートと違い、プライバシー上の懸念から、失敗レポートを送信しないプロパイダーもある。

DMARCを導入するドメインとは別のドメインをruaやrufの送信先として指定する場合、そのドメイン側で次のようなDNSレコードを追加する必要がある。

<DMARCを導入しているドメイン名>._report._dmarc.<DMARCレポートの送付先ドメイン名>  IN  TXT  “v=DMARC1”

具体的にはDMARCを導入しているドメイン名を「example.com」、DMARCレポートの送付先ドメイン名を「hoge.com」とすると以下のようになる。

example.com._report._dmarc.hoge.com  IN  TXT  “v=DMARC1”

アライメント

アライメントとはメールに表示される送信元メールアドレス(ヘッダーFrom)が、SPFやDKIMで認証したドメインと一致するかを照合することである。

前述のとおり、SPFはエンベロープFrom(送信メールサーバーで設定される送信元アドレス、エンベロープは封筒の意)のドメインに対して、送信元メールサーバーのIPアドレスが送信を許可されているかを確認する技術である。
またDKIMはヘッダーFromを確認して用意している鍵ペアに適合するかどうかを確認してメールに電子署名を付与する技術である。
つまり、SPFとDKIMはヘッダーFrom(メールソフト側で確認できる送信元アドレス。エンベロープFromが封筒、つまり配達員が確認するメールアドレスでその中身は封筒を開けるユーザーのみが知るメールアドレスである)とエンベロープFromが一致しているかどうかを確認していない。

ヘッダーFromとエンベロープFromは第三者が無関係なドメインを詐称することができる(エンベロープFromはメール送信サーバーのポリシーによって、実際に送信できるアドレスが制限されていることが多い)ため、ヘッダーFromを詐称したなりすましメールが、エンベロープFromのドメインでSPFとDKIMの認証をPass(合格)させている場合、受信者側は不正なメールとして検知できない可能性がある。

そのため、アライメントという仕組みを利用してヘッダーFromとエンベロープFromが一致しているかを確認している。

アライメントには、SPFアライメント(ヘッダーFromのアドレスが、SPFで認証したエンベロープFromのドメインと一致するかをチェック)とDKIMアライメント(ヘッダーFromのアドレスが、DKM署名の「d=」で指定したドメインと一致するかチェックする)の2種類あり、DMARCに合格するためにはSPFとSPFアライメント、またはDKIMとDKIMアライメントのいずれかに合格する必要がある。

まとめると、以下のようになる。

  • SPF → Return-Path と From のアライメント
  • DKIM → d= と From のアライメント

※前述のとおり、DKIM署名が行われるのは、通常ヘッダーFromのドメインに対応する鍵ペアがサーバーに設定されている場合のみ(送信側のメールサーバーによる確認)であるが、設定によって別ドメインでも署名可能となるため、DKIMアライメントによってヘッダーFromと署名者(d=)が一致しているかを受信側のメールサーバー確認する必要がある

なぜヘッダーFromやエンベロープFromは詐称することができるのか

メールの規格(RFC 5322など)は、1970〜80年代に設計されたもので、当初は信頼された学術ネットワークでの利用が前提であり、「送信者の正当性を疑う必要がない」と考えられていたため、誰でも任意の「From」アドレスを設定できる柔軟性が必要とされていた。
またメーリングリスト、代理送信、CRMシステムなど、「本当の送信者」以外のアドレスをFromにする正当な理由も多く存在し、この仕様は「柔軟性」と「セキュリティ」のバランスの上に成り立っている。
送信者が完全に自由に設定できないようにすると、正当な用途まで制限されてしまうため、送信の自由は残しつつ、現在は認証で受信側が対策するという構造となっている。

ちなみに、Fromと同様、ヘッダーToとエンベロープToもあり、BCCは送信する宛先をエンベロープToのみに設定し、ヘッダToには設定しないことで受信者に他の宛先を見せずに送信することで実現されている。
またエンベロープFromはなんらかの原因でメールが宛先に届かなかった場合にそのアドレス宛にバウンスメール(エラーメール)を返送するようになっていたりなど、ヘッダーFromとエンベロープFromが分かれているのは、その送信の自由を担保するためであり、そのおかげでBCCや転送、代理送信などの柔軟なメール配信が可能となっている。

エンベロープFromとReturn-Pathの違い

ほとんど同じ意味で使用されるが、厳密な概念は微妙に異なっている。
エンベロープFromはSMTP通信中に使われる送信者アドレスのことで、メールの転送を担うMTA(Message Transfer Agent)が、メールサーバー上で自動的に付加している。
Return-Pathは受信者側のメールサーバーが受信後にヘッダーに追加するメールアドレスのことである。SMTP通信でメールが転送されている間はエンベロープFromの情報も一緒に転送されるが、宛先のメールサーバーへメールの配送が完了した段階で「エンベロープFrom」が破棄され、その内容が「Return-Path」へと変換されてメールヘッダ内に記載される。
そのため、受信したメールからエンベロープFromを確認する場合は、メール原文の「Return-Path」に続くメールアドレスを確認することでエンベロープFromを確認できるというわけである。

メールのリレーやエイリアス、一部のメール転送サービスを通ると、Return-Pathが途中で変更されることがあるが、SPFはReturn-PathではなくエンベロープFromのドメインでチェックされるため、違っていても通常は問題ないが、迷惑メール判定に影響することがある。

メール本文とドメインのクロール

メール本文がスパムくさいだけで迷惑メール判定される場合もある。
また、Googleなど検索エンジンを運用するベンダーの場合、ドメインがクロールされていないと迷惑メール判定されることもあることに留意する。