※本記事にはアフィリエイト広告(PR)を含みます。
ある日を境に、特定の取引先とのメールが急に届かなくなり、受信側のログでSPFの認証結果が軒並みおかしくなった——という経験はないだろうか。自社のSPFレコード自体は変更していないのに、まず疑うべきはSPFのDNSルックアップ回数制限だ。RFC 7208は、SPFレコード評価時に発生してよいDNSクエリの回数へ明確な上限を定めており、これを超えると結果は単なる不一致ではなく「PermError」という恒久的なエラーになる。Microsoft 365やGoogle Workspace、SendGridなど複数のクラウド基盤・ESPを併用する組織ほど、この上限に近づきやすい。本稿では10回制限とvoid lookupの仕組み、何が回数を消費するのか、確認方法と対処法を整理する。
SPFの「DNSルックアップ10回制限」とは何か
SPFの検証処理は、RFC 7208でcheck_host()と呼ばれる関数として定義されている。送信元IPが許可されているかを判定するため、対象ドメインのSPFレコードに書かれたメカニズムを先頭から順に評価していく。この過程で、レコード自体を取得するTXTクエリとは別に、レコード中のinclude等をたどって追加のDNSクエリが発生することがある。
RFC 7208の4.6.4節は、DNSクエリを発生させる項(term)を明確に定義している。include・a・mx・ptr・existsの各メカニズムとredirectモディファイアがこれに該当し、その合計は評価全体を通じて10回以内でなければならない(MUST)。上限を超えた場合、実装はPermErrorを返さなければならない。
見落とされがちなのが、もう一つの上限「void lookup」だ。問い合わせ結果が「ドメインが存在しない(NXDOMAIN)」、または「応答はあるがレコードが0件」だった参照を指し、RFC 7208はこれを2回までに制限すべき(SHOULD)としている。実装依存の面はあるが、多くの実装は既定値の2回を踏襲する。10回に届いていなくても、参照先の設定ミスや廃止でvoid lookupが3回以上発生すれば、同じくPermErrorになり得る。
PermErrorはRFC上、「ドメインが公開したレコードを正しく解釈できなかった」ことを示し、DNSオペレーターの対応が必須になる恒久的なエラーと定義される。DNSの一時的な障害による「TempError」(再試行で解消し得るエラー)とは明確に区別される。この上限は、悪意のあるドメインがDNS参照を誘発しSPF検証側を踏み台にする増幅型DoS攻撃を防ぐために設けられている。
何がDNSルックアップを消費するのか:include・a・mx・ptr・exists
include
指定ドメインのSPFレコードを再帰的に評価する。includeそのものが1カウントとなるのに加え、参照先レコード内のinclude・a・mxなども通算でカウントされる。見落としやすいのは、include先にSPFレコードが存在しない場合の挙動だ。単なる「不一致」として無視されるのではなく、呼び出し元全体がPermErrorになるとRFCで規定されている。委託先の変更やサービス終了で参照先のレコードが消えると、静かに認証全体が壊れる典型パターンになる。
aとmx
aメカニズムは対象ドメインのA/AAAAレコードを引く処理で、返るレコード数に関わらず1カウントだ。一方mxメカニズムは、まずMXレコードを引き、返ってきたMXホストごとにアドレスレコードを引く。RFC 7208は問い合わせるMXレコードの件数を10回の上限に算入すると定めており、MXが3件あるドメインをmx:で参照すれば3カウント消費し得る。
ptr
接続元IPを逆引きし正引きで整合を確認する仕組みだが、RFC 7208自身が「公開すべきではない(SHOULD NOT)」と明記する非推奨のメカニズムであり、新規のSPFレコードでは使うべきではない。
exists
マクロで組み立てた任意のドメイン名にAレコードを問い合わせ、存在すれば一致とみなす仕組みで、送信者やIPアドレス単位の細かい制御に使われる。使用頻度は高くないが、使えば1カウントになる。
これに加えredirectモディファイアも同じ10回制限の対象になる。一方、all・ip4・ip6とexpモディファイアはDNSクエリを発生させず上限に算入されない。この違いが後述する「フラット化」の土台になる。
ルックアップ超過を確認する方法:digと自動チェックツールの考え方
自社のSPFレコードが何回のルックアップを消費しているかは、digで地道にたどれる。まず自ドメインのTXTレコードを引く。
dig TXT example.co.jp +short "v=spf1 include:_spf.example.net include:_spf.example.org -all"
include:_spf.example.netが見つかったら、そのドメインのTXTレコードも同様に引く。
dig TXT _spf.example.net +short "v=spf1 include:spf.example.com a mx -all"
このように、includeをたどるたびに現れるinclude・a・mx・ptr・existsとredirectを一つずつ数え、参照先の参照先までもぐって合計を出す。10に近い、あるいは超えていればPermErrorのリスクがある状態だ。あわせて「NXDOMAIN」や応答はあるがレコードなし、といった結果(void lookup)が出ていないかも確認する。手作業は数え漏れが起きやすく、この展開・集計を自動化したチェックツールを併用すると効率的だ。ツールも参照を深さ優先で展開し合計しているだけなので、仕組みを理解していれば内訳を自分で検証できる。
対処法:不要include削除・フラット化・ip4/ip6直書き・サブドメイン分離
棚卸しと不要includeの削除
最初に着手すべきは棚卸しだ。現在のSPFレコードに並ぶinclude・a・mx・ptr・exists・redirectそれぞれが、どのサービス・送信元に対応するかを洗い出す。担当者交代の過程で、既に使っていない配信サービスや移行済みの旧システム向けincludeが残っているケースは珍しくない。不要と確認できたものを削除するのが、最もリスクが低く効果の大きい対処になる。
フラット化(ip4/ip6への直書き)
棚卸し後も10回を超える、あるいは余裕がない場合はフラット化を検討する。include先のSPFレコードを実際にたどって得られるIPアドレス範囲を、自社のSPFレコードにip4/ip6として直接書き出す方法だ。
変更前: v=spf1 include:_spf.example.net -all 変更後(_spf.example.netの実体を展開): v=spf1 ip4:203.0.113.0/24 ip4:198.51.100.0/24 ip6:2001:db8:1::/48 -all
ip4・ip6はDNSクエリを発生させないため、includeで消費していた枠をまるごと解放できる。レコードは長くなる分、記述の見通しは必要になるが、10回制限そのものを回避できる直接的な方法だ。
サブドメイン分離
特定用途でしか使わないサービスのincludeを、メインドメインのSPFレコードに同居させ続けると、無関係な送信元まで含めて全社のルックアップ枠を消費し続ける。メールマガジン配信専用にnews.example.co.jpを使うなら、そのサブドメインだけに必要なincludeを持つ専用SPFレコードを用意すればよい。メインドメインをシンプルに保ちながら、サービスごとの増減の影響を局所化できる。
なお、同一管理主体で複数ドメインに同じ認可ポリシーを持たせたい場合は、includeよりredirectモディファイアで一本化したほうが管理しやすい。ただしredirectも10回制限の対象である点は変わらない。
運用上の注意点:フラット化は「変更への追従」が鍵
フラット化には見落とされがちな副作用がある。includeなら参照先がIPレンジを変更しても自動的に最新状態を参照し続けられるが、フラット化でip4/ip6に直書きすると、その時点のスナップショットを固定することになる。参照元がIPレンジを変更すれば自社レコードは追従できず、正当な送信元のメールがSPFで不一致になるリスクを抱える。
フラット化を採用するなら「書いたら終わり」ではなく、参照元のSPF公開情報を定期的に確認し、必要に応じてip4/ip6を更新する運用が前提になる。変更頻度の高い大規模サービスをまとめてフラット化すると追従コストが運用負荷になるため、変更の少ない参照先から優先し、変更が頻繁な相手はincludeのまま残すのも現実的だ。変更後は必ずdigやチェックツールでルックアップ数とvoid lookupの状況を確認し、受信側のヘッダーで想定通りpassしているかも一定期間追跡したい。
SPFやDMARCなどのメール認証を実際に設定・検証するには、DNSレコードを自由に編集できる独自ドメイン環境が必要です。
![]()
まとめ
SPFのPermErrorは「なんとなく失敗した」のではなく、RFC 7208が定めるDNSルックアップ10回、void lookup 2回という明確な上限を超えたことを示す恒久的なエラーだ。まずは自社レコードのinclude・a・mx・ptr・exists・redirectを棚卸しし、不要なものを削除する。それでも足りなければ、変更頻度の低い参照先からフラット化を進め、ip4/ip6への直書きでルックアップの枠を確保する。ただしフラット化は参照元の変更に追従できなくなる代償を伴うため、定期的な見直しとセットで運用してほしい。
最終更新:2026年7月

