SPF DNS ルックアップ上限(DNS Lookup Limit)
概要
SPF DNS ルックアップ上限(DNS Lookup Limit) は、RFC 7208(2014年)が定める制約で、1 回の SPF チェックで実行できる DNS ルックアップの合計を 10 回以内に制限します。この上限を超えると受信サーバーは permerror を返し、DMARC はこれを fail と判定します。
上限を超えることで自社の正規メールが認証失敗扱いになり、p=reject の環境では受信拒否されます。SendGrid、Salesforce Marketing Cloud、HubSpot、Google Workspace などを併用している組織では、気づかないうちに上限に達するケースが多く、SPF 設定の落とし穴として最も頻繁に問題になる項目の一つです。
仕組み
SPF レコードのメカニズムのうち、DNS ルックアップを伴うものとそうでないものがあります。
| メカニズム | DNS ルックアップ | 備考 |
|---|---|---|
include: | あり | 参照先のレコードも再帰的にカウント |
a / a: | あり | 対象ドメインの A レコードを引く |
mx / mx: | あり | 対象ドメインの MX レコードを引く |
ptr | あり | 逆引き DNS を使う。RFC 7208 で使用非推奨 |
exists: | あり | 指定ドメインの A レコードを引く |
redirect= | あり | 別ドメインのレコードに処理を移譲する |
ip4: / ip6: | なし | 直接 IP を指定するためルックアップ不要 |
all | なし |
ネストによるルックアップの増加
include: で参照した先のレコードがさらに include: を含む場合、ネストの深さ分だけルックアップが積み重なります。
例として、include:_spf.google.com を 1 個追加しても、_spf.google.com の内部は次のように展開されます。
_spf.google.com → include:_netblocks.google.com
include:_netblocks2.google.com
include:_netblocks3.google.com
これだけで _spf.google.com の参照 1 回と内部 3 回の計 4 回を消費します。これに SendGrid(2〜3 回)、HubSpot(2〜3 回)を追加すると、あっという間に 10 回に達します。
void lookup の制限
RFC 7208 は追加で、DNS ルックアップのうち結果が返らなかったもの(void lookup)を 2 回以内に制限しています。存在しないドメインへの include: など、設定ミスによる無効な参照がこれに該当します。
設定例
include のネストによるルックアップ消費を把握し、必要に応じてフラットニングで IP 直書きに切り替えます。
複数 SaaS の include 構成
SaaS を複数使う場合のよくある構成です。
example.com. IN TXT "v=spf1 include:_spf.google.com include:sendgrid.net include:_spf.salesforce.com include:spf.protection.outlook.com ~all"
この記述は見かけ上 4 個の include: ですが、各サービスの内部ルックアップを含めると 10 回を超える可能性があります。
フラットニング後
フラットニング(展開)後の例です。include: の参照先を再帰的に展開して ip4: に書き換えます。
example.com. IN TXT "v=spf1 ip4:209.85.128.0/17 ip4:209.85.192.0/19 ip4:74.125.0.0/16 ip4:149.72.0.0/16 ip4:167.89.0.0/16 ~all"
ただし、フラットニングは各サービスが IP レンジを変更するたびに手動更新が必要です。SendGrid や Google Workspace は予告なく IP を追加することがあります。更新を自動化する SPF フラットニングサービス(AutoSPF、EasyDMARC の SPF Flattening 等)を使うと管理コストを下げられます。
確認方法
dig で SPF レコードを確認しても、ネストされた include: の展開後のルックアップ回数はわかりません。
dig TXT example.com
;; ANSWER SECTION:
example.com. 3600 IN TXT "v=spf1 -all"
v=spf1 で始まる行に含まれる include: の数は分かりますが、その内部の参照は展開されません。
外部の視点からも確認したい場合は、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 レコードが確認できる状態です。実際のルックアップ回数を数えるには、MXToolbox(mxtoolbox.com/spf.aspx)や dmarcian の SPF Surveyor など、フラット展開機能を持つチェックツールを使います。
よくある問題
DNS ルックアップ上限の超過は、include の追加やフラットニングの放置によって発生し、permerror でメール認証が停止します。
SaaS を追加するたびに include: を追記する
新しいメール配信サービスを導入するたびに include: を追記していくと、気づかないうちに 10 回を超えます。導入のたびにルックアップ回数をチェックします。すでに上限に近い場合は、ip4: に書き換えるか、SPF フラットニングサービスを導入します。
ptr メカニズムを使う
ptr は逆引き DNS を使うため処理が遅く、ルックアップ数も増えます。RFC 7208 も使用を非推奨としています。ptr が含まれている場合は ip4: か include: で代替します。
permerror の原因に気づかない
permerror はメールのヘッダーに Authentication-Results: spf=permerror として記録されます。しかしエンドユーザーには届かないメールとして消えるため、送信側では問題に気づきません。DMARC の rua 集計レポートで spf=permerror の件数が増えていたら、DNS ルックアップ上限の超過を疑います。
フラットニングを一度やって放置する
ip4: に書き換えたあと、サービス側が IP レンジを変更しても自動的には反映されません。フラットニングした SPF レコードは定期的に最新の IP レンジと照合するか、自動更新サービスを使います。古い ip4: だけが残った状態では、新しい IP から送信されたメールが SPF fail になります。
同一ドメインに TXT レコードを複数発行する
include: を 1 行に収めようとしてレコードを分割するのは RFC 7208 違反です。同一ドメインに v=spf1 で始まる TXT レコードが複数存在すると permerror を返します。新しい送信サービスを追加するときは、既存の 1 件のレコードに include: を追記します。