サイトアイコンmaita tomoya dev io

#69 なりすましメールを防ぐSPF・DKIM・DMARCの仕組みをゼロから解説

なりすましメールを防ぐSPF・DKIM・DMARCの仕組みをゼロから解説

自分のWebサービスからメール通知を送る。一見シンプルですが、その裏には「このメールは本当にあなたが送ったものですか?」という認証の仕組みが必要です。

この記事では、Webサービス開発でメール送信機能を実装する際に避けて通れないSPFDKIMDMARCについて、手紙の郵送にたとえながら解説します。

この記事のゴール

  • メール認証(SPF/DKIM/DMARC)が「なぜ必要か」を理解できる
  • 各技術が「何をしているか」をイメージできる
  • 実際のDNSレコードを見て「何が書いてあるか」を読めるようになる
  • 公式ドキュメントを読むための前提知識が身につく

目次

  1. そもそもなぜメール認証が必要なのか
  2. メール送信の仕組み(超基本)
  3. SPFとは
  4. DKIMとは
  5. DMARCとは
  6. 3つの関係をまとめる
  7. 実践: Resend + Cloudflareでメール認証を設定する
  8. DNSレコードを読んでみよう
  9. よくある疑問
  10. まとめ

1. そもそもなぜメール認証が必要なのか

メールは「送信者を偽れる」仕組みで動いている

これは意外かもしれませんが、メールの送信プロトコル(SMTP)は、送信者のアドレスを自由に書き換えられるようにできています。

紙の手紙を思い浮かべてください。封筒の「差出人」欄に何を書くかは、書く人の自由ですよね。「東京都千代田区 田中太郎」と書いても、実際に田中太郎さんかどうかは誰も確認しません。

メールもまったく同じです。From: support@amazon.co.jp と書いてメールを送ることは、技術的には誰にでもできてしまいます。

なりすましメールの被害

この仕組みを悪用したのが**なりすましメール(スプーフィング)**です。

From: support@your-bank.co.jp
件名: 【重要】お客様のアカウントが凍結されました

以下のリンクからログインして確認してください。
https://fake-bank-site.com/login  ← 偽サイト

受信者はメールの差出人を見て「銀行からのメールだ」と思い込み、偽サイトにパスワードを入力してしまいます。これがフィッシング詐欺です。

Webサービス開発者にとっての問題

あなたが開発したWebサービスからメールを送る場合、2つの問題が発生します。

問題説明
迷惑メールに振り分けられる認証がないメールはGmailやOutlookに「怪しいメール」と判断される
ドメインが悪用される認証がないと、第三者があなたのドメインを使って偽メールを送れてしまう

SPF・DKIM・DMARCは、この両方の問題を解決する仕組みです。


2. メール送信の仕組み(超基本)

メール認証を理解するために、まずメールがどう送られるかを簡単に見ましょう。

送信者のアプリ
    |
    v
[送信メールサーバー(SMTP)] ← 「このサーバーからメールを送るよ」
    |
    v
  インターネット
    |
    v
[受信メールサーバー] ← 「このメール、本物?」
    |
    v
受信者のメールボックス(Gmail等)

受信メールサーバーが「このメール、本物?」と判断するときに、**DNS(Domain Name System)**に設定された情報を参照します。

DNSとは?

DNSは「インターネットの電話帳」です。ドメイン名(例: locatripjapan.com)に対して、さまざまな情報を紐づけて公開できます。

DNSレコードの種類役割
AドメインのIPアドレス93.184.216.34
MXメールの送り先サーバーmail.example.com
TXTテキスト情報(何でも書ける)SPFやDKIMの設定もここ
CNAME別のドメインへの転送alias.example.com

SPF、DKIM、DMARCの設定は、主にTXTレコードとしてDNSに登録します。


3. SPFとは

一言で言うと

「このドメインからメールを送っていいサーバーの一覧表」 をDNSに公開する仕組み。

手紙にたとえると

あなたの会社(example.com)の受付に「郵便物を出していいのは、郵便局Aと宅配便Bだけです」という掲示を出すようなもの。

受け取った側は、掲示を確認して「この手紙は郵便局Aから来ている。OK、本物だ」と判断できる。

仕組み

1. 送信サーバー(IP: 203.0.113.5)が hello@example.com からメールを送信
2. 受信サーバーが example.com のDNSを問い合わせる
3. TXTレコードに「v=spf1 ip4:203.0.113.5 ~all」が見つかる
4. 送信サーバーのIP(203.0.113.5)が許可リストに含まれている → OK!

SPFレコードの読み方

v=spf1 include:amazonses.com ~all
部分意味
v=spf1「これはSPFレコードです」という宣言
include:amazonses.comAmazon SES(メール送信サービス)のサーバーを許可
~all上記以外のサーバーからのメールは「怪しい」と判定(ソフトフェイル)

~allの種類:

記述意味厳しさ
+all全て許可緩い(非推奨)
~all許可リスト以外は怪しいと判定標準的
-all許可リスト以外は拒否厳しい

SPFの限界

SPFには1つ大きな弱点があります。メールが転送されると壊れることです。

メールが別のサーバーを経由して転送されると、送信元のIPアドレスが変わってしまい、SPFチェックに失敗します。この弱点を補うのがDKIMです。


4. DKIMとは

一言で言うと

「メールに電子署名(ハンコ)を押して、改ざんされていないことを証明する」 仕組み。

手紙にたとえると

あなたの会社が持つ特別な印鑑(秘密鍵)で封蝋をして手紙を送る。

受け取った側は、あなたの会社が公開している印鑑の型(公開鍵)と照合して「確かにこの会社が封をした手紙だ。途中で開けられてもいない」と確認できる。

仕組み

DKIMは公開鍵暗号方式を使っています。

[送信側]
1. メールの内容からハッシュ(指紋)を生成
2. 秘密鍵でハッシュを暗号化(= 電子署名)
3. 署名をメールヘッダーに添付して送信

[受信側]
4. DNSから送信者の公開鍵を取得
5. 署名を公開鍵で復号してハッシュを取り出す
6. メール本文から同じ方法でハッシュを生成
7. 2つのハッシュを比較 → 一致すれば本物!

公開鍵暗号方式とは?

少し脱線しますが、DKIMの根幹なので簡単に説明します。

鍵が2つ1組になっている暗号方式です。

誰が持つ役割
秘密鍵送信者だけが持つ署名を作る(暗号化)
公開鍵誰でも見られる(DNS)署名を検証する(復号)

イメージとしては:

  • 秘密鍵 = 自分だけが持つ印鑑
  • 公開鍵 = 印鑑証明書(誰でも役所で取得できる)

秘密鍵で押した印鑑は、公開鍵(印鑑証明書)で「本物の印鑑だ」と確認できます。逆に、公開鍵からは秘密鍵を作れないので、偽造は不可能です。

DKIMレコードの読み方

resend._domainkey.locatripjapan.com TXT "p=MIGfMA0GCSqGSIb3DQEBA..."
部分意味
resend._domainkeyセレクタ名。どのサービスの鍵かを区別する
_domainkey「これはDKIM用の公開鍵です」という目印
p=MIGfMA0...公開鍵の本体(Base64エンコード)

SPFとDKIMの違い

項目SPFDKIM
検証対象送信サーバーのIPアドレスメール本文の内容
たとえ「誰が郵便を出していいか」の許可リスト「封蝋」で中身が改ざんされていないことを証明
転送に強い?弱い(IPが変わると壊れる)強い(署名はメールに付いたまま)
設定場所DNS TXTレコードDNS TXTレコード

SPFとDKIMは補い合う関係です。 どちらか一方ではなく、両方設定するのが基本です。


5. DMARCとは

一言で言うと

「SPFとDKIMの結果をどう扱うか」のルールを公開する仕組み。

手紙にたとえると

「もし印鑑(DKIM)も郵便許可(SPF)も確認できなかった手紙が届いたら、捨ててください。そして、怪しい手紙があったら admin@example.com に報告してください」

という指示書を受付に貼り出すようなもの。

DMARCの3つの役割

  1. SPFとDKIMの結果に基づいてメールをどう処理するか指定する
  2. レポートを受け取れる(誰があなたのドメインでメールを送っているか把握)
  3. SPFとDKIMを「束ねる」ポリシーとして機能する

DMARCレコードの読み方

_dmarc.example.com TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"
部分意味
v=DMARC1「これはDMARCレコードです」という宣言
p=quarantine認証に失敗したメールの処理方法
rua=mailto:...レポートの送り先メールアドレス

p=(ポリシー)の種類:

意味厳しさ
none何もしない(監視のみ)緩い(最初はこれ推奨)
quarantine迷惑メールフォルダに振り分け中間
reject受信を拒否厳しい

6. 3つの関係をまとめる

メールが届いた!
    |
    v
[SPFチェック] → 送信サーバーは許可リストに入っている?
    |
    v
[DKIMチェック] → 電子署名は正しい? 内容は改ざんされていない?
    |
    v
[DMARCチェック] → SPFとDKIMの結果を踏まえて、どう処理する?
    |
    ├── 両方OK → 受信トレイへ
    ├── 片方失敗 → DMARCポリシーに従う(quarantineなら迷惑メールへ)
    └── 両方失敗 → DMARCポリシーに従う(rejectなら受信拒否)

3つのまとめ表

技術役割たとえ設定場所
SPF送信サーバーの許可リスト「郵便を出していいのはこの業者だけ」DNS TXTレコード
DKIMメールの電子署名「封蝋」で改ざん防止DNS TXTレコード + 送信サーバー
DMARCポリシーとレポート「怪しい手紙の処理方法を受付に指示」DNS TXTレコード

7. 実践: Resend + Cloudflareでメール認証を設定する

ここからは、実際にWebサービスのメール送信で設定した手順を紹介します。

背景

筆者は海外旅行者向けのカスタム旅行プランサービスを開発しています。ユーザーへのメール通知にメール送信サービスResendを使用し、ドメイン管理にはCloudflareを使っています。

なぜこの設定が必要?

Resendのデフォルトでは onboarding@resend.dev というテスト用アドレスからメールが送られます。これは開発中は問題ありませんが、本番運用では以下の問題があります。

  • 受信者に「知らないアドレスからのメール」と不信感を与える
  • Gmailなどで迷惑メールに振り分けられやすい
  • ブランドの信頼性が損なわれる

自分のドメイン(例: hello@locatripjapan.com)から送信するには、ドメインの認証が必要です。

設定手順

ステップ1: Resendにドメインを追加

Resendダッシュボードの Domains > Add Domain で自分のドメインを追加します。

ステップ2: 表示されたDNSレコードを確認

Resendが3つのDNSレコードを表示します。

TypeName役割
TXTresend._domainkeyDKIM公開鍵(メールの署名検証用)
MXsendメールの送信経路(Resendのサーバー)
TXTsendSPF(送信サーバーの許可リスト)

ステップ3: CloudflareにDNSレコードを追加

Resendが Auto configure オプションを提供している場合、ワンクリックで自動設定されます。Cloudflareを利用している場合はこれが最も簡単です。

手動の場合は、Cloudflareダッシュボードの DNS > Records > Add record から、Resendが表示した3つのレコードを1つずつ追加します。

注意: Proxy status(プロキシ状態)は DNS only(グレーの雲マーク)にしてください。メール関連のDNSレコードはCloudflareのプロキシを通すと正常に動作しません。

ステップ4: Resendでドメイン認証を確認

DNSレコード追加後、Resendのダッシュボードでドメインのステータスが Verified に変わります。DNS反映に最大48時間かかることがありますが、Cloudflareの場合は通常数分で完了します。

ステップ5: アプリケーション側の設定

メール送信元アドレスを環境変数で管理し、本番では認証済みドメインを使用します。

// 環境変数で送信元を管理(本番はカスタムドメイン、開発はResendテスト用)
const FROM_EMAIL = process.env.FROM_EMAIL || 'App <onboarding@resend.dev>'
# .env(本番)
FROM_EMAIL=LocaTripJapan <hello@locatripjapan.com>

8. DNSレコードを読んでみよう

実際に設定したDNSレコードを1つずつ読み解いてみましょう。

DKIM(TXTレコード)

Type:    TXT
Name:    resend._domainkey
Content: "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD8Zi..."
  • resend = セレクタ名(Resendが使う鍵の識別子)
  • _domainkey = 「DKIM用の公開鍵」を示す決まり文句
  • p=MIGf... = 公開鍵そのもの(Base64エンコードされたRSA公開鍵)

受信サーバーはこの公開鍵を使って、メールに付いた署名を検証します。

SPF(TXTレコード)

Type:    TXT
Name:    send
Content: "v=spf1 include:amazonses.com ~all"
  • send = サブドメイン(send.locatripjapan.comからメールを送る設定)
  • v=spf1 = SPFバージョン1
  • include:amazonses.com = Amazon SES(Resendが内部で使っているメール配信基盤)のサーバーを許可
  • ~all = それ以外は「怪しい」として扱う

MX(MXレコード)

Type:     MX
Name:     send
Content:  feedback-smtp.ap-northeast-1.amazonses.com
Priority: 10
  • MX = メールの配送先を指定するレコード
  • send = send.locatripjapan.comサブドメインのメール設定
  • feedback-smtp... = バウンスメール(送信失敗の通知)の受け取り先
  • Priority: 10 = 優先度(数字が小さいほど優先)

9. よくある疑問

Q. SPFだけ設定すればDKIMはいらない?

両方必要です。 SPFはメール転送に弱く、DKIMはIP検証ができません。2つを組み合わせることで、お互いの弱点をカバーします。Gmailなどの主要メールサービスは、SPF・DKIM両方の設定を推奨しており、どちらかが欠けるとスパム判定されやすくなります。

Q. DMARCは設定しなくても大丈夫?

MVPの段階では必須ではありません。ただし、2024年2月からGmailとYahoo!メールが1日5,000通以上送信するドメインにDMARC設定を義務化しています。サービスが成長したら設定しましょう。

参考: Google Workspace - メール送信者のガイドライン

Q. Cloudflareのプロキシ(オレンジの雲)をONにしたらダメ?

メール関連のDNSレコードは**DNS only(グレーの雲)**にしてください。CloudflareのプロキシはHTTPトラフィック用であり、メールプロトコル(SMTP)を通さないため、プロキシをONにするとメール認証が壊れます。

Q. 設定後、反映されるまでどのくらいかかる?

DNSレコードの反映(プロパゲーション)には最大48時間かかりますが、Cloudflareの場合は通常数分から数十分で完了します。Resendのダッシュボードで Verify ボタンを押して確認できます。

Q. 個人開発でも設定すべき?

はい。 設定しないとGmailが迷惑メールに振り分ける確率が大幅に上がります。ユーザーにメールが届かないサービスは信頼を失います。設定自体は10分程度で完了するので、メール送信機能を実装したら必ず設定しましょう。


10. まとめ

やったことなぜ必要か
Resendにドメインを登録自分のドメインからメールを送れるようにする
DKIM(TXTレコード)を設定メールの電子署名を検証可能にする
SPF(TXTレコード)を設定許可されたサーバーからの送信であることを証明する
MX(MXレコード)を設定バウンスメール(送信エラー)を正しく処理する

メール認証は地味な設定作業ですが、ユーザーにメールが確実に届くというサービスの信頼性に直結します。Webサービスを本番運用する際は、必ず設定しましょう。

参考リンク