ブログ / エンジニアリング / No.015

レコードは正しいのに SPF・DKIM・DMARC が失敗する理由

すべて名前解決でき、チェックツールはすべて緑、それでもメールは迷惑メールに入る。他社のドメインで送信者認証を設定してきた中で踏んだ四つの失敗と、いずれもそれを見つけるはずのツールからは見えないという話。

Adam · Knockwire2026年8月11日9 エンジニアリング

この記事は英語版からの翻訳です。

送信者認証には少し変わった失敗の仕方がある。レコードは正しく、オンラインのチェックツールも正しいと言い、それでもメッセージは認証されていないものとして扱われる。これはチェックツールが「公開した内容そのもの」を検証するのに対し、受信側は「公開した内容とメッセージとの関係」を検証しているからだ。この二つは別の問いである。以下は、前者に「はい」と答えられながら後者に「いいえ」と答えられた四つのパターンで、いずれも自社ではないドメインに設定してきた経験から来ている。

01検証されるのはアラインメントであり、レコードではない

公開された SPF レコードは、あるサーバがあるドメインのために送信してよいことを示す。有効な DKIM 署名は、ある鍵がそのメッセージに署名したことを示す。どちらも、そのドメインが受信者に見えている From ヘッダのドメインと同じであるとは言っていない。そして DMARC が評価するのはその一点だけである。

つまりすべてのメッセージには二つのドメインがあり、多くのツールはその片方しか見せない。見えている From のドメインは受信者が読むものだ。SPF が実際に照合される Return-Path のドメインは送信を行う側が決めるもので、既定ではそれは事業者側になる。事業者のホスト名に対して SPF が完璧に通りながら DMARC は失敗として記録されることがあり、それは自分のものではないドメインに対して SPF が通ったからだ。

DMARC は二つのうち片方が揃っていれば足りる。ここが理解しておく価値のある部分だ。独自の Return-Path による SPF のアラインメント、あるいは自ドメインを含む署名による DKIM のアラインメント、どちらか一方でよい。SPF が緑に見えていても失敗する理由はこれであり、SPF の問題に見えたものが DKIM を直すと解決することが多い理由もこれである。

チェックツールは公開した内容を検証する。受信側は、公開した内容が From 欄のアドレスと関係があるかどうかを検証する。

02違うアドレスを返すプロキシされた CNAME

これが最も時間を奪われたもので、四つの中で最も説得力のある偽の成功を生む。認証用のレコードはたいてい事業者のゾーンへの CNAME である。プロキシ機能を持つ DNS では CNAME に通信をプロキシ経由にする印を付けられ、プロキシされたレコードは参照先を返さない。エッジのアドレスを返す。それがその機能の目的そのものだからだ。

ウェブサイトにとってそれは正しい挙動であり、人々がその機能を使う理由でもある。しかし DKIM のセレクタにとっては、特定の意味で致命的になる。参照は成功するのだ。名前は解決され、何かが応答し、どこにもエラーは出ない。返ってくるのは鍵があるはずの場所にあるアドレスレコードなので、検証側は鍵を見つけられず、そのメッセージを署名なしとして扱う。この一連の流れは、外から見て設定ミスには少しも見えない。

これが繰り返し起きるのは、既定値が一般的な用途に合わせてあるからだ。ゾーンに追加されるレコードの大半はサイト向けであり、通常はそれが望まれるので画面はプロキシを提案する。認証用のレコードは例外であり、しかもそれを追加するのは、自分の DNS 事業者が独自に用意したトグルについて何も書いていない手順書に従っている人である。

まず確認すべきことDKIM が失敗しているなら、ほかを見る前にセレクタを名前解決し、返ってきたレコードの種類を見ること。TXT が返ればチェーンは無事である。アドレスレコードが返れば、その名前はプロキシされていて到達できる鍵は存在しない。DNS の画面に何が表示されていようと関係ない。

03渡されたセレクタはすでに使われている

DKIM のセレクタは、一つのドメインが複数の鍵を同時に持てるようにするためのラベルである。事業者は既定値を決め、これまで発行したすべてのアカウントでそれを使い回す。あるドメインが同じ事業者と二つの関係を持つまでは、それで何の問題もない。

私たちが認証しているドメインの一つが、生きた実例になっている。その事業者は既定で s1 と s2 を割り当てるが、そのドメインには私たちより前のアカウントによってすでに両方が公開されていた。既定値を受け入れていたら、私たちのレコードは自分たちが管理していないドメイン上で稼働中のレコードと衝突し、その障害は他人のメールが壊れるという形で現れていた。別のセレクタを使っているのは、まさにこのためである。

一つ目の罠の内側にもう一つの罠があり、それは二つ目の鍵が発行されたときにしか表に出ない。事業者は二つ目のセレクタを、一つ目に数字を足して作ることが多い。すでに数字で終わるセレクタを選ぶと、手に入る組み合わせは想定したものとは違うものになる。私たちは末尾に数字を持たない名前を選んだが、その判断は文書ではなく実際の API に対して挙動を確認したうえでのものだ。

  • 何かを追加する前に、そのドメインに対して事業者の既定セレクタを引くこと。既存のレコードがあるなら、誰も教えてくれなかった既存の関係があるということだ。
  • 一つのドメインにメール事業者は一つ、と決して思い込まないこと。マーケティング、トランザクション、サポート、そして引き継がれた古い契約で、関係は四つ、事業者も四社ということはよくある。
  • 年や連番ではなく、送信者が分かるセレクタを選ぶこと。後からそのゾーンを監査する人にとって、DNS 上で読める情報になる。

04事業者のホスト名を指すと、それは自分のレコードではなく相手のレコードになる

これは当日の失敗ではなく、十八か月後の失敗である。そして私たちのレコードが、多くのサービスが配るものと違う形をしている理由でもある。

事業者は自社ゾーンへの CNAME を渡してくる。それをそのまま顧客に渡すのが分かりやすい方法で、実際すぐに動く。同時にそれは、自分が管理していないゾーンの中に事業者のホスト名を、顧客ごとに一つずつ置くことでもある。事業者を変えるとは、そのとき全顧客に DNS の編集を依頼することであり、実際には一定数はそれを行わず、静かに認証されなくなる。

そこで私たちは、顧客のレコードを自社のホスト名に向け、そのホスト名を事業者に向けている。一段増えるコストは名前解決一回分で、移行作業は一斉メールではなく自社ゾーンの三レコードの変更になる。実際のチェーンは、顧客のセレクタ、次に私たちの別名、次に事業者の参照先という順に読める。事業者の CNAME がやっていることと同じで、役に立つ唯一の場所に一段の間接参照を足しただけである。

この設計の代償は、新しい間違え方が一つ増えることであり、隠すより名指ししたほうがよい。事業者の参照先には、約束ではなく割り当てにすぎない識別子が含まれていて、その中には変わりうるプール識別子がある。それが変われば私たちの別名は役に立たない先を指し、すべての顧客が一斉に、しかも静かに認証されなくなる。レコード自体は解決し続けるからだ。私たちがこのずれを定期的に監視しているのは、ほかのすべてを監視しているのと同じ理由である。内側からは見えない失敗だからだ。

05ワンクリックは事業者の判断であって、標準ではない

顧客に三つのレコードの追加を頼むところで導入は止まる。その標準的な答えが Domain Connect である。顧客は自分の DNS 事業者に送られ、その事業者が本人確認を行い、書き込まれるレコードを見せ、同意した場合にだけ書き込む。誰も誰にも認証情報を渡さない。

読み違えやすいのは、テンプレートを公開すると何が手に入るのかという点だ。公開テンプレートのリポジトリに取り込まれることは必要だが十分ではない。事業者はテンプレートを個別に取り込むからである。テンプレートが何年も公開され、しかも正しいまま、ある DNS 事業者では一度も提供されていないということが起こりうる。

よく知られた配信事業者のテンプレートは 2022 年から上流に取り込まれている。それを今日ある大手 DNS 事業者に問い合わせると 404 が返る。つまりその事業者の顧客は今も手作業でレコードを追加しているということだ。私たちは想定する前に確認した。想定していたら、どこにもつながらないボタンを顧客に見せることになっていた。

ここまでのすべてに共通する形がこれである。ボタンを出す前に、その事業者がテンプレートを提供しているか尋ねる。画面を信じる前に、レコードを解決してその種類を読む。既定値を受け入れる前に、そのドメインに対してセレクタを引く。いずれの確認も一回の参照で済み、それを省くと、何も届けていないのに成功と報告するシステムができあがる。

私たちがしないことここまでのどれも、顧客のゾーンの認証情報を預かることを必要としない。自社ゾーン以外の API キーは一つも持っておらず、ワンクリックの流れはまさにそれを必要としないための設計である。事業者がテンプレートを取り込んでいない場合は、手で追加するための三つのレコードを表示する。こちらは常に機能する。

まとめると、認証とはメッセージとドメインの関係であり、上に挙げた失敗はいずれもレコードの記述ミスではなく、その関係の断絶である。だからレコードは正しく見える。実際に正しいのだ。ただ、検証されている対象とつながっていないだけであり、それを確実に知る唯一の方法は、自分が公開したものを名前解決し、実際に返ってくるものを読むことである。

Knockwire はウェブを読み、決して購入しない企業を除外し、購入しうる企業の窓口だけをノックします。自社ドメインで実行し、自分の見送り記録を確認してください。

自社サイトで試す記事一覧