DNS レコードを追加したのに「存在しない名前」と返るとき:NXDOMAIN、NODATA とネガティブキャッシュ
レコードを追加した後も一部のリゾルバーが「存在しない」と返し続ける理由を RFC で整理しました。NXDOMAIN と NODATA の違い、SOA で決まるネガティブ TTL、下位の名前まで止める NXDOMAIN cut、失敗キャッシュの 5 分の上限を扱います。
新しいサブドメインのレコードを権威サーバーに追加したのに、あるネットワークではすぐ見え、別のネットワークではしばらく「その名前は存在しない」という応答が続くことがあります。リゾルバーがキャッシュするのは、存在するレコードだけではありません。「存在しない」という応答もキャッシュします。これをネガティブキャッシュと呼び、ルールは RFC 2308 にあります。この記事は RFC 2308 と、RFC 2308 を更新した文書のうちこの話題に関わる RFC 8020、RFC 9520、および関連する RFC 8767 に基づいています。特定のリゾルバー製品の既定値は扱いません。
DNS の名前解決の基本的な流れと、通常のレコードの TTL は ドメイン名が IP アドレスになるまで:DNS の名前解決のしくみ にまとめています。
「存在しない」には 2 種類ある
RFC 2308 の 1 節と 2 節は、否定応答を 2 種類に分けています。
- NXDOMAIN:応答ヘッダーの RCODE が Name Error です。問い合わせた名前そのものが存在しないという意味です。
- NODATA:RCODE は NOERROR ですが、回答セクションに要求したタイプのレコードがありません。名前は存在するものの、そのタイプのレコードがないという意味です。NODATA を表す RCODE の値はないため、応答の内容から判断する必要があります。
キャッシュされる単位も違います(RFC 2308 5 節)。
- NXDOMAIN は
<QNAME, QCLASS>に対してキャッシュされます。タイプに関係なく、その名前全体が「存在しない」と記憶されます。 - NODATA は
<QNAME, QTYPE, QCLASS>に対してキャッシュされます。存在しないのはそのタイプだけです。
そのため、すでに A レコードがある名前に AAAA レコードを追加した場合、キャッシュに残りうるのは AAAA についての NODATA だけで、A の問い合わせには影響しません。逆に、まだなかった名前を新しく作る場合は、それ以前に誰かがその名前を問い合わせて受け取った NXDOMAIN が、すべてのタイプの問い合わせを止めている可能性があります。
ネガティブ TTL は SOA から来る
通常の応答では、回答セクションのレコードごとに TTL があります。否定応答には回答レコードがないので、TTL を別の方法で運ぶ必要があります。RFC 2308 の 3 節は、権威サーバーが NXDOMAIN や NODATA を返すとき、そのゾーンの SOA レコードを authority セクションに含めなければならない(MUST) と定めています。この SOA レコードの TTL は SOA の MINIMUM フィールドと SOA レコード自身の TTL のうち小さいほう に設定され、その値がリゾルバーが否定応答をキャッシュできる時間になります。
MINIMUM フィールドは、かつて複数の意味で使われていました。RFC 2308 の 4 節は「ゾーン内の全レコードの最小 TTL」という本来の意味を廃止し、「TTL が書かれていないレコードの既定 TTL」という使い方については、代わりにマスターファイルに $TTL ディレクティブを追加しました。そのうえで MINIMUM の意味を否定応答の TTL と新たに定めています。名前は MINIMUM ですが、今はネガティブキャッシュの時間を決める値です。
キャッシュされた否定応答の TTL は通常の応答と同じように減っていき、0 になったらもう使ってはいけません(MUST NOT、5 節)。キャッシュから否定応答を返すときは、キャッシュにあった時間だけ減らした TTL で SOA を付ける必要があります(6 節)。RFC 2308 の 10 節の例では、MINIMUM が 1200 秒のゾーンで存在しない名前を問い合わせると、最初の応答の SOA の TTL は 1200、10 分後にキャッシュから返された応答では 600 になっています。リゾルバーが示す SOA の TTL は残り時間として読めます。
ここから 2 つのことがわかります。
- 否定応答の有効期間は、リゾルバーがその応答を受け取った時点で決まります。あとで MINIMUM を下げても、すでにキャッシュされたエントリーは受け取ったときの TTL のまま減っていきます。
- 新しい名前を作る予定があるなら、そのゾーンの SOA の MINIMUM と SOA の TTL のうち小さいほうが、「事前に問い合わせられていた場合に最悪どれだけ待つか」の目安になります。リゾルバーが独自の上限を設けていれば、それより短くなることがあります。
SOA のない否定応答はキャッシュすべきではありません(SHOULD NOT、5 節)。TTL が減っていく根拠がないと、互いをフォワーダーに指定した 2 台のサーバーの間などで、否定応答が TTL をリセットされながら回り続けるおそれがあるためです。
リゾルバー側の上限
RFC 2308 の 5 節は、リゾルバーがネガティブキャッシュの期間に上限を設けるのが妥当だとし、その理由としてプロトコルが最大 68 年までのキャッシュを許していることを挙げていました。同じ節は、その上限は通常の応答に設ける上限より大きくすべきではなく、調整できるのが望ましいと書き、1〜3 時間がうまく機能してきて既定値として適当であり、1 日を超える値は問題があったという経験も記しています。これは 1998 年の文書の推奨です。
68 年という前提はその後変わりました。2020 年の RFC 8767 の 4 節は RFC 1035 の TTL の定義を改め、最上位ビットが立った TTL の値を 0 ではなく正の値として解釈するようにし、TTL の値には数日から数週間程度の上限を設けるべきだ(SHOULD)と定めました。推奨される上限は 604,800 秒(7 日)です。同じ節は、RFC 2181 の 8 節の 31 ビットが許していた 68 年ではなく 7 日を提案したのは、主要な最新のリゾルバーの慣行を反映したものだと説明しています。現在の各リゾルバーが実際にどんな上限を使っているかは製品、バージョン、設定によって異なるので、この記事では扱いません。
NXDOMAIN はその下の名前も存在しないという意味
RFC 8020 は NXDOMAIN の意味を明確にしました。ドメイン名は木構造なので、あるノードが存在しなければ、その下のサブツリー全体も存在しません。2 節は、反復問い合わせを行うキャッシュリゾルバーが NXDOMAIN を受け取ったら、それをキャッシュし、そのノードとその下のすべての名前を到達不能とみなし、以降その下の名前への問い合わせにも NXDOMAIN で答えるべきだ(SHOULD)と定めています。これを NXDOMAIN cut と呼びます。3.2 節は RFC 2308 の 5 節の文を改め、元の QNAME の下位の名前への問い合わせにも、キャッシュした NXDOMAIN を返せるようにしました。
RFC 8020 の例はこうです。存在しない foo.example を問い合わせて NXDOMAIN を受け取ったリゾルバーは、続いて来た bar.foo.example の問い合わせを権威サーバーに送らず、すぐに NXDOMAIN で答えられます。逆に最初の問い合わせが bar.foo.example だった場合、その NXDOMAIN は baz.foo.example について何も教えてくれません。一緒に届いた SOA の所有者名から、もっと上の名前まで存在しないと推論してもいけません(付録 A)。SOA はゾーンの頂点を示すだけで、存在するいちばん近い名前を示すわけではないからです。
実際に問題になる例を 1 つ挙げます。example.com ゾーンに dev.example.com がまだなかった時点で誰かが dev.example.com を問い合わせ、そのあとで api.dev.example.com のレコードを追加したとします。NXDOMAIN cut に従うリゾルバーは、dev.example.com の NXDOMAIN がキャッシュに残っている間、api.dev.example.com にも NXDOMAIN で答えることがあります。新しく作った名前を一度も問い合わせていなくても、そうなります。
いくつか条件があります。
- このルールは MUST ではなく SHOULD です。RFC 8020 の 6 節は、キャッシュを木ではない構造(たとえば辞書)で実装したリゾルバーには、このルールに従わない理由があると説明しています。1 節は、2016 年の発行当時に知られていたほとんどのリゾルバーが、キャッシュした不存在を下位の名前が存在しない証拠とはみなしていなかったと書いています。上の状況がすべてのリゾルバーで起きるとは言えません。
- NXDOMAIN cut の下にすでにキャッシュされたデータがあれば、リゾルバーはその TTL が切れるまで答え続けてもかまいません(MAY、2 節)。
- DNSSEC の検証を行うリゾルバーは、応答が DNSSEC で検証された場合にだけ NXDOMAIN cut を適用してもかまいません(MAY、2 節)。
- 下位の名前はあるものの自分自身にはレコードがない名前(Empty Non-Terminal。上の例でレコードを追加した後の
dev.example.com)への正しい応答は、NXDOMAIN ではなく NODATA です(3.1 節)。5 節は、そうした名前に NXDOMAIN で答える権威サーバーは最初から誤っていると述べています。
サーバーの失敗は別にキャッシュされる
NXDOMAIN と NODATA は、サーバーが「存在しない」という役に立つ応答を返した場合です。RFC 9520 の 2 節は、この 2 つは名前解決の失敗(resolution failure) ではないと明言し、名前解決の失敗を別に定義しています。利用できるどのサーバーも、ある <name, type, class> について役に立つ応答を返さなかった場合です。例として SERVFAIL、REFUSED、タイムアウトや到達不能、委任のループ、別名(CNAME)のループ、DNSSEC の検証失敗、FORMERR などが挙げられています。
RFC 2308 の 7 節は、こうした応答には望ましい TTL を載せる方法がないと指摘し、サーバーの失敗と応答しないサーバーのキャッシュを任意としたうえで、5 分を超えないよう定めていました。2023 年の RFC 9520 はこれを強化しています。
- リゾルバーは名前解決の失敗をキャッシュしなければなりません(MUST、3.2 節)。キャッシュされた失敗に一致する問い合わせが来たら、エントリーが期限切れになるまで、対応する外部への問い合わせを送ってはいけません。
- キャッシュ期間は最短 1 秒、最長 5 分です(3.2 節)。最短期間は運用者が設定できるべきで(SHOULD)、失敗が続くなら指数的または線形のバックオフで期間を延ばすべきです(SHOULD)。5 秒から始めて延ばす例が出てきますが、これはあくまで例です。
- 同じサーバーアドレスに同じトランスポートで同じ問い合わせを再試行するのは 2 回まで、つまり合計 3 回までです(3.1 節)。別のサーバーや別のトランスポートで問い合わせ直すことは妨げられていません(2 節、3.1 節)。
まとめると、「存在しない名前」は SOA で決まる時間、「サーバーが答えられなかった状態」はリゾルバーが決める 1 秒〜5 分の間キャッシュされます。権威サーバーを直した後もしばらく SERVFAIL が続くなら後者かもしれず、その時間は RFC 上 5 分を超えません。
古いデータの提供(serve-stale)との関係
RFC 8767 は、権威サーバーに届かないときに期限切れのデータを例外的に使えるようにした文書です。4 節は、権威サーバーが AA ビットを立てた NoError または NXDomain の応答を返したら、それでデータが更新されたとみなさなければならない(MUST)と定めています。それ以外の RCODE は更新の失敗とみなし、以前の状態をそのまま保つべきです(SHOULD)。そのため、名前を削除した後に権威サーバーが AA ビットを立てた NXDOMAIN を返せば、serve-stale を使うリゾルバーもその応答を更新として受け入れます。6 節は、以前あった名前に対する NXDomain は間違いかもしれないものの、運用者の意図を見分ける方法がないため、エラーとしては扱わないと説明しています。
変更する前に確認すること
- 新しい名前を作るゾーンの SOA の MINIMUM と SOA レコードの TTL を見ます。小さいほうが、否定応答がキャッシュされうる最長の時間です。
- 名前を公開する前に試しに問い合わせること自体が、その時間分の NXDOMAIN をキャッシュに残すことがあります。親の名前がない状態で問い合わせていた場合は、NXDOMAIN cut に従うリゾルバーでは、その下の名前まで影響を受けることがあります。
- 既存の名前にタイプを追加するだけなら、影響を受けるのはそのタイプの NODATA だけです。
- SERVFAIL やタイムアウトはネガティブキャッシュではなく名前解決の失敗のキャッシュの問題で、RFC 上の上限は 5 分です。
参考にした RFC
- RFC 2308 — Negative Caching of DNS Queries (DNS NCACHE)(1998 年):1 節(NXDOMAIN と NODATA の用語)、2 節(否定応答の形)、3 節(権威サーバーの SOA を含める義務と TTL)、4 節(SOA の MINIMUM フィールドの再定義、
$TTL)、5 節(キャッシュのキー、TTL の減少、SOA のない応答、リゾルバーの上限)、6 節(キャッシュから答えるときの TTL)、7 節(サーバーの失敗、応答しないサーバー)、10 節(例)。 - RFC 8020 — NXDOMAIN: There Really Is Nothing Underneath(2016 年):1 節(背景)、2 節(NXDOMAIN cut のルールと例外)、3.1 節(Empty Non-Terminal には NODATA)、3.2 節(RFC 2308 の 5 節の改訂)、5 節、6 節、付録 A。
- RFC 9520 — Negative Caching of DNS Resolution Failures(2023 年):2 節(名前解決の失敗の定義と例)、3.1 節(再試行の回数)、3.2 節(失敗キャッシュの義務、1 秒〜5 分、バックオフ)。
- RFC 8767 — Serving Stale Data to Improve DNS Resiliency(2020 年):4 節(TTL の定義の改訂と 604,800 秒の推奨上限、NoError、NXDomain の応答を更新とみなすルール)、6 節。
この記事は標準文書のルールだけを扱っています。実際のリゾルバーのネガティブキャッシュの上限、NXDOMAIN cut に対応しているかどうか、失敗キャッシュの期間は製品、バージョン、設定によって異なるので、使っているリゾルバーのドキュメントを確認してください。リンクと内容は2026年10月9日に確認しました。