【DNS入門 第3回】名前解決の流れ ― 再帰と反復、キャッシュとTTL、フォワーディング

DNS サーバー
スポンサーリンク
スポンサーリンク

「DNSを変更したのに、まだ古いアドレスに行くんですけど…」
「レコードを追加したのに引けない。再起動したら引けた」

DNSの障害相談で、いちばん多いのがこのタイプです。原因のほとんどは、キャッシュとTTLの仕組みにあります。

第1回では、キャッシュDNSがルート→TLD→担当ゾーンと紹介をたどって答えを見つける流れを見ました。第3回では、その裏側をもう一段詳しく見ていきます。キャッシュDNSはどう答えを探し、どれだけの間覚えておくのか。そして、PCやサーバーのOSはどの順番で名前を調べているのかです。


再帰問い合わせと反復問い合わせ

問い合わせには2つの種類があります。

PCはキャッシュDNSに再帰(RD=1)で問い合わせ、キャッシュDNSはルート・jp・example.jpに反復で問い合わせることを、電話のたとえとともに示す図
  • 再帰問い合わせ:「最後まで調べて、答えだけ返してください」という頼み方。スタブリゾルバーがキャッシュDNSサーバーに、ヘッダーのRD(Recursion Desired)ビットを立てて出します。
  • 反復問い合わせ:「知っている範囲で答えてください」という頼み方。キャッシュDNSサーバーがルートやTLD、権威DNSサーバーに出します。

反復問い合わせを受けた側は、答えを知っていれば答えを、知らなければ次に聞くべきサーバーの紹介を返し、問い合わせた側が自分で次へ進みます。

電話のたとえでは、再帰は「調べて折り返し電話をください」、反復は「うちでは分からないので、この番号にかけてください」です。キャッシュDNSサーバーは、再帰を受けて反復を繰り返す存在です。依頼を受けるのは1回ですが、キャッシュDNSは何度も聞きに行きます。

一方、権威DNSサーバーは再帰を頼まれても調べに行かず、応答のRA(Recursion Available)ビットも立てません。digで権威DNSに聞いたとき、flagsにraがないのはこのためです。

ポイント
・再帰は「最後まで調べて」、反復は「知っている範囲で答えて」
・スタブ→キャッシュDNSは再帰、キャッシュDNS→権威DNSは反復
・権威DNSは再帰をしない。応答にRAビットが立たない


ルートヒントとプライミング

キャッシュDNSサーバーがルートから調べ始めるには、ルートサーバーのアドレスを最初から知っている必要があります。この一覧がルートヒントで、ソフトウェアに同梱されているほか、IANAがnamed.rootというファイルで配布しています。

キャッシュDNSがルートヒントを手がかりにa.root-servers.netへ「.のNS?」と問い合わせ、最新のルートサーバー一覧をキャッシュすることを示す図

ただし、ルートヒントはあくまで手がかりです。キャッシュDNSサーバーは起動時や、キャッシュしたルートのNSの期限が切れたときに、ヒントに載ったサーバーの1つにルート(.)のNSを問い合わせ、最新のルートサーバーの一覧を取り直します。これをプライミングと呼び、RFC 9609(2025年、RFC 8109を置き換え)に手順が定められています。

そのため、ヒントの一部が古くても名前解決はできます。とはいえ、2023年11月にb.root-servers.netのアドレスが変わったように、ルートサーバーのアドレスはまれに変わります。ソフトウェアとヒントは最新に保ちましょう。


キャッシュとTTL

キャッシュDNSサーバーは、調べた答えをTTL(Time To Live、生存時間)の間だけ覚えておき、同じ問い合わせにはキャッシュから答えます。

TTLは、ゾーンの管理者がレコードごとに秒で決める値で、「この答えは何秒まで使ってよい」という有効期限です。キャッシュにより応答は速くなり、上位への問い合わせも大きく減ります。

1回目のwww.example.jpは3か所に聞き、2回目のmail.example.jpは紹介を覚えているので1か所、3回目はキャッシュから即答することと、キャッシュの中身の例を示す図

ここで大事なのは、キャッシュされるのは最終的な答えだけではないことです。途中で得た「jpのサーバーはここ」「example.jpのサーバーはここ」という紹介もキャッシュされます。そのため、次にmail.example.jpを引くときは、いきなりexample.jpの権威DNSサーバーに聞けます。

  • キャッシュDNSサーバーが返すTTLは残り時間で、時間とともに減る(第1回で見た「259」がこれ)
  • 極端に長いTTLは、キャッシュDNSサーバー側の上限で切り詰められる(BINDの既定は1週間、Unboundは1日)

ポイント
・TTLは権威側が決める「何秒まで使ってよいか」という有効期限
・最終的な答えだけでなく、途中の紹介(NS)もキャッシュされる
・キャッシュDNSが返すTTLは残り時間。長すぎるTTLは上限で切られる


TTLの時間経過と変更の反映

TTLは「変更がいつ反映されるか」を左右します。

TTL 3600秒のレコードを10:20に変更したとき、10:00にキャッシュしたキャッシュDNS Aは11:00まで、10:15にキャッシュしたBは11:15まで旧アドレスを返し、新旧が混在することを示すタイムライン

www.example.jpのAレコードのTTLが3600秒(1時間)で、キャッシュDNSサーバーAが10:00にそれをキャッシュしたとします。

  • 10:20に権威DNSサーバーでアドレスを変えても、Aは11:00にTTLが切れるまで古いアドレスを返し続けます。
  • 10:15にキャッシュしたキャッシュDNSサーバーBなら、11:15まで古いままです。

変更が全員に行き渡るまでには最大でTTLの時間がかかり、その間は新旧の答えが混在します。

よく「DNSの変更が浸透する」と言いますが、実際には変更が伝わっていくのではありません。各地のキャッシュの期限切れを待っているのです。この理解があるだけで、移設作業の計画の立て方が変わります。

そのため、移設などの前にはTTLを短くしておくのが定石です(手順は第7回)。なお、ブラウザーやJavaなどのアプリケーションが独自のキャッシュを持つ場合もあります。


ネガティブキャッシュ:「存在しない」も覚える

冒頭の「追加したのに引けない。再起動したら引けた」の正体がこれです。

「その名前は存在しない(NXDOMAIN)」や「名前はあるが、その種類のレコードはない(NODATA)」という否定の答えもキャッシュされます。これをネガティブキャッシュと呼び、RFC 2308で定められています。

new.example.jpのNXDOMAIN応答に添えられたSOAのTTLとMINIMUMの小さいほう(900秒)が否定の答えを覚える時間になり、レコード追加後もしばらく「存在しない」が返り続けることを示す図

否定の答えにはSOAが添えられ、キャッシュする時間は、SOAのMINIMUMとSOA自身のTTLの小さいほうです。

図の例では、10:00に誰かがnew.example.jpを引いてNXDOMAINがキャッシュされ、10:05にレコードを追加しても、キャッシュには届きません。10:15まで「存在しない」が返り続けます。

MINIMUMの意味は変わった

注意したいのは、MINIMUMの意味が変わっていることです。

  • RFC 1035では「レコードの既定のTTL」
  • RFC 2308で「否定の答えをキャッシュする時間」に変わった

古い手順書のまま86400(1日)にしていると、レコードの追加前に誰かが引いた「存在しない」が長く残り、「追加したのに引けない、再起動したら引けた」という事態になります。RFC 2308は1〜3時間を妥当とし、1日超は問題があるとしています。キャッシュDNS側にも上限があります(既定でBINDは3時間、Unboundは1時間)。

ポイント
・「存在しない」という否定の答えもキャッシュされる
・保持時間は、SOAのMINIMUMとSOA自身のTTLの小さいほう
・MINIMUMの意味は変わった。古い86400のままにしない


QNAME最小化:必要な分だけ聞く

従来のキャッシュDNSサーバーは、ルートにもTLDにも、www.sales.example.jpという完全な名前をそのまま問い合わせていました。

しかし、ルートが知る必要があるのはjpの担当だけで、jpのサーバーにはexample.jpの担当が分かれば十分です。完全な名前を送ると、利用者が見ようとしているサイトを、必要以上に多くのサーバーへ伝えてしまいます。

従来はすべての問い合わせ先にwww.sales.example.jpを送っていたが、QNAME最小化ではjp、example.jp、sales.example.jpとラベルを1つずつ増やして聞くことを示す図

QNAME最小化(RFC 9156、2021年)は、各段階で必要なラベルだけを問い合わせる方法です。ルートにはjp、jpのサーバーにはexample.jpだけを聞き、最後に担当の権威DNSサーバーへ完全な名前を聞きます。

現在はBIND(relaxedモード)やUnboundなど主要な製品で既定で有効です。ただし、途中の名前に正しく答えない権威DNSサーバーがあると失敗することがあり、「特定のドメインだけ引けない」ときの確認点になります。


フォワーディング

フォワーダーは、受け取った問い合わせを自分では調べず、指定した別のDNSサーバーへ再帰問い合わせとして転送するサーバーです。

社内LANのADのDNS(フォワーダー)がFWを越えてDMZの共用キャッシュDNSへ再帰1回で転送し、共用キャッシュDNSがインターネットのルート・TLD・権威に反復で問い合わせる構成を示す図

企業では、ADや拠点のDNSサーバーをフォワーダーにし、外部の名前はDMZなどの共用キャッシュDNSサーバーへ転送する構成がよく使われます。外部へ問い合わせるサーバーを限定でき、キャッシュもよく効きます。キャッシュDNSサーバーとの違いは、自分で階層をたどるかどうかです。

「止めたのに引ける」の罠

注意点は、転送先が応答しないときの動きです。BINDの既定(forward first)やWindows ServerのDNSの既定では、転送に失敗すると自分でルートからたどります。そのため「転送先を止めたのに引ける」ことがあります。

ファイアウォールで外への53番を閉じているつもりでも、この迂回で思わぬ経路が使われていることがあるので要注意です。転送だけに限るには、次のように設定します。

  • BIND:forward only
  • Windows Server:ルートヒントを使う設定(UseRootHint)をオフ

ポイント
・フォワーダーは、上位のキャッシュDNSへ再帰問い合わせを1回投げる
・外部へ問い合わせるサーバーを集約でき、キャッシュも効きやすい
・転送に失敗すると自力で解決する製品がある(BIND・Windowsの既定)


条件付きフォワーディング

条件付きフォワーディングは、特定のドメインだけを、指定したDNSサーバーへ転送する機能です。それ以外は通常どおり(自分で解決、または通常のフォワーダーへ)扱います。

社内のキャッシュDNSが、corp.example.jpだけをADのDNSへ転送し、それ以外は通常どおり解決することを示す図

使いどころは次のような場面です。

  • 社内ADのドメイン
  • 統合した他社のドメイン
  • VPN先の拠点のドメイン
  • クラウドのプライベートゾーン(第10回)

ゾーン転送(第7回)をせずに、相手のDNSと疎結合のまま連携できるのが利点です。転送先の障害は、そのドメインだけ引けない形で現れます。

# BIND(named.conf)
zone "corp.example.jp" {
    type forward;
    forward only;
    forwarders { 192.0.2.53; 192.0.2.54; };
};
# Windows Server(PowerShell)
Add-DnsServerConditionalForwarderZone -Name "corp.example.jp" `
  -MasterServers 192.0.2.53,192.0.2.54 -ReplicationScope "Forest"

注意点が2つあります。

  • 2台が互いに転送し合うとループになる
  • DNSSECの検証を有効にしたキャッシュDNSでは、公開側に存在しない社内のサブドメインが検証に失敗することがある(第9回)

スタブリゾルバーの動き① Linux

ここからは、問い合わせを出す側(スタブリゾルバー)の動きです。まずLinuxです。

$ cat /etc/resolv.conf
nameserver 192.0.2.53
nameserver 192.0.2.54
search corp.example.jp example.jp
options timeout:2 attempts:2

$ grep ^hosts /etc/nsswitch.conf
hosts:          files dns
  • nameserver:問い合わせ先のキャッシュDNS。最大3つで、上から順に使う(options rotateで分散)。既定のタイムアウトは5秒、試行は2回
  • search:ドットの数がndots(既定1)未満の名前には、先にこのドメインを付けて試す。pc01→pc01.corp.example.jp→pc01.example.jpの順
  • nsswitch.confのhosts:行:調べる順番。files(/etc/hosts)→dns。mdns4_minimalやresolve(systemd-resolved)が入る環境もある
アプリがgetaddrinfoからnsswitch.confに従って/etc/hostsとresolv.confのnameserverを順に使う経路と、dig・nslookupがそれを通らず直接キャッシュDNSに聞く経路を示す図

ここで大事なのが、digやnslookupはこの仕組みを通らず、直接DNSに聞くということです。つまり、「digでは引けるのに、アプリからは引けない」ということが起こり得ます(hostsに古い行がある、など)。OSと同じ経路で確かめるにはgetent hosts 名前を使います。


スタブリゾルバーの動き② systemd-resolved

UbuntuやFedoraなどでは、systemd-resolvedがスタブリゾルバーの役割を担います。この場合、/etc/resolv.confの問い合わせ先はnameserver 127.0.0.53だけです。

アプリが127.0.0.53のsystemd-resolvedに聞き、systemd-resolvedがキャッシュを確かめてから、ens160とVPNのtun0それぞれの本当の問い合わせ先へ振り分けることを示す図

アプリケーションは自分自身の127.0.0.53で待ち受けるsystemd-resolvedに聞き、systemd-resolvedがキャッシュを確かめてから、本当のDNSサーバーへ問い合わせます。

  • 本当の問い合わせ先はresolvectl statusで確認する
  • インターフェースごとにDNSサーバーと担当ドメインを持てる。VPN接続中は社内のドメイン(~corp.example.jp)だけをVPN側に聞く、といった振り分けもできる
  • キャッシュの消去はresolvectl flush-caches
  • 127.0.0.54は、検証やLLMNR・mDNSを行わず、上位へほぼそのまま中継する別の待ち受け

「resolv.confを見たら127.0.0.53しか書いていない」と戸惑ったら、resolvectl statusを見ましょう。


スタブリゾルバーの動き③ Windows

Windowsのスタブリゾルバーは、次の順番で調べます。

Windowsのスタブリゾルバーが、DNSクライアントのキャッシュ、DNSサーバー、LLMNR、NetBIOS名前解決の順に調べることを示す図
順番調べる先内容
1DNSクライアントのキャッシュ過去の応答(否定の応答を含む)と、hostsファイルの内容
2DNSサーバーネットワーク設定のDNSサーバーへ。DNSサフィックス(プライマリ、接続固有、検索一覧)を付けて試す
3LLMNRDNSで引けない名前を、LANにマルチキャストで聞く
4NetBIOS名前解決WINS、またはブロードキャストで聞く
  • キャッシュを管理するのはDNS Clientサービス(Dnscache)。表示はipconfig /displaydns、消去はipconfig /flushdns(PowerShellではGet-DnsClientCache、Clear-DnsClientCache)
  • LLMNRとNetBIOSは、偽の応答で認証情報を盗む攻撃に悪用される。グループポリシーで無効にするのが一般的
  • Microsoftは2022年に、LLMNRとNetBIOSの名前解決を段階的に縮小してmDNSに寄せる方針を示した。Windows Server 2025では、NetBIOSによるドメインコントローラーの検索が既定で禁止されている

キャッシュには否定の応答も入るので、「さっき引けなかった名前が、DNSを直した後も引けない」ときは、クライアント側のipconfig /flushdnsも試してみてください。


serve-stale:障害時に古い答えを返す

最後に、少し新しめの仕組みです。

権威DNSサーバーが停止したり届かなくなったりすると、キャッシュのTTLが切れた時点で、そのドメインの名前は引けなくなります。serve-stale(RFC 8767、2020年)は、このような場合に限り、期限切れのキャッシュ(古い答え)を一時的に返してよいとする仕組みです。

権威DNSが停止中、serve-staleなしではTTL切れ後にSERVFAILになるが、serve-staleありでは古い答えをTTL 30秒で返し続けることを示すタイムライン
  • 返す答えのTTLは30秒、古い答えを保持する期間は1〜3日程度が推奨
  • たとえば権威DNSサーバーが1時間止まっても、利用者は直前まで使えていたアドレスでつながり続けられる
  • 一方で、アドレスを変えた直後に権威DNSサーバーが止まると、古い答えが返り続ける副作用もある
  • BINDではstale-cache-enableとstale-answer-enable、Unboundではserve-expiredで有効にする。どちらも既定では無効

「障害中なのに、あるDNSでは引ける」理由として知っておきましょう。同じ障害でも、serve-staleの設定しだいで利用者からの見え方が変わります。


考えてみよう

  1. 来週の夜、Webサーバーのアドレスを変えることになりました。今のTTLは86400秒です。いつ、何をしておくべきでしょうか。
  2. 新しく追加したレコードが「一部の人だけ引けない」と言われました。考えられる原因を、キャッシュDNS側とクライアント側に分けて挙げてください。
  3. 社内のDNSサーバーは、フォワーダーですか、自分でルートからたどるキャッシュDNSですか。転送先が止まったときはどう動きますか。

ヒント:この記事の「TTLの時間経過」「ネガティブキャッシュ」「フォワーディングの転送失敗時の動き」「スタブリゾルバー(クライアント側のキャッシュ)」が手がかりです。


まとめ

  • スタブ→キャッシュDNSは再帰、キャッシュDNS→権威DNSは反復
  • キャッシュされるのは答えだけでなく途中の紹介も。TTLは残り時間で減っていく
  • 「浸透」の正体はキャッシュの期限切れ待ち。移設の前にはTTLを短くする
  • 「存在しない」もキャッシュされる。SOAのMINIMUMを86400のままにしない
  • フォワーダーは転送失敗時に自力で解決することがある
  • digはOSの名前解決の経路を通らない。OSと同じ経路で確かめるならgetent hosts

次回は、DNSのメッセージの中身と、UDP・TCPなどによる運ばれ方を扱います。


連載「DNS入門」全12回

  1. DNSとは?名前解決の全体像と3つの登場人物
  2. ドメイン名の階層と委任
  3. 名前解決の流れ(この記事)
  4. DNSメッセージとトランスポート
  5. リソースレコード 前編
  6. リソースレコード 後編
  7. 権威DNSサーバーの運用
  8. コマンドで調べる
  9. DNSのセキュリティ
  10. クラウド・社内環境のDNS
  11. DNSトラブルシュート
  12. DNS設計演習

コメント

タイトルとURLをコピーしました