
DNS の仕組み入門 - 名前解決・レコード種別・TTL とキャッシュを理解する
Web サイトにアクセスするとき、私たちは example.com のようなドメイン名を打ち込みますが、実際に通信するには 93.184.x.x のようなIP アドレスが必要です。この変換をしているのが DNS(Domain Name System / ドメインネームシステム)です。「インターネットの電話帳」とよく例えられますが、その実体は世界中に分散した巨大な階層型データベースです。
この記事では、DNS の名前解決の仕組みを、一次ソースである RFC 1034 / 1035 をはじめとする各 RFC や IANA の情報を軸に整理します。レコード種別、解決の流れ、TTL とキャッシュ、そして DNSSEC や DoH/DoT といった近年の話題までを、Web 開発者・インフラ担当者向けに一通り押さえます。
DNS は階層型の分散データベース
DNS の中核となる概念は RFC 1034 で定義されています。ドメイン名の空間は木構造(ツリー)として表現され、各ノードに付いたラベルを、ノードからルートまでたどって連結したものがドメイン名になります。
- ラベルは1個あたり最大63オクテット
- ドメイン名全体は最大255オクテット
この木のいちばん上にあるのがルート(名前を持たない、空ラベルのノード)です。www.example.com. という表記の末尾のドット(.)がルートを表します。普段は省略しますが、これが完全修飾ドメイン名(FQDN)の正式な形です。
階層をたどると次のようになります。
- ルート: 最上位。どの TLD がどこにあるかを知っている
- TLD(Top Level Domain / トップレベルドメイン):
com、net、orgや、jp、ukなどの国別(ccTLD) - 権威サーバー(authoritative server):
example.comのように、実際のレコードの正解を持っているサーバー
ゾーンと権威
RFC 1034 では、名前空間のある部分について「正解」を持っているサーバーを権威(authority)と呼び、権威情報を管理する単位をゾーン(zone)と呼びます。「ドメイン」が木構造上の部分木全体を指すのに対し、「ゾーン」は1つの組織が実際に管理する範囲を指す、という違いがあります。たとえば example.com のゾーンを管理しつつ、sub.example.com を別ゾーンとして切り出して別の組織に委任(delegation)する、といったことができます。
NOTE
ルートゾーンに「正解」を提供する権威サーバー群がルートサーバーです。IANA によれば、ルートサーバーは a から m までの13系統の識別子(letter)で運用されており、Verisign、USC、Cogent、NASA、ISC、RIPE NCC、ICANN、WIDE Project など複数の組織が分担しています。「13台しかない」という誤解がありますが、実際には各系統が anycast によって世界中の多数の物理サーバーに展開されており、IANA も「世界中の数百のサーバーからなるネットワーク」だと説明しています。13というのは、後述の DNS メッセージサイズの制約に由来する識別子の数です。
名前解決に登場する2種類のリゾルバ
名前解決を担うのがリゾルバ(resolver)です。役割の異なる2種類があります。
| 種類 | 役割 | 例 |
|---|---|---|
| スタブリゾルバ | アプリ・OS に組み込まれた最小限のリゾルバ。自分では解決せず、再帰リゾルバに丸投げする | OS の名前解決機能、ブラウザ |
| 再帰リゾルバ(フルサービスリゾルバ) | スタブから依頼を受け、ルートから順にたどって最終的な答えを取得し、キャッシュも持つ | ISP の DNS、8.8.8.8、1.1.1.1 など |
普段アプリが行うのは、スタブリゾルバから再帰リゾルバへの再帰問い合わせ(recursive query)です。「最後まで解決して答えだけ返して」という依頼です。一方、再帰リゾルバが権威サーバー群に対して行うのは反復問い合わせ(iterative query)で、「知らなければ次にどこへ聞けばよいか教えて」というやり取りを繰り返します。
RFC 1034 でも、データグラム(UDP)アクセスでは反復方式が好まれるとされ、再帰モードはサーバーが任意で提供する機能だと位置づけられています。
名前解決の流れ(キャッシュが空の場合)
www.example.com を初めて解決する場合、再帰リゾルバは次のように動きます。
ポイントは、再帰リゾルバがルートから順に下に降りていくことと、途中のサーバーは「最終的な答え」ではなく「次に聞くべきサーバー(委任先の NS)」を返す、という点です。最終的な答えを返すのは、そのゾーンに対して権威を持つサーバーだけです。
2回目以降は、リゾルバが持つキャッシュから即座に答えられるため、ルートまで毎回たどることはありません。これが DNS のスケーラビリティを支えています。
リソースレコード(RR)の基本
DNS が保持するデータの単位がリソースレコード(Resource Record / RR)です。RFC 1034 によれば、各 RR は次の要素を持ちます。
- owner(所有者名): そのレコードが属するドメイン名
- type(型): A、MX など、レコードの種類
- class(クラス): ほぼ常に
IN(Internet) - TTL: そのレコードをキャッシュしてよい秒数
- RDATA: 型ごとの実データ(IP アドレスやホスト名など)
TTL について RFC 1034 は「主にリゾルバが RR をキャッシュする際に使う、生存時間」と定義しています。TTL とキャッシュは後ほど詳しく扱います。
主なレコード種別
実務で出会うレコード種別を整理します。型コードや定義 RFC も併記します。
| 種別 | 役割 | 主な定義 |
|---|---|---|
| A | ドメイン名を IPv4 アドレスに対応づける | RFC 1035 |
| AAAA | ドメイン名を IPv6 アドレスに対応づける(型28、128ビット) | RFC 3596 |
| CNAME | 別名(alias)。owner を別の正規名に転送する | RFC 1034 / 1035 |
| NS | そのゾーンの権威ネームサーバーを示す。委任に使う | RFC 1035 |
| SOA | ゾーンの起点。シリアル番号や各種タイマー、ネガティブキャッシュ TTL を持つ | RFC 1035 / 2308 |
| MX | メールの宛先サーバー(preference 値付き) | RFC 1035 |
| TXT | 任意のテキスト。SPF/DKIM/ドメイン所有確認などに使われる | RFC 1035 |
| PTR | 逆引き。IP アドレスからドメイン名を引く | RFC 1035 |
| CAA | どの認証局(CA)に証明書発行を許すかを宣言する | RFC 8659 |
| SRV | サービスの場所(ホスト・ポート)を示す。priority/weight/port/target | RFC 2782 |
いくつか補足します。
- CNAME には重要な制約があります。RFC 1034 は CNAME を「owner を別名として扱う」と定義しており、原則として1つの名前に CNAME と他のレコードを同居させられません。とくにゾーン頂点(apex、
example.comそのもの)には SOA や NS が必須なので、apex に CNAME は置けません。 - CAA(RFC 8659)は、ドメイン名の保有者が「この証明書はこの CA からだけ発行を許す」と宣言できるレコードで、CA が誤発行を減らすための仕組みです。
- SRV(RFC 2782、型33)は
_Service._Proto.Nameという名前で、priority・weight・port・target を返します。weight と port はそれぞれ0〜65535の範囲です。 - PTR による逆引きは、
in-addr.arpa(IPv4)/ip6.arpa(IPv6)という特別なドメイン以下で管理されます。
ゾーンファイルの例
権威サーバーに置くゾーンの設定(ゾーンファイル)の抜粋イメージです。RFC 2606 で予約されている example.com を使います。
$ORIGIN example.com.
$TTL 3600
@ IN SOA ns1.example.com. admin.example.com. (
2026063001 ; serial
7200 ; refresh
3600 ; retry
1209600 ; expire
300 ) ; minimum (ネガティブキャッシュ TTL)
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
@ IN A 93.184.216.34
@ IN AAAA 2606:2800:21f:cb07:6820:80da:af6b:8b2c
www IN CNAME example.com.
@ IN MX 10 mail.example.com.
@ IN TXT "v=spf1 include:_spf.example.com -all"
@ IN CAA 0 issue "letsencrypt.org"SOA の serial はゾーンの版数で、セカンダリ(スレーブ)が更新を検知するのに使います。minimum(ここでは300秒)は、後述のネガティブキャッシュの TTL に使われます。
TTL とキャッシュ
DNS のパフォーマンスと整合性は TTL(Time To Live)で制御されます。リゾルバは取得したレコードを TTL の秒数だけキャッシュし、その間は同じ問い合わせに対して権威サーバーへ聞き直さず即答します。TTL が経過するとキャッシュは破棄され、次回は再取得します。
実務上の勘所は次のとおりです。
- TTL を短くすると、レコード変更(サーバー移転など)が速く反映されますが、問い合わせ回数が増えます。
- TTL を長くすると、キャッシュが効いて高速・低負荷ですが、変更の反映が遅れます。
- 移転の前にあらかじめ TTL を短くしておく(例: 数日前に300秒へ下げる)と、切り替え当日の浸透を速くできます。切り替え後に元へ戻します。
このキャッシュの考え方は HTTP/CDN のキャッシュ制御とよく似ています。レイヤーは違いますが「TTL で鮮度と負荷のトレードオフを取る」点は共通なので、CDN キャッシュと s-maxage の実践ガイド も合わせて読むと理解が深まります。
ネガティブキャッシュ(RFC 2308)
「存在しない」という事実もキャッシュされます。これをネガティブキャッシュと呼び、RFC 2308 が定めています。存在しない名前への応答(NXDOMAIN)や、名前はあるが該当型がない応答(NODATA)を毎回権威まで聞きに行くのは無駄なので、一定時間キャッシュします。
そのキャッシュ時間(TTL)は、SOA レコードの MINIMUM フィールドと SOA 自身の TTL のうち小さいほうで決まります。RFC 2308 は、かつて多義的だった SOA の MINIMUM フィールドを「ネガティブ応答に使う TTL」として再定義しました。先ほどのゾーンファイル例で minimum 300 としていたのがこれにあたります。
NOTE
新しいレコードを追加した直後にうまく引けないとき、ネガティブキャッシュが原因のことがあります。直前に「存在しない」と答えられた結果が、MINIMUM の秒数だけ各リゾルバにキャッシュされているためです。
DNS メッセージとポート53、UDP/TCP
DNS の通信はポート53を使い、UDP と TCP の両方を用います。
- 通常の問い合わせは UDP が既定です。1往復で軽量に終わります。
- TCP が使われるのは、応答が大きい場合や、信頼性・順序保証が要る場合です。代表例はゾーン転送(AXFR/IXFR)と、UDP 応答が大きすぎて切り詰め(truncation)が起きたケースです。
オリジナルの DNS(RFC 1035)では、UDP メッセージは512バイトまでという制限がありました。これを超える応答は切り詰められ、ヘッダの TC(truncated)ビットが立ちます。TC ビットを見たクライアントは、TCP で再問い合わせします。なお RFC 7766 は、汎用 DNS 実装は UDP と TCP の両方をサポートしなければならない(MUST)と定めています。「DNS は UDP だけ」というのは誤りで、TCP も必須です。
EDNS0(RFC 6891)
512バイト制限は、DNSSEC の署名や複数の IPv6 アドレスを返す現代の用途には小さすぎます。これを拡張するのが EDNS0(Extension Mechanisms for DNS、RFC 6891)です。
EDNS0 は OPT 疑似レコード(型41)を問い合わせに含めることで、「自分はこのサイズまでの UDP 応答を受け取れる」とクライアント側の最大ペイロードサイズを通知します。これにより、512バイトを超える応答も TCP に切り替えずに UDP で受け取りやすくなります。OPT レコードはキャッシュされず、その1回のやり取りのための制御情報を運ぶ、という点が特徴です。
DNSSEC: 改ざん検知のための署名(RFC 4033 ほか)
素の DNS には、応答が本物か検証する仕組みがありません。これを補うのが DNSSEC(DNS Security Extensions)で、RFC 4033 / 4034 / 4035 が中核です。
RFC 4033 は DNSSEC を「DNS にデータ起源認証(data origin authentication)とデータ完全性(data integrity)を加えるもの」と定義しています。重要なのは、DNSSEC は暗号化(秘匿性)の仕組みではないことです。RFC 4033 自身が「機密性やアクセス制御を提供するものではない」と明言しています。あくまで「この応答は改ざんされておらず、正規のゾーンから来た」ことを公開鍵署名で検証する仕組みです。
DNSSEC が導入する主なレコードは次のとおりです。
| 種別 | 役割 |
|---|---|
| RRSIG | レコードセットに対する署名 |
| DNSKEY | ゾーンの公開鍵 |
| DS | 親ゾーンに置く、子の鍵のハッシュ(委任署名) |
| NSEC | 「存在しないこと」を認証付きで示す |
検証は信頼の連鎖(chain of trust)で行われます。リゾルバはルートの鍵(トラストアンカー)を起点に、DS -> DNSKEY の連鎖を下へたどり、各委任を検証しながら目的のゾーンまで到達します。
WARNING
DNSSEC は秘匿性を提供しません。問い合わせ内容そのものを盗聴から守りたい場合は、別レイヤーである後述の DoH/DoT が必要です。両者は目的が異なるので混同しないでください。
DoH と DoT: 問い合わせの暗号化
素の DNS は平文で流れるため、経路上の第三者に問い合わせ内容が見えてしまいます。これを暗号化するのが DoT と DoH です。
- DoT(DNS over TLS、RFC 7858): DNS の通信を TLS で包みます。専用のポート853を使います。TLS により経路上の盗聴・改ざんを防ぎます。
- DoH(DNS over HTTPS、RFC 8484): DNS の問い合わせ・応答を HTTPS に載せます。
application/dns-messageというメディアタイプを使い、GET/POST の両メソッドに対応します。ポート443で他の Web トラフィックに紛れるため、観測・妨害がより困難になります。
どちらも目的は問い合わせ内容のプライバシー保護と経路上での改ざん防止です。DNSSEC が「データの真正性(改ざん検知)」を担うのに対し、DoH/DoT は「通信の秘匿性」を担う、という役割分担で覚えると整理できます。なお TLS によるホスト名検証など、TLS 自体の落とし穴については Node.js の TLS ホスト名検証バイパス も参考になります。
dig で実際に確認する
手元で挙動を確かめるには dig コマンドが便利です。A レコードを引く例です(出力は実行環境により異なります)。
dig example.com A +noall +answerexample.com. 3600 IN A 93.184.216.34左から owner、TTL、class(IN)、type(A)、RDATA の順です。TTL は問い合わせのたびに、キャッシュ残り秒数に応じて減っていきます。
特定の権威サーバーへ直接聞いたり、解決の経路をたどったりもできます。
dig example.com A +tracedig example.com NS +shortns1.example.com.
ns2.example.com.MX や CAA、ネガティブ応答(存在しない名前)も同様に確認できます。
dig nonexistent.example.com A応答の status: NXDOMAIN と、Authority セクションに返る SOA を見れば、ネガティブキャッシュがどの TTL で効くかが読み取れます。
まとめ
- DNS は木構造の分散データベース。ルート -> TLD -> 権威サーバーの階層をたどり、「ゾーン」という単位で権威が管理される
- 解決は2種類のリゾルバで進む。アプリはスタブリゾルバから再帰リゾルバへ再帰問い合わせし、再帰リゾルバはルートから反復問い合わせで答えにたどり着く
- データの単位はRR。A/AAAA/CNAME/NS/SOA/MX/TXT/PTR/CAA/SRV など型ごとに役割が違う。apex に CNAME は置けない
- TTL でキャッシュし、鮮度と負荷のトレードオフを取る。「存在しない」もネガティブキャッシュ(RFC 2308、SOA の MINIMUM)される
- 通信はポート53、UDP/TCP 両対応(RFC 7766)。512バイト超は TC ビットで TCP 再送、または EDNS0(RFC 6891)で UDP のまま拡張
- DNSSEC(RFC 4033)は改ざん検知(真正性)、DoT(RFC 7858)/DoH(RFC 8484)は通信の暗号化(秘匿性)。目的が異なる
DNS は普段は意識しませんが、トラブル時には「キャッシュなのか、権威の設定なのか、委任なのか」を切り分ける力が効きます。dig で1枚ずつ層をはがして確認できるようになると、名前解決のトラブルは怖くなくなります。
参考リンク
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1035: Domain Names - Implementation and Specification
- RFC 2308: Negative Caching of DNS Queries (DNS NCACHE)
- RFC 6891: Extension Mechanisms for DNS (EDNS(0))
- RFC 7766: DNS Transport over TCP - Implementation Requirements
- RFC 4033: DNS Security Introduction and Requirements
- RFC 7858: DNS over TLS (DoT)
- RFC 8484: DNS Queries over HTTPS (DoH)
- RFC 8659: DNS Certification Authority Authorization (CAA)
- RFC 2782: A DNS RR for specifying the location of services (DNS SRV)
- RFC 3596: DNS Extensions to Support IP Version 6 (AAAA)
- IANA: Root Servers
- CDN キャッシュと s-maxage の実践ガイド(当ブログ)
- Node.js の TLS ホスト名検証バイパス(当ブログ)


