Old-School Networking / 2026 ・ No.09

いにしえのネットワーク入門

第9回 DNS ── 名前から住所を引く、インターネットの電話帳

公開

Wireshark の画面。リゾルバーで記録した DNS の一覧で、PC からの A expenses.example の問い合わせ、ルート(203.0.113.1)への問い合わせと答え、203.0.113.2、203.0.113.3 への問い合わせと答え、PC への答え A 203.0.113.20 が並ぶ。5番のルートの答えが選ばれ、明細の Authoritative nameservers に example: type NS, ns1.example、Time to live: 86400 (1 day) が見える
リゾルバーの記録。5番は、ルートが「expenses.example は知らない。.example のことは ns1.example に聞いて」と答えたところで、その紹介を1日(86400 秒)覚えておいてよいと書いてあります(筆者がクラウド上に作った練習用ネットワークで、2026年10月25日に記録したものを Wireshark 4.2.2 で開いて撮影。画面は英語のまま。ウインドウの上の帯と見出しは説明のために描き足したもの)

第8回まで、curl には --resolve で「expenses.example は 203.0.113.20」と教えていました。今回はそれをやめ、本物の仕組み、DNS に名前を引かせます。
練習用に、ルート・.example・expenses.example の3段の DNS サーバーと、プロバイダの役のリゾルバーを立てました。名前の木をたどる道のり、答えを覚えておく時間(TTL)、hosts との食い違い、DNS が止まったときの症状まで、実測で確かめます。

一

名前の層

新井前回の --resolve、本当はどうやって名前から住所がわかるんですか?

古井世界中の名前を1台が知っているわけではない。名前を木の形に分けて、枝ごとに担当を決めてある。知らなければ「あっちに聞いて」と紹介する。それをたどるんだ。

新井たらい回しじゃないですか。

古井そう、よくできたたらい回しだ。しかも、一度回った答えはしばらく覚えておく。

全12回の路線図(いまここ:第9回)

1 全体図 2 物理層 3 データリンク層 4 IP アドレス 5 ルーター 6 TCP 7 UDP・ソケット 8 TLS 9 DNS 10 HTTP 11 開発者の網 12 切り分け いまここ 全体図 第1層 第2層 第3層 第4層 第5・6層 第7層 実践
  • 名前の木 ── ルート、.example、expenses.example と、段ごとに担当がいる
  • リゾルバー ── PC の代わりに木をたどる。はじめては 0.166 秒(実測)
  • TTL とキャッシュ ── 覚えている間は 0 ミリ秒、切れたら聞き直し(実測)
  • 開発者の落とし穴 ── hosts と dig の食い違い、DNS が止まったときの症状(実測)

DNS は、TCP/IP の層で言えば第7層、アプリの層の仕組みです。それでもアプリの通信より先に必ず動くので、ここで扱います。練習用ネットワークは、PC とプロバイダのリゾルバー(Unbound)を線の手前に、3段の DNS サーバー(NSD)と申請のサーバーを、片道 20 ミリ秒のいたずら線の向こうに置きました。

二

名前の木

名前は木の形に分けられ、枝ごとに担当の DNS サーバーがいる

. ルート com jp example この回の主役 net … expenses 経費精算のゾーン www mail ns1 ルートのサーバー 203.0.113.1 .example のサーバー 203.0.113.2 expenses.example の 203.0.113.3 名前は右から読む:www . expenses . example . (最後の点がルート)

www.expenses.example は、右から読みます。いちばん右の見えない点がルート、その下に example、さらに expenses、最後に www。ルートの DNS サーバーは example の担当を知っていて、example の担当は expenses の担当を知っている。この「担当を知っている」ことを委任と呼びます。

本物のインターネットでは、ルートは a から m までの 13 の名前を持ち、12 の組織が運用しています。実際には同じ中身の写しが世界中に千台以上置かれていて、近くのものが答えます。この回の練習では、ルートも筆者が作りました(a.root.lab、203.0.113.1)。

三

リゾルバーがたどる道

PC は、木をたどる仕事を自分ではしません。家のルーターやプロバイダが用意したリゾルバー(キャッシュ DNS サーバー)に「expenses.example の住所は?」と1回聞くだけです。リゾルバーの側で記録しました。

# リゾルバーで記録:PC の1つの問い合わせのために、リゾルバーは3か所に順に聞いた(片道 20 ms の線の向こう)
  0.000                PC → resolver          A expenses.example
  0.000          resolver → root              NS <Root>
  0.041              root → resolver          NS <Root> NS a.root.lab A 203.0.113.1
  0.042          resolver → root              A expenses.example
  0.082              root → resolver          A expenses.example NS ns1.example A 203.0.113.2
  0.083          resolver → .example          A expenses.example
  0.124          .example → resolver          A expenses.example NS ns1.expenses.example A 203.0.113.3
  0.124          resolver → expenses.example  A expenses.example
  0.165  expenses.example → resolver          A expenses.example A 203.0.113.20 NS ns1.expenses.example A 203.0.113.3
  0.166          resolver → PC                A expenses.example A 203.0.113.20

PC は1回聞くだけ。たどるのはリゾルバー(実測の時刻)

PC リゾルバー ルート .example expenses ルートの確認 .example へ expenses へ 203.0.113.20 答え 0 166 PC は1回聞くだけ。たどるのはリゾルバーの仕事(片道 20 ms の線を3往復+最初の確かめ1往復)

リゾルバーは、まずルートが生きているかを確かめ(ルートの NS)、それからルートに聞きます。ルートの答えは「知らない。.example は ns1.example(203.0.113.2)に聞いて」という紹介です(表紙の写真)。.example も同じように expenses.example を紹介し、最後に expenses.example の DNS サーバーが 203.0.113.20 と答えました。線を4往復して 0.166 秒です。

同じ道のりを、PC から順にたどって見せてくれるのが dig +trace です。

# dig +trace:PC が自分でルートから順にたどる(← は答えた DNS サーバー)
pc$ dig +trace expenses.example
    .  86368  IN  NS  a.root.lab.
    ← 198.51.100.53 (198.51.100.53)
    example.  86400  IN  NS  ns1.example.
    ← a.root.lab (203.0.113.1)
    expenses.example.  3600  IN  NS  ns1.expenses.example.
    ← ns1.example (203.0.113.2)
    expenses.example.  30  IN  A  203.0.113.20
    expenses.example.  3600  IN  NS  ns1.expenses.example.
    ← ns1.expenses.example (203.0.113.3)
NOTE

本物のリゾルバーの多くは、ルートには「example のことだけ」、.example には「expenses.example のことだけ」と、必要な分だけ名前を見せて聞きます(QNAME minimisation)。この回は流れを見やすくするため、その設定を切っています。

四

覚えておく:TTL とキャッシュ

毎回 0.166 秒かけて木をたどっていたら、Web は遅くてたまりません。そこでリゾルバーは、答えを覚えておきます。どのくらい覚えてよいかは、答えについている TTL(秒)が決めます。expenses.example の住所は、練習のため 30 秒にしました。

# PC からリゾルバー(198.51.100.53)へ。答えの TTL(あと何秒覚えておくか)と、かかった時間
pc$ dig expenses.example @198.51.100.53
    expenses.example.  30  IN  A  203.0.113.20    168 ms   ← はじめて
    expenses.example.  29  IN  A  203.0.113.20      0 ms   ← 1 秒後
    expenses.example.  19  IN  A  203.0.113.20      0 ms   ← 10 秒後
    expenses.example.  10  IN  A  203.0.113.20      0 ms   ← 20 秒後
    expenses.example.  30  IN  A  203.0.113.20     44 ms   ← 30 秒後(切れた)

TTL が減っていき、切れたら聞き直す(実測)

0 s 10 s 20 s 30 s 168 ms TTL 30 0 ms TTL 19 0 ms TTL 10 44 ms TTL 30 青い線=答えをあと何秒覚えておくか(TTL) 赤い点はリゾルバーが聞き直したとき、青い点は覚えていた答えを返したとき 切れたあとは expenses.example にだけ聞く(紹介の答えは長く覚えている)
Wireshark のパケット一覧を2つ縦に並べたもの。上は、はじめての問い合わせで、リゾルバーがルート、203.0.113.2、203.0.113.3 と順に聞き、0.165845 秒に PC へ答えている。下は 30 秒後で、リゾルバーは 203.0.113.3 にだけ聞き、0.041326 秒に答えている
上がはじめての問い合わせ、下が答えの期限(30 秒)が切れたあとの問い合わせ。ルートと .example の紹介はまだ覚えているので、2回目は1か所に聞くだけで済みました(筆者がクラウド上に作った練習用ネットワークで、2026年10月25日に記録したものを Wireshark 4.2.2 で開いて撮影。画面は英語のまま。ウインドウの上の帯と見出しは説明のために描き足したもの)

覚えている間は 0 ミリ秒で、TTL は 29、19、10 と減っていきました。30 秒で切れると、リゾルバーは聞き直しますが、ルートと .example の紹介はまだ覚えている(TTL は1日と1時間)ので、expenses.example にだけ聞いて 0.044 秒でした。

POINT

サーバーの引っ越しで住所を変えるとき、古い答えは TTL が切れるまで世界中のリゾルバーに残ります。俗に「DNS の浸透待ち」と呼ばれるのは、この期限切れ待ちのことです。引っ越しの数日前に TTL を短くしておくのが定石です。

五

いろいろなレコード

DNS が答えるのは住所だけではありません。名前に結びつけた1行1行をレコードと呼び、種類があります。

# expenses.example のいろいろなレコード(数字は TTL、秒)
    expenses.example.  29  IN  A  203.0.113.20
    expenses.example.  30  IN  AAAA  2001:db8::20
    www.expenses.example.  300  IN  CNAME  expenses.example.
    expenses.example.  3600  IN  MX  10 mail.expenses.example.
    expenses.example.  3600  IN  TXT  "kiji practice zone for part 9"
    expenses.example.  3600  IN  NS  ns1.expenses.example.
種類意味開発者が出会う場面
A / AAAAIPv4 / IPv6 の住所サーバーの住所を登録する
CNAME別名。「この名前は、あの名前と同じ」www をドメインのてっぺんに向ける、クラウドのサービスに向ける
MXメールを受け取るサーバー(数字は優先順位)独自ドメインでメールを受ける
TXT自由な文字列ドメインの持ち主の確認、送信元の確認(SPF など)
NSこのゾーンの担当の DNS サーバードメインを買ったあと、使う DNS サービスを指定する
SOAゾーンの基本情報(「ない」答えの期限など)次の章

CNAME の名前には、ほかのレコードを置けません。ドメインのてっぺん(ここでは expenses.example そのもの)には NS や SOA が必ずあるので、てっぺんを CNAME にはできない、という決まりは知っておくとよいでしょう。

六

ない名前

# ない名前を聞く
pc$ dig nosuch.expenses.example
    status: NXDOMAIN
    expenses.example.  60  IN  SOA  ns1.expenses.example.  admin.expenses.example.  2026102501  1800  900  604800  60
# 「ない」という答えも、SOA の最後の数(60 秒)のあいだ覚えておく
    1回目: 40 ms    2回目: 0 ms

ない名前を聞くと、答えは NXDOMAIN(そんな名前はない)です。答えには SOA が添えられていて、その最後の数(60 秒)が「ない」という答えを覚えておいてよい時間です。2回目は 0 ミリ秒でした。打ち間違いの名前に何度アクセスしても、毎回木をたどらずに済みます。逆に、新しい名前を登録する前にうっかり引いてしまうと、「ない」をしばらく覚えられてしまいます。

七

アプリが名前を引くとき

いよいよ --resolve なしで、curl に申請を送らせます。リゾルバーのキャッシュを空にしてから2回続けました。

# curl で HTTPS の申請(--resolve なし)。リゾルバーのキャッシュを空にしてから2回
    1回目  namelookup 0.1667  connect 0.208  tls 0.252  total 0.294  (201)
    2回目  namelookup 0.0006  connect 0.041  tls 0.087  total 0.144  (201)
Wireshark のパケット一覧を2つ縦に並べたもの。どちらも PC で記録したもので、DNS の問い合わせと答えのあと、203.0.113.20 の 3443 番への SYN と Client Hello が続く。上は答えまで 0.166132 秒、下は 0.000145 秒
curl で HTTPS の申請を2回。1回目はリゾルバーが名前の木をたどったので 0.166 秒、2回目は覚えていた答えを返したので 0.0001 秒で、すぐにつなぎに行けました(筆者がクラウド上に作った練習用ネットワークで、2026年10月25日に記録したものを Wireshark 4.2.2 で開いて撮影。画面は英語のまま。ウインドウの上の帯と見出しは説明のために描き足したもの)

1回目は、名前を引くのに 0.167 秒。そのあと第6回の TCP、第8回の TLS と続きます。2回目は 0.0006 秒で、全体も 0.294 秒から 0.144 秒になりました。初めてのサイトがほんの少し遅いのは、こういうことです。

名前引きは、手前から順に探す

ブラウザ キャッシュ OS キャッシュ hosts ファイル リゾルバー キャッシュ DNS サーバー 木をたどる 左から順に探し、見つかったところで止まる 自分の PC の中 ネットワークの向こう hosts に古い住所が残っていると、DNS より先にそれが使われる dig は hosts を見ない。curl やブラウザと答えが食い違うことがある この回の curl の2回目は、リゾルバーのキャッシュで 0.0006 秒だった

アプリ(curl やブラウザ)は、DNS に聞く前に、手前の場所から探します。中でも hosts ファイルは、DNS より先に見られます。開発中に書いた1行が残っていると、こうなります。

# PC の hosts に、古い住所 203.0.113.21 が書き残されていたら
    /etc/hosts:  203.0.113.21  expenses.example
# OS の名前引き(hosts を先に見る)
pc$ getent ahostsv4 expenses.example
    203.0.113.21  STREAM  expenses.example
# dig(DNS にしか聞かない)
pc$ dig +short expenses.example
    203.0.113.20
# curl(OS の名前引きを使う)
    curl: (28) Failed to connect to expenses.example port 3443 after 3002 ms: Timeout was reached

dig は 203.0.113.20 と正しく答えるのに、curl は hosts の古い住所 203.0.113.21 へつなぎに行って、3 秒で時間切れになりました。dig は DNS にしか聞かないので、hosts を見ません。「dig では合っているのに、アプリだけつながらない」ときは、hosts と、OS やブラウザのキャッシュを疑いましょう。

八

DNS が止まると

# リゾルバーのプログラムが止まっている(「そこには誰もいない」と ICMP が返る)
    curl: (6) Could not resolve host: expenses.example
    total 0.0001 s
# リゾルバーまで届かない(線が切れている)
    curl: (6) Could not resolve host: expenses.example
    total 6.023 s

リゾルバーのプログラムだけが止まっている場合は、OS が「そこには誰もいない」(第7回の ICMP)と知らせるので、curl はすぐ Could not resolve host になりました。ところがリゾルバーまで届かない場合は、6 秒待たされてから同じエラーになりました。ここでは PC がリゾルバーの MAC を ARP で6回尋ねた分です。途中で消える場合は、Linux の既定(resolv.conf の timeout 5 秒、attempts 2 回)に従って、さらに長く待つこともあります。

POINT

DNS が止まると、住所で書いたものは動くのに、名前で書いたものがすべて止まります。利用者からは「ネットにつながらない」「遅い」に見えます。切り分けは、名前と住所の両方で試すのが第一歩です(第12回)。

九

DNS の中身を隠す

この回の記録はすべて、UDP の 53 番で、聞いた名前がそのまま読める DNS でした。第8回で、HTTPS にしても名前(SNI)が見えると書きましたが、DNS の問い合わせからも名前はわかります。

DNS の問い合わせを包む方法

PC リゾルバー UDP 53 ふつうの DNS:名前が丸見え この回の記録もすべてこれ PC リゾルバー DoT 853 DNS over TLS 第8回の TLS で包む PC リゾルバー DoH 443 DNS over HTTPS ふつうの Web の通信にまぎれる 隠しても、リゾルバー自身には名前がわかる。どのリゾルバーを信頼するかの問題 第8回の ECH と合わせて、ようやく「どこに行くか」を途中から隠せる

そこで、DNS の問い合わせ自体を TLS で包む DoT(853 番)や、HTTPS で包む DoH(443 番)が使われるようになりました。いまの主なブラウザや OS は、設定で DoH を使えます。ただし、リゾルバー自身には名前が見えるので、どのリゾルバーを信頼するかは別の問題として残ります。なお、答えが大きいと UDP から TCP に切りかえて聞き直すしくみもあり(第7回の 1232 バイト)、TCP の 53 番も DNS の番号です。

十

自分の PC で確かめる

調べたいことMacWindowsLinux
名前を引くdig example.comResolve-DnsName example.comdig example.com
道のりをたどるdig +trace example.com(nslookup で順に)dig +trace example.com
OS としての答え(hosts 込み)dscacheutil -q host -a name example.comping -n 1 example.comgetent ahosts example.com
使っているリゾルバーscutil --dnsipconfig /allresolvectl status
OS のキャッシュを消すsudo killall -HUP mDNSResponderipconfig /flushdnsresolvectl flush-caches

dig の答えの2列目が TTL です。同じ名前を何度か引いて、数が減っていくのを見てみましょう。

結 — 一枚まとめと、次回

  1. 名前は右から読む木。ルート → .example → expenses.example と、段ごとに担当がいる(委任)。
  2. PC はリゾルバーに1回聞くだけ。リゾルバーが紹介をたどり、はじめては線を4往復して 0.166 秒。
  3. 答えは TTL の間覚えておく。覚えている間は 0 ミリ秒、切れたら必要な所にだけ聞き直して 0.044 秒。
  4. A・AAAA・CNAME・MX・TXT・NS・SOA。てっぺんは CNAME にできない。
  5. ない名前(NXDOMAIN)も SOA の数だけ覚えておく。
  6. アプリは hosts を DNS より先に見る。dig は hosts を見ないので、食い違うことがある。
  7. リゾルバーまで届かないと、名前で書いたものはすべて、待たされたあと止まる。DoT・DoH で問い合わせを隠せる。

新井名前がわかって、つながって、鍵もかかって。やっと申請の中身の番ですね。

古井次回は HTTP。第1回からずっと送ってきた POST /api/expenses を、1行ずつ読む。

参考

記録は、筆者がクラウド上の Linux(Ubuntu 24.04、カーネル 6.18)にネットワーク名前空間で作った練習用ネットワークで、2026年10月25日に取ったものです。リゾルバーは Unbound 1.19.2(DNSSEC の検証と QNAME minimisation は切ってある)、ルート・.example・expenses.example の DNS サーバーは NSD 4.8.0 で、名前と住所はすべて説明用に予約されたもの、または練習用に作ったものです。リゾルバーと DNS サーバーの間は、第6回のいたずら線(片道 20 ミリ秒)です。表の数字はすべて、この記録とそのときのコマンドの出力から読んだ実際の値です。ルートサーバーの数は root-servers.org によります。登場人物は架空の人物です。

いにしえのネットワーク入門 第9回 — DNS / 2026.10

← 記事一覧へ