+ 作るログイン
図を読み込んでいます…
1 / 13
メールのしくみ ― DNS から SPF・DKIM・DMARC、Resend の運用まで / 全11章

メールのしくみ 5:SPF ― 送信元の一覧

発行
アニメモ公式
版
第1版
改訂
コマ
全13

SPF の1行の読み方(include・ip4・mx・all)、受け取る側がどのドメインの何を照らし合わせるのか、なぜ「相手の番号」なら信じてよいのか、7種類の結果、そして SPF の2つの穴(画面の From を見ない・転送で壊れる)と、1行だけ・10回まで、という落とし穴までを説明します。

SPF:「このドメインのメールは、ここからしか出さない」

4本目で、メールの身元確認は「持ち主が DNS に宣言を書き、受け取る側が照らし合わせる」形で後から足された、と説明しました。この作品では、その1つ目である SPF(Sender Policy Framework)を詳しく見ます。

SPF の考え方は単純です。ドメインの持ち主が、DNS に次のような宣言を書いておきます。

「うちのドメインのメールを送ってよいのは、このサーバーたちだけです」

図の下の掲示板にある1行がそれです。

send.mail.animemo.app  TXT  "v=spf1 include:amazonses.com ~all"

受け取る側は、メールを送ってきた相手がこの一覧に入っているかを確かめます。入っていれば、「このドメインの持ち主が許可したサーバーから来た」と言えます。

この作品では、この1行の読み方から始めて、受け取る側が実際に何を照らし合わせているのか、そして SPF だけでは防げない穴まで見ていきます。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 1 / 13
  • SPF:「このドメインのメールは、ここからしか出さない」
  • 送信サーバー
  • 受信サーバー
  • Resend(Amazon SES)
  • Gmail
  • 封筒: send.mail.animemo.app
  • 送信元IP: Amazon SES のもの
  • From: [email protected]
  • SPF
  • animemo.app の掲示板(TXT)
  • send.mail.animemo.app v=spf1 include:amazonses.com ~all
  • 送ってよい送信元の一覧を、持ち主が DNS に書いておく。

SPF の1行を読む

SPF の宣言は、空白で区切られた部品の並びです。

部品意味
v=spf1これは SPF の宣言です(必ず先頭に書く)
include:amazonses.comamazonses.com が公開している SPF の一覧を、そのまま含める
ip4:203.0.113.0/24この IPv4 アドレスの範囲を許可する(ip6: もある)
aこのドメインの A レコードの機械を許可する
mxこのドメインの MX の機械を許可する
~all上のどれにも当てはまらない送信元の扱い(次のページ)

左から順に調べて、最初に当てはまったもので結果が決まります。

いちばんよく使うのは `include:` です。Resend(中身は Amazon SES)のような送信サービスは、自分たちの送信サーバーの番号を自分のドメインの SPF で公開しています。include:amazonses.com と書けば、Amazon SES の番号が増えたり変わったりしても、こちらの宣言を書き換えずに済みます。

/24 は番号の範囲の書き方で、203.0.113.0 から 203.0.113.255 までの256個をまとめて指します。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 2 / 13
  • SPF の1行を読む
  • v=spf1 include:amazonses.com ip4:203.0.113.0/24 mx ~all
  • v=spf1
  • これは SPF の宣言です(必ず先頭)
  • include:amazonses.com
  • Amazon SES が公開している一覧を含める
  • ip4:203.0.113.0/24
  • この番号の範囲も許可する
  • mx
  • このドメインの MX の機械も許可する
  • ~all
  • それ以外は「たぶん偽物」
  • v=spf1 で始まり、許可する送信元を並べ、最後に「それ以外」をどう扱うかで終わる。

最後の all で、一覧に無い送信元の扱いを決める

SPF の最後には、all の前に記号を付けて、一覧に無い送信元から来たメールをどう扱ってほしいかを書きます。

書き方結果の名前意味
-allfail偽物と断定してよい
~allsoftfailたぶん偽物(疑わしい)
?allneutral何とも言わない
+allpass何でも許可(使ってはいけない)

Resend の画面に出てくる値は ~all です。-all のほうが厳しくて安全に見えますが、自分でも忘れていた正規の送信元が一覧から漏れていたとき、そのメールが偽物扱いされてしまいます。まずは ~all で運用するのが普通です。

また、SPF が fail になっても、実際にメールをどう扱うか(受信トレイか、迷惑メールか、拒否か)は、最終的には受け取る側が決めます。今は、7本目の DMARC の宣言と合わせて判断されることが多くなっています。

+all は「誰が送ってもよい」という意味なので、SPF を書く意味がなくなります。書いてはいけません。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 3 / 13
  • 最後の all で、一覧に無い送信元の扱いを決める
  • -all 偽物と断定(fail)
  • Resend が示す値は ~all。 fail にしても、最後に どうするかは受け取る側 と DMARC(7本目)が決める。
  • ~all たぶん偽物(softfail)
  • ?all 何とも言わない(neutral)
  • +all 全部許可(使ってはいけない)
  • ~all(たぶん偽物)から始めるのが普通。-all は漏れがあると本物が消える。

受け取る側は、まず「封筒の差出人」のドメインを見る

では、受け取る側(Gmail)が SPF をどう確かめるのかを、順に見ていきます。

最初に、どのドメインの SPF を読むかを決めます。見るのは、3本目で出てきた封筒の差出人(SMTP の MAIL FROM)のドメインです。図の例では send.mail.animemo.app です。

ここが大事なところです。画面に出る手紙の `From:` ではありません。 SPF は、SMTP の会話の中で名乗られた封筒の差出人について確かめる仕組みです。

Gmail は send.mail.animemo.app の掲示板から TXT を読み、v=spf1 で始まる行を探します。そこに「送ってよいのは Amazon SES」と書いてあります。

※届かなかった知らせ(バウンス)のように封筒の差出人が空のメールでは、代わりに EHLO で名乗った機械の名前を使って SPF を確かめます。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 4 / 13
  • 受け取る側は、まず「封筒の差出人」のドメインを見る
  • 送信サーバー
  • 受信サーバー
  • Resend(Amazon SES)
  • Gmail
  • 封筒: send.mail.animemo.app
  • 送信元IP: Amazon SES のもの
  • From: [email protected]
  • SPF
  • ↑ このドメインの SPF を読む
  • animemo.app の掲示板(TXT)
  • send.mail.animemo.app v=spf1 include:amazonses.com ~all
  • 見るのは画面の From ではない。MAIL FROM に書かれたドメイン。

次に、いま話している相手の番号を一覧と照らす

次に Gmail は、いま自分と SMTP の会話をしている相手の IP アドレスを見ます。

その番号が、読んできた一覧(include:amazonses.com の中身)に入っていれば、SPF は pass(合格) です。図では、送ってきたのが Amazon SES のサーバーで、一覧にも Amazon SES が入っているので合格しています。

まとめると、SPF は次の2つを組み合わせています。

材料なぜ信じてよいか
掲示板に書かれた一覧持ち主しか書けないから(2本目)
相手の番号嘘の番号では会話が続かないから(次のページ)

この2つがそろうことで、「このドメインの持ち主が許可したサーバーから来た」と言えるようになります。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 5 / 13
  • 次に、いま話している相手の番号を一覧と照らす
  • 送信サーバー
  • 受信サーバー
  • Resend(Amazon SES)
  • Gmail
  • 封筒: send.mail.animemo.app
  • 送信元IP: Amazon SES のもの
  • From: [email protected]
  • SPF
  • pass(合格)
  • animemo.app の掲示板(TXT)
  • send.mail.animemo.app v=spf1 include:amazonses.com ~all
  • 一覧に Amazon SES が入っていて、送ってきたのも Amazon SES。合格。

なぜ「相手の番号」なら信じてよいのか

SPF は「相手の番号」を信じる前提に立っています。メールの From: は自由に書けるのに、番号は信じてよいのはなぜでしょうか。

1本目で、通信の小包には差出人の番号が書かれている、と説明しました。この番号を偽ることはできます。ところが、偽の番号を書くと、受け取った側の返事は、その偽の番号あてに送られます。本当の送り手には返事が届きません。

SMTP は、送る側が1行言い、受ける側が返事をする、という会話を何往復も続けます。返事が届かなければ、次に何を言えばいいか分からず、会話が進みません。当然、メールを最後まで渡すこともできません。

つまり、SMTP の会話が最後まで成り立った相手の番号は、本物とみなしてよいのです。SPF はこの性質を利用しています。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 6 / 13
  • なぜ「相手の番号」なら信じてよいのか
  • 送り手
  • 受信サーバー
  • 嘘の番号を名乗る
  • 返事を名乗られた番号へ
  • 返事が本人に届かない → 会話が進まない → メールを渡せない
  • だから、会話が成り立った相手の番号は本物とみなせる
  • 嘘の番号では返事が戻らず、SMTP の会話が続かない(1本目)。

SPF の結果は7種類ある

SPF を確かめた結果には、名前が付いています。

結果意味
pass一覧に入っている
fail一覧に無い(-all)
softfail一覧に無い(~all)
neutral何とも言っていない(?all)
noneそもそも SPF の宣言が無い
permerror宣言が壊れていて読めない(書き方の間違い)
temperrorDNS が一時的に引けなかった

ふだん気にするのは、pass・fail・softfail の3つです。

もう1つ覚えておきたいのが permerror です。これは「設定した側の書き方が間違っている」ことを表します。permerror になると、せっかく書いた SPF が無いのと同じ扱いになり、正規のメールまで身元が確かめられなくなります。この作品の後半で、permerror になる典型的な間違いを2つ見ます。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 7 / 13
  • SPF の結果は7種類ある
  • pass
  • 一覧に入っている
  • fail
  • 一覧に無い(-all)
  • softfail
  • 一覧に無い(~all)
  • neutral
  • 何とも言っていない(?all)
  • none
  • SPF の宣言が無い
  • permerror
  • 宣言が壊れている(書き方の間違い)
  • temperror
  • DNS が一時的に引けなかった
  • 大事なのは pass・fail・softfail と、設定の間違いを示す permerror。

SPF の穴①:画面に出る From を見ていない

ここからは、SPF だけでは防げない穴を見ます。

1つ目の穴は、SPF が確かめるのが封筒の差出人だけだということです。受信者の画面に出る手紙の `From:` は見ていません。

図では、なりすましの送り手が、封筒の差出人を自分のドメイン evil.example にしています。自分のドメインなので、SPF の宣言も自分で書けます。送ってくるのも自分のサーバーなので、SPF は合格します。

一方で、手紙の From: には 〇〇銀行 <[email protected]> と書いてあります。受信者の画面に出るのはこちらです。

SPF は「封筒の差出人は本物」と言っているだけで、「画面の差出人は本物」とは言っていません。利用者が目にするのは画面の差出人なので、これはなりすましを防ぐうえで致命的な穴です。この穴は、7本目の DMARC が塞ぎます。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 8 / 13
  • SPF の穴①:画面に出る From を見ていない
  • なりすまし
  • 受信サーバー
  • evil.example
  • Gmail
  • 封筒: evil.example
  • 送信元IP: evil.example の機械
  • From: 〇〇銀行 <[email protected]>
  • SPF
  • ↑ ここは誰も見ていない
  • pass(合格)
  • evil.example の掲示板(TXT)
  • evil.example v=spf1 ip4:(自分のサーバー) -all
  • 封筒は自分のドメイン、手紙は銀行。SPF はそれでも合格する。

SPF の穴②:転送されると失敗する

2つ目の穴は転送です。

太郎さんが、大学のメールアドレスに届いたメールを、Gmail へ自動転送する設定にしていたとします。すると、メールは Resend → 大学のサーバー → Gmail と運ばれます。

Gmail から見ると、SMTP の会話をしている相手は大学のサーバーです。封筒の差出人は send.mail.animemo.app のままなので、その SPF の一覧を見ますが、大学のサーバーは載っていません。SPF は不合格になります。

メールは正規のものなのに、転送されただけで落ちてしまいます。SPF は「どの番号から来たか」を見る仕組みなので、途中で経路が変わると必ず壊れます。これは SPF の設定をどう工夫しても避けられません。

この穴は、6本目の DKIM が埋めます。DKIM は経路ではなく、メールそのものに印を付ける方式だからです。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 9 / 13
  • SPF の穴②:転送されると失敗する
  • 転送サーバー
  • 受信サーバー
  • 大学のメール
  • Gmail
  • 封筒: send.mail.animemo.app
  • 送信元IP: 大学のサーバー
  • From: [email protected]
  • Resend → 大学 → Gmail
  • SPF
  • fail / softfail(不合格)
  • animemo.app の掲示板(TXT)
  • send.mail.animemo.app v=spf1 include:amazonses.com ~all
  • 転送で送信元IPが大学のものに変わる。一覧に無いので不合格。

SPF の行は、1つの名前に1行だけ

ここからは、SPF を設定するときの落とし穴です。

Google Workspace を使っているドメインに、あとから別のサービスの SPF を足すとき、もう1行増やしてしまうのは典型的な失敗です。

SPF の宣言は、1つの名前につき1行だけと決まっています。v=spf1 で始まる行が2つあると、受け取る側はどちらを信じればよいか分からず、permerror(宣言が壊れている)として扱います。善意で足した1行のせいで、それまで合格していたメールまで落ちます。

正しくは、include: を並べて1行にまとめます。

v=spf1 include:_spf.google.com include:amazonses.com ~all

なお、v=spf1 で始まらない TXT(ほかのサービスの確認用の文字列など)は、同じ名前に何行あっても構いません。問題になるのは SPF の行だけです。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 10 / 13
  • SPF の行は、1つの名前に1行だけ
  • example.com の掲示板(悪い例)
  • v=spf1 include:_spf.google.com ~all
  • v=spf1 include:amazonses.com ~all
  • v=spf1 include:_spf.google.com include:amazonses.com ~all
  • 2行あると両方無効(permerror)。include でまとめて1行にする。

include をたどれる回数は10回まで

もう1つの落とし穴は、DNS を引く回数の上限です。

受け取る側は SPF を確かめるとき、include: の先の一覧を DNS で引きに行きます。その先にさらに include: があれば、それも引きます。この「DNS を引く部品」(include・a・mx など)の数は、合計で10回までと決まっています。ip4: や ip6: は DNS を引かないので数えません。

上限がある理由は、受け取る側を守るためです。1通のメールのたびに何十回も DNS を引かされると、受信サーバーが重くなり、悪用もされやすくなります。

使っているサービスを次々に include: で足していくと、自分では数回のつもりでも、各サービスの一覧の中の include: まで数えて10回を超えてしまうことがあります。超えると permerror です。

対策として有効なのが、送信用のサブドメインを分けることです。Resend のように send.mail.animemo.app という別の名前に SPF を置けば、ほかのサービスの一覧と混ざらず、回数も数えやすくなります。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 11 / 13
  • include をたどれる回数は10回まで
  • example.com の SPF
  • include: google
  • include: amazonses
  • include: 請求サービス
  • include: 問い合わせ…
  • include の先がさらに include していれば、それも数える。合計10回を超えたら失敗
  • 対策: 送信用のサブドメインを分け、1つの名前に載せるサービスを減らす
  • サービスを足しすぎると上限を超えて permerror。これも本物が落ちる。

Resend の SPF が send.mail.animemo.app にある理由

10本目で Resend の設定をすると、SPF の行を send.mail.animemo.app(管理画面では send.mail)という名前に入れるよう指示されます。mail.animemo.app そのものではないのはなぜでしょうか。

理由は、この作品の前半で見た「SPF は封筒の差出人のドメインで読まれる」ことにあります。Resend は、封筒の差出人を …@send.mail.animemo.app にしてメールを送ります。だから SPF も、その send.mail.animemo.app の掲示板に置く必要があるのです。

封筒の差出人を専用の名前にしているのには、ほかにも理由があります。

理由中身
戻りの受け口を作る届かなかった知らせを Resend が受け取れるように、同じ名前に MX も置く(10本目)
普段の設定とぶつけないmail.animemo.app や animemo.app の SPF とは別の行になる
回数を数えやすくする前のページの10回の上限に引っかかりにくい

画面に出る From: は [email protected] のままで、封筒だけが send.mail… になります。この2つが別のドメインでも問題ないことは、7本目の DMARC で確かめます。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 12 / 13
  • Resend の SPF が send.mail.animemo.app にある理由
  • 送信サーバー
  • 受信サーバー
  • Resend(Amazon SES)
  • Gmail
  • 封筒: send.mail.animemo.app
  • 送信元IP: Amazon SES のもの
  • From: [email protected]
  • SPF
  • 封筒 = send.mail.animemo.app
  • pass(合格)
  • animemo.app の掲示板(TXT)
  • send.mail.animemo.app v=spf1 include:amazonses.com ~all
  • SPF は封筒のドメインで読まれる。Resend は封筒を send.〜 にして送るから。

まとめ:SPF

この作品で見たことをまとめます。

項目内容
何を宣言するかこのドメインのメールを送ってよい送信元の一覧
どこに書くか封筒の差出人のドメインの TXT。1つの名前に1行だけ
受け取る側は何を見るかその一覧と、SMTP の会話の相手の番号
なぜ番号を信じてよいか嘘の番号では会話が続かないから
最後の all~all(たぶん偽物)から始める
穴①画面の From: を見ていない → 7本目の DMARC が塞ぐ
穴②転送で壊れる → 6本目の DKIM が補う
落とし穴2行書くと permerror。DNS を引く回数は10回まで

次の作品では、経路ではなくメールそのものに印を付ける DKIM を見ていきます。

  • メールのしくみ 5 / 11 ― SPF:送信元の一覧
  • 13 / 13
  • まとめ:SPF
  • 見るもの
  • 封筒のドメインの一覧 と 相手の番号
  • 書く場所
  • 封筒のドメインの TXT(1行だけ)
  • 穴①
  • 画面の From を見ない
  • 穴②
  • 転送で壊れる
  • 注意
  • 1行だけ・10回まで・~all から
  • SPF は「どこから来たか」を確かめる。穴②は DKIM が、穴①は DMARC が埋める。

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]