必見の記事

突貫でおぼえるSPF、DKIM、DMARC

2024.01.28

しばたです。

昨年10月にGoogle(Gmail)および米国Yahoo!においてスパム対策の強化がアナウンスされました。
この件に関してつい先日まで他人事でいたのですが、実は全然他人事では済まないことが発覚し突貫で知識を仕入れています。

アナウンスに対する具体的な対応策についてはこちらのZennの記事を見れば全部わかる感じです。
最高ですね。

また、メール送信にAmazon SESを使っている場合はAWSのブログを確認すると良いでしょう。

「これらの記事を読み解けば万事解決!」という感じではあるのですが、私自身が学んだなかで予め知っておくと良さそうに思えた点がいくつかありました。
本記事ではその辺を共有するのと、実際にAmazon SESの環境を作って動作確認をしたのでその結果も合わせて共有します。

はじめに覚えておくと良い基礎知識

Zennの記事でも詳細な解説がありますが、個人的に「最初にこの辺の知識を持っておくとより理解が進む」と思った点を書いていきます。

※注意事項※
本節の内容について、正確さを保証できない状態で公開しつづけることは問題があると判断し一部記述を取り下げました。申し訳ございません。

1. 2つのFromアドレス

最初にメール送信において2種類のFromアドレスがある点を強く意識しておく必要があります。

詳細はインターネット上いたるところにあるので箇条書きで済ませますが、SPF・DKIM・DMARCそれぞれの技術を語る際に「どのFromアドレスの話をしているか?」を押さえておくことが重要です。

  • ヘッダFrom
    • 読み手に送り主を伝えるためのFromアドレス
    • 送り主が自由に設定可能
      • 悪意をもって詐称されうる
    • メール受信者はヘッダ中の「From」で確認できる
  • エンベロープFrom
    • メールサーバーが使うFromアドレス
    • 基本的にシステムの都合で設定されるが変更可能
      • 悪意をもって詐称されうる
    • メール受信者はヘッダ中の「Return-Path」で確認できる

2. SPF

こちらに関して内容を取り下げました。
Zennの記事の方でご確認ください。

Amazon SESでの例

実例として、Amazon SESの初期設定状態ではエンベロープFromはamazonses.comドメイン(より正確にはサブドメイン)のアドレスとなります。
こちらはAWS所有のドメインでありAWSによりSPFの設定がなされています。

# amazonses.com ドメインのTXTレコードからSPFの設定がされているものをチェック
$ dig amazonses.com TXT +short | grep spf
"v=spf1 ip4:199.255.192.0/22 ip4:199.127.232.0/22 ip4:54.240.0.0/18 ip4:69.169.224.0/20 ip4:23.249.208.0/20 ip4:23.251.224.0/19 ip4:76.223.176.0/20 ip4:52.82.172.0/22 ip4:54.240.64.0/19 ip4:54.240.96.0/19 ip4:76.223.128.0/19 ip4:216.221.160.0/19 -all"

このためAmazon SESを使えば自動的にSPF認証は通るわけですが、「amazonses.comドメインが使われることが正しい」のかはSPFだけだと分かりません。

ここをカバーする仕組みとしてカスタム MAIL FROM ドメインがあり、こちらについては後述します。

補足 : SPFレコードとTXTレコード

かつてSPFの設定には専用のSPFレコード (Type 99)がありましたが現在は非推奨です。
SPFの設定はTXTレコード (Type 16)に設定します。

Route 53だと「SPFレコードは非推奨」と警告してくれます。

3. DKIM

こちらに関して内容を取り下げました。
Zennの記事の方でご確認ください。

補足 : DKIM ADSPは非推奨

DKIM署名ドメインをチェックする仕組みとしてDKIM ADSPというものがありましたが今は使われていません。
DMARCが事実上の後継となっています。

(2013年11月にHISTORICになった模様)

4. DMARC

DMARC(Domain-based Message Authentication, Reporting & Conformance)は次に述べるアライメントを含めた認証と認証に失敗したメールの扱いやレポーティングを定義する仕組みです。

DMARCの設定はドメインのTXTレコードに所定の内容を記述します。
レコードのホスト名は「_dmarc.ドメイン」にする必要があります。

# 最低限のDMARC設定例
$ dig _dmarc.example.shibata.tech TXT +short
"v=DMARC1; p=none"

また、デフォルトでサブドメインに対しても設定が継承されます。

アライメント

SPFとDKIMでは

  • SPF : エンベロープFromの詐称チェック
  • DKIM : メールの改ざんチェック (ヘッダFromの改ざんチェック含む)

までできるものの、ドメインの正しさまではチェックできておらずヘッダFromの詐称は可能です。
このため出てくるのが「アライメント」であり、SPFとDKIMで使われるドメインの一致をチェックします。

SPFの場合は「ヘッダFromのドメイン」と「エンベロープFromのドメイン」が一致しているかをチェックします。
DKIMの場合は「ヘッダFromのドメイン」と「署名に使われたドメイン」が一致しているかをチェックします。
それぞれの認証で使われるドメインが一致していればなりすましでは無いという判断です。

ドメインの一致ついて、サブドメインでも一致として扱う緩和(Relaxed)モードと完全に同一ドメインでないと一致と見做さない厳格(Strict)モードがあります。
どちらのモードにするかは設定可能であり、デフォルト値は緩和(Relaxed)モードです。

とりあえずは「デフォルトだとサブドメインでもOK」とだけ覚えておけば良いでしょう。

DMARC認証

DMARCではこれまでのSPF、DKIMに対しアライメントを加え、

  • SPF認証
  • SPFアライメント
  • DKIM認証
  • DKIMアライメント

の4つをチェックしその結果に応じて合否を判定します。

基本的には

「SPF認証に合格し、SPFアライメントも一致している」

または

「DKIM認証に合格し、DKIMアライメントも一致している」

のどちらかを満たす

とDMARC認証に合格します。
どちらか、なのでDMARC認証に合格しても部分的に不備が残っている可能性があるのは要注意ポイントです。

より具体的な話はこちらの記事をご覧いただくと良いでしょう。

認証失敗時の扱いやレポーティング

DMARCは認証の仕組みであるものの、ほとんどの設定が認証失敗時の扱いやレポーティングに関するものです。
どの様な設定と運用をすべきかについてはこちらの記事が参考になると思います。

どこまで目指せば良いのか?

Googleと米国Yahoo!のアナウンスでは1日当たりのメール送信件数によって必要な対応が変わっていますが、ことSPF・DKIM・DMARCについては「原則全部やる」様にしてください。
要は

  • SPF認証
  • SPFアライメント
  • DKIM認証
  • DKIMアライメント

全部クリアしましょうという事です。
最低限必要なのは

  • SPF認証に合格する
  • DKIM認証に合格する
  • DMARC認証に合格する (アライメントに不一致があっても許容)

です。

Amazon SESで確認してみた

ここからはAmazon SES環境を用意して実際に試した結果を共有します。

構築した環境

私の検証用AWSアカウントの東京リージョンで私の個人ドメインexample.shibata.techで検証済みの環境を用意しました。

現在のAmazon SESはドメインの検証にDKIM用のTXTレコードを兼用しているので新規作成時にDKIM署名が有効になりますが、今回は動作確認のため敢えて初期状態をDKIM署名無効にしています。

本番環境では必ずDKIM署名を有効にしてください。

1. DMARCレコードの設定

最初にDMARCの設定をしておきます。
これはDNSに所定のレコード(今回は_dmarc.example.shibata.tech)を設定するだけです。

今回は最低限の"v=DMARC1; p=none"という設定にしています。

設定結果をdigコマンドで確認するとこんな感じです。

$ dig _dmarc.example.shibata.tech TXT +short
"v=DMARC1; p=none"

2. DKIM署名無効の場合

ここから条件を変えてテストメールを送っていきます。
最初はDKIM署名を無効にした状態で試します。

テストメールの内容はこんな感じでヘッダFrominfo@example.shibata.techから私用Gmailアドレスへ単純な文章を送っています。

Amazon SESのサンドボックス解除はしておらず、あらかじめ私用Gmailアドレスを認証済みにしています。

結果はこんな感じで「amazonses.com経由」のメールとして扱われます。

ソースを確認するとこんな感じでした。

DKIM署名を無効にしたので「署名なし」で失敗するのかと思っていたのですがamazonses.comドメインで署名され合格していました。
ヘッダFromがexample.shibata.tech、署名がamazonses.comなのでDKIMアライメントは不一致です。

# メールヘッダから抜粋 : d=amazonses.com とamazonses.comの署名になっている
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=zh4gjftm6etwoq6afzugpky45synznly; d=amazonses.com; t=1706330360; h=From:To:Subject:MIME-Version:Content-Type:Message-ID:Date:Feedback-ID; bh=bClo6lqiWB9e7Rp4KOIG9kopwkxS0mCJfMPNsIb6MKE=; b=bJe0fT1lDwa91oI25r91JqNYjIgD9pmkggWHrgRNDUDacSDbokbfBNeFbz8GZ0YU

SPFについてはエンベロープFromがamazonses.comのサブドメインとなっており、amazonses.comでSPFに合格しています。
ヘッダFromがexample.shibata.tech、エンベロープFromがamazonses.comなのでSPFアライメントは不一致です。

# メールヘッダから抜粋 : ap-northeast-1.amazonses.com ドメイン
Return-Path: <0106018d4937097f-a150a3df-9717-4ddd-bf0d-1a01880b7225-000000@ap-northeast-1.amazonses.com>

DMARC認証についてはSPFアライメント、DKIMアライメント両方とも不一致のため不合格となります。
全体をまとめると以下の通りとなります。

項目 結果
SPF認証 PASS (amazonses.com)
SPFアライメント FAIL
DKIM認証 PASS (amazonses.com)
DKIMアライメント FAIL
DMARC認証 FAIL

3. DKIM署名有効の場合

次にDKIM署名を有効にした状態でテストメールを送信します。

テストメールの内容はこんな感じで、件名と本文をちょっと変えただけです。

結果はこんな感じになりました。

「amazonses.com経由」の記載が無くなり、DKIMの署名がexample.shibata.techになりました。
これでヘッダFromと署名がexample.shibata.techとなりDKIMアライメントが一致します。

# メールヘッダから抜粋 : d=example.shibata.tech とexample.shibata.techの署名が増えた
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=3mydn3arvwxyropk2ignunny36oahouv; d=example.shibata.tech; t=1706330546; h=From:To:Subject:MIME-Version:Content-Type:Message-ID:Date; bh=CWm3VBWG8DdEKWYFbed4siCDAZ+jo/VGiAldaSWlChY=; b=EPCPcBsvZwhWM・・・(後略)・・・

SPFについてはエンベロープFromがamazonses.comサブドメインのままなので、SPF認証に合格し、アライメントは不一致となります。

# メールヘッダから抜粋 : ap-northeast-1.amazonses.com ドメイン
Return-Path: <0106018d4939e085-c493f12b-e0fa-44b9-807e-682ac9199c5e-000000@ap-northeast-1.amazonses.com>

DKIMのアライメントが一致したためDMARC認証は合格となります。
まとめると以下の通りです。

項目 結果
SPF認証 PASS (amazonses.com)
SPFアライメント FAIL
DKIM認証 PASS (example.shibata.tech)
DKIMアライメント PASS
DMARC認証 PASS

4. カスタムMAIL FROMドメインを設定した場合

ここまでamazonses.comドメインでSPF認証に合格しているものの、SPFアライメントは不一致のままです。
そこで「カスタムMAIL FROMドメイン」を設定し、エンベロープFromアドレスを変えてアライメントを一致させてやります。

マネジメントコンソールから「編集」ボタンをクリックして内容を設定していきます。

この機能ではエンベロープFromのドメインをexample.shibata.techの任意のサブドメインに指定可能です。
今回はsesmail.example.shibata.techというサブドメインにしています。
MX障害時の動作は環境に応じて設定してください。

変更を保存すると保留中の状態となり、専用のMXレコードとTXTレコード(SPF用)の登録を求められます。
これらを設定することにより実体はAmazon SESだけどあたかも自ドメインからメールを送る体にするわけです。

両レコードを登録して少し待つと状態が「成功」に変わり設定完了となります。

設定結果をdigコマンドで確認するとこんな感じです。

# 検証後 : 実体はAmazon SESだが、あたかもsesmail.example.shibata.techが独自のメールサーバかの様な設定に
$ dig sesmail.example.shibata.tech MX +short
10 feedback-smtp.ap-northeast-1.amazonses.com.

$ dig sesmail.example.shibata.tech TXT +short
"v=spf1 include:amazonses.com ~all"

この状態で下図のテストメールを送ります。

結果はこの様になりました。

これでエンベロープFromがsesmail.example.shibata.techドメインのアドレスに変わります。
sesmail.example.shibata.techのSPFレコードも設定済みなのでSFP認証に合格し、SPFアライメントも一致します。

# メールヘッダから抜粋 : sesmail.example.shibata.tech ドメイン
Return-Path: <0106018d493c547d-3a8ae3f7-5591-4e26-871f-abd27a2d182b-000000@sesmail.example.shibata.tech>

DKIMについては前節から変えていないので認証に合格しアライメントも一致した状態です。
まとめると以下となり、これで全ての要素を合格させることができました。

項目 結果
SPF認証 PASS (sesmail.example.shibata.tech)
SPFアライメント PASS
DKIM認証 PASS (example.shibata.tech)
DKIMアライメント PASS
DMARC認証 PASS

ちなみにIPアドレス23.251.234.5を逆引きするとAmazon SESのホスト名が返され、逆引きレコードの厳密な一致まではしていません。
(とはいえ、そこまで求められることは現実的に無いはず...)

# 逆引きの結果は amazonses.com となる
$ dig -x 23.251.234.5 PTR +short
e234-5.smtp-out.ap-northeast-1.amazonses.com.

# 正引きもできるので FCrDNS は対応ずみ
$ dig e234-5.smtp-out.ap-northeast-1.amazonses.com. +short
23.251.234.5

5. 補足 : カスタムMAIL FROMドメインを設定 + DKIM署名無効の場合

補足としてカスタムMAIL FROMドメインを設定しつつ、DKIM署名を無効にした場合の結果も共有します。
テストメールはこんな感じ。

結果はこの様になりました。

カスタムMAIL FROMドメイン設定済みなのでSPF認証に合格しSPFアライメントも一致しています。
DKIMはamazonses.comドメインで署名されるため、認証に合格するもアライメントは不一致となります。

DMARC認証はSPFのアライメントが一致していることにより合格となります。

項目 結果
SPF認証 PASS (sesmail.example.shibata.tech)
SPFアライメント PASS
DKIM認証 PASS (amazonses.com)
DKIMアライメント FAIL
DMARC認証 PASS

リンク集

本記事を書くにあたり参考にしたサイトの一覧です。(順不同)

最後に

以上となります。
突貫の割に長くなってしまいました...

がんばってまとめてみたものの、まだあまり自信がないところもあります。
記載内容に間違いがあれば随時更新するつもりです。

本記事の内容が少しでも誰かの役に立てば幸いです。

追記

追記1

Twitter(現X)で内容の誤りをご指摘いただいたので一部修正しています。

  • SMTPコマンドに関する記述は削除しました。
  • SPFの説明に関して内容を修正しました。
  • DKIMの説明に関して内容を修正しました。
  • アライメントに対し「調整」の訳を付けたのはGoogleのサイトなどで使われているのを見てのことだったのですが、こちらについては「アライメント」の表記だけにする様にしました。
  • アライメントの説明に関して文章の構成を見直しました。

ありがとうございました。

追記2

正確さを保証できない状態で公開し続けるのは問題があると判断し、SPFとDKIMの記述に関して一部内容を取り下げました。