SPF include メカニズム(Include Mechanism)
概要
SPF include メカニズム(Include Mechanism) は、指定したドメインの SPF レコードを参照して、送信元 IP の認可を外部に委任する仕組みです。RFC 7208(2014年)の Section 5.2 で定義されており、自社が直接管理しない IP アドレスからのメール送信を許可する際に使います。
典型的な利用場面は SaaS メール配信サービスの認可です。Google Workspace、SendGrid、Amazon SES、HubSpot など、外部サービス経由でメールを送信する場合、そのサービスの送信サーバー IP をすべて自分で列挙する必要はありません。include:_spf.google.com のように記述するだけで、Google が管理する SPF レコード内の IP レンジを自動的に参照します。
ただし include は DNS ルックアップを伴い、参照先がさらに include を含む場合はネストした分だけルックアップ回数が増えます。RFC 7208 が定める 1 回の SPF チェックあたり DNS ルックアップ 10 回以内という制限に直接影響するため、複数の SaaS を併用する環境では計画的な管理が必要です。
仕組み
include は参照先の SPF レコードが pass を返した場合にのみ一致とみなし、参照先の fail は次のメカニズムへ進む合図として処理します。
評価フロー
受信サーバーが SPF レコード内の include: を処理するとき、次の手順で評価します。
- 受信サーバーが送信元ドメインの SPF レコードを取得する
include:example.comに到達すると、example.comの SPF レコードを DNS で引く(ここで 1 回の DNS ルックアップを消費)- 参照先の SPF レコードに含まれるメカニズムで送信元 IP を評価する
- 参照先の評価結果が
passであれば、includeメカニズム全体がpassになる - 参照先の評価結果が
fail、softfail、neutralの場合、includeメカニズムは一致しなかったものとして次のメカニズムに進む
ここで重要なのは、include の結果が fail でも元のレコード全体が fail にはならない点です。include は「参照先が pass を返したら一致」という動作であり、参照先の fail は単に「このメカニズムは一致しなかった」という意味になります。最終的な fail 判定は、元のレコードの all メカニズムが決定します。
ネストと DNS ルックアップの消費
include の参照先がさらに include を含む場合、ルックアップは再帰的にカウントされます。
Google Workspace の _spf.google.com を例に取ると、内部構造は次のようになっています。
_spf.google.com
→ include:_netblocks.google.com (1 回)
→ include:_netblocks2.google.com (1 回)
→ include:_netblocks3.google.com (1 回)
_spf.google.com 自体の参照で 1 回、内部の 3 件で 3 回、合計 4 回の DNS ルックアップを消費します。
同様に他の SaaS サービスも内部で複数のルックアップを使います。
| サービス | include 指定 | 消費するルックアップ数(目安) |
|---|---|---|
| Google Workspace | _spf.google.com | 4 回 |
| SendGrid | sendgrid.net | 1〜2 回 |
| Amazon SES | amazonses.com | 1〜2 回 |
| Microsoft 365 | spf.protection.outlook.com | 2〜3 回 |
| HubSpot | spf.hubspot.com | 1 回 |
Google Workspace と SendGrid を併用するだけで 5〜6 回を消費し、そこに自社の a や mx メカニズムを加えると 10 回の上限に接近します。
include と redirect の違い
include と似た動作をする redirect= 修飾子がありますが、動作が異なります。
include は「参照先が pass を返したら一致」として処理し、一致しなければ次のメカニズムに進みます。一方、redirect= は「このレコードの処理を完全に別ドメインに移譲する」という動作で、元のレコードの all は無視されます。redirect= は SPF レコードの末尾に 1 つだけ記述でき、all メカニズムと併用できません。
複数の送信元を認可する場合は include を使い、SPF 設定をまるごと別ドメインに委任する場合(例: 親ドメインの設定をサブドメインに適用する)は redirect= を使います。
設定例
include は 1 つの TXT レコード内に複数記述し、ip4: との組み合わせでルックアップ回数を節約できます。
基本構成
Google Workspace を利用している場合の SPF レコードです。
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
include:_spf.google.com で Google のメールサーバー IP を許可し、~all でそれ以外を softfail にしています。
複数 SaaS の併用
Google Workspace と SendGrid を併用する場合は、1 つの TXT レコードにまとめます。
example.com. IN TXT "v=spf1 include:_spf.google.com include:sendgrid.net ~all"
RFC 7208 は同一ドメインに v=spf1 で始まる TXT レコードが複数存在することを禁止しています。サービスを追加するときは既存のレコードに include: を追記してください。
ip4 との組み合わせ
自社のメールサーバーと SaaS を両方使う場合、自社 IP は ip4: で直接指定し、SaaS は include: で参照します。ip4: は DNS ルックアップを消費しないため、上限の節約になります。
example.com. IN TXT "v=spf1 ip4:203.0.113.0/24 include:_spf.google.com ~all"
ルックアップ上限に達した場合のフラットニング
include のネストで 10 回を超える場合、参照先の IP レンジを ip4: に展開する方法(SPF フラットニング)があります。
example.com. IN TXT "v=spf1 ip4:209.85.128.0/17 ip4:74.125.0.0/16 ip4:149.72.0.0/16 ~all"
ただし、SaaS プロバイダーは予告なく IP レンジを変更します。手動フラットニングの場合は定期的に最新の IP レンジと照合する必要があり、管理コストが増えます。自動フラットニングサービス(AutoSPF、EasyDMARC SPF Flattening 等)を検討してください。
確認方法
ドメインの SPF レコードを確認するには dig を使います。
dig TXT example.com +short
出力から v=spf1 で始まる行を探し、含まれる include: の数を確認します。
"v=spf1 include:_spf.google.com include:sendgrid.net ~all"
include 先の中身を展開して確認するには、参照先ドメインに対して dig を繰り返します。
dig TXT _spf.google.com +short
"v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
この方法でネストをすべて辿ると、最終的に何回の DNS ルックアップを消費しているかを手動で数えられます。
外部の視点からも確認したい場合は、Labee Dev Toolbox の Mail Auth API を使うと、外部の視点から見た結果を取得できます。
curl "https://labee.dev/api/mail-auth?domain=example.com"
{
"success": true,
"data": {
"spf": {
"record": "v=spf1 include:_spf.google.com include:sendgrid.net ~all",
"exists": true
},
"dkim": { "record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqh...", "exists": true, "selector": "default" },
"dmarc": { "record": "v=DMARC1; p=reject; rua=mailto:dmarc@example.com", "exists": true },
"bimi": { "record": null, "exists": false }
},
"error": null,
"meta": { "responseTime": 123 }
}
data.spf.record フィールドに SPF レコードの内容が返ります。data.spf.exists が true であれば外部から SPF レコードが確認できる状態です。ただし、この API は SPF レコードの取得のみで、include の再帰展開やルックアップ回数の計算は行いません。ルックアップ回数を正確に把握するには、MXToolbox の SPF Record Lookup や dmarcian の SPF Surveyor のようなフラット展開機能を持つチェックツールを併用します。
よくある問題
include に関するトラブルは、DNS ルックアップ上限の超過、参照先レコードの消失、redirect との混同に集中しています。
include の追加でルックアップ上限を超える
新しい SaaS メール配信サービスを導入するたびに include: を追記していくと、表面上は数個の include: でも内部のネストにより 10 回を超えることがあります。超過すると受信サーバーは permerror を返し、DMARC ポリシーが p=reject の場合は正規メールでも受信拒否されます。
対策は 3 つあります。使わなくなったサービスの include: を削除する。送信 IP が固定のサービスは ip4: に書き換える。サービス数が多い場合は SPF フラットニングを導入する。
include 先のドメインが存在しない
include: で指定したドメインに SPF レコードが存在しない場合、その include は permerror を返します。これはサービスの移行後に古い include: を削除し忘れた場合に発生します。RFC 7208 では、include 先の DNS ルックアップで結果が返らなかった場合は void lookup としてカウントされ、void lookup は 2 回以内に制限されています。
SPF レコードを変更したあとは、dig で参照先のドメインが有効な SPF レコードを返すか確認してください。
include と redirect の混同
redirect= と include: の動作の違いを理解せずに併用すると、意図しない評価結果になります。redirect= は all メカニズムと同時に使えません。redirect= が指定されている場合、レコード内の all は無視されます。
複数の送信元を認可する用途では include: を使います。redirect= は SPF 設定を丸ごと別ドメインに委任する場合にのみ使用します。
サービス変更後の include 残置
SaaS メール配信サービスを乗り換えたにもかかわらず、旧サービスの include: を SPF レコードに残したままにしているケースがあります。直接の害(メール配信障害)は起きにくいものの、DNS ルックアップの無駄遣いになり、上限 10 回を圧迫します。定期的に SPF レコードを棚卸しして、実際に使用しているサービスの include: だけが残っている状態を維持してください。
同一 include の重複記述
同じドメインを 2 回 include: してもエラーにはなりませんが、DNS ルックアップは 2 回分消費されます。レコードが長くなると見落としやすいため、追記する前に既存の include: と重複していないか確認してください。