0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RFC 1034/1035からRFC 9499まで、DNSが40年前の設計で動き続ける理由

0
Last updated at Posted at 2026-08-21

www.example.com のようなサブドメインにCNAMEを置くのは普通のことです。実際に引くとこう返ります。

$ dig +noall +answer www.fastly.com CNAME
www.fastly.com.		3600	IN	CNAME	prod.www-fastly-com.map.fastly.net.

これは実際に実行した結果です。このシリーズの他の記事では、例示にRFC 2606が文書用に予約したドメイン名を使っていますが、ここは作例ではなく実測値なので実在のドメインを載せています。

同じことを example.com のようなapexでやろうとすると成立しません。よく「DNSの仕様上できない」と説明されますが、その仕様が具体的にどの記述を指すのかは、2本のRFCの3箇所に分かれています。まずその3箇所を確認します。

apex CNAMEを成立させない規定

CNAMEがある名前に他のデータを置けない規則

RFC 1034 の 3.6.2 節に、次の記述があります。

If a CNAME RR is present at a node, no other data should be present; this ensures that the data for a canonical name and its aliases cannot be different. This rule also insures that a cached CNAME can be used without checking with an authoritative server for other RR types.

あるノードにCNAME RRが存在する場合、他のデータを置くべきではない。これにより、canonical nameとその別名でデータが異なる事態を防げる。またこの規則により、キャッシュされたCNAMEを、他のRR型について権威サーバーへ確認し直すことなく使える。

理由まで書かれている点が重要です。CNAMEは「この名前の実体は別名の先にある」と宣言するレコードなので、同じ名前にAやMXが同居すると、どちらが実体なのか決まりません。加えて、リゾルバーがCNAMEをキャッシュしたあとで「この名前には他の型も存在しうる」と疑う必要が出てきます。排他にしておけば、CNAMEを1つ引いた時点で他の型を探さずに済みます。

すべてのゾーンでSOAとNSが必須という規定

RFC 2181 の 6.1 節に、次の記述があります。

The authoritative servers for a zone are enumerated in the NS records for the origin of the zone, which, along with a Start of Authority (SOA) record are the mandatory records in every zone.

あるゾーンの権威サーバーは、そのゾーンのoriginに置かれたNSレコードによって列挙される。NSレコードはSOA (Start of Authority) レコードとともに、すべてのゾーンにおいて必須のレコードである。

ここでいうoriginがapexです。同じくRFC 2181 の 6 節が定義しています。

The domain name that appears at the top of a zone (just below the cut that separates the zone from its parent) is called the zone's "origin".

ゾーンの最上位に現れるドメイン名 (そのゾーンを親から切り離すcutのすぐ下) を、そのゾーンのoriginと呼ぶ。

名前が取りうる4つの状態

RFC 2181 の 10.1 節は、1つ目の規則をDNS上のすべての名前について次の形に整理しています。

That is, for any label in the DNS (any domain name) exactly one of the
following is true:

  + one CNAME record exists, optionally accompanied by SIG, NXT, and
    KEY RRs,
  + one or more records exist, none being CNAME records,
  + the name exists, but has no associated RRs of any type,
  + the name does not exist at all.

訳すと次のようになります。DNS上のどのラベル (どのドメイン名) についても、次のいずれか1つだけが成り立つ、という規定です。

  • CNAMEレコードが1つ存在する (DNSSEC利用時はSIG・NXT・KEYを伴ってよい)
  • 1つ以上のレコードが存在し、そのいずれもCNAMEではない
  • 名前は存在するが、いかなる型のRRも持たない
  • 名前がまったく存在しない

ゾーンファイルでの確認

この3つを example.com ゾーンに当てはめます。まず、apexにCNAMEを置かない普通のゾーンです。

$ORIGIN example.com.
$TTL 3600
@     IN  SOA   ns1.example.com. admin.example.com. (
                2026081601 7200 3600 1209600 3600 )
@     IN  NS    ns1.example.com.
@     IN  NS    ns2.example.com.
@     IN  A     203.0.113.10
www   IN  CNAME customer.example.fastly.net.

apex (@ = example.com.) は「1つ以上のレコードが存在し、そのいずれもCNAMEではない」に当てはまります。SOA・NS・Aの3種類があり、CNAMEはありません。www は「CNAMEレコードが1つ存在する」に当てはまります。どちらも4つの状態のいずれか1つに該当します。

ここで、apexのAレコードをCNAMEへ置き換えます。

$ORIGIN example.com.
$TTL 3600
@     IN  SOA   ns1.example.com. admin.example.com. (
                2026081601 7200 3600 1209600 3600 )
@     IN  NS    ns1.example.com.
@     IN  NS    ns2.example.com.
@     IN  CNAME customer.example.fastly.net.

この example.com. を4つの状態に当てはめると、どれにも入りません。

状態 判定
CNAMEレコードが1つ存在する 当てはまらない。SOAとNSが同居している
1つ以上のレコードがあり、いずれもCNAMEではない 当てはまらない。CNAMEがある
名前は存在するが、いかなる型のRRも持たない 当てはまらない。4つのRRがある
名前がまったく存在しない 当てはまらない。存在する

SOAとNSを消せば1つ目に当てはまります。しかしその2つは、RFC 2181の6.1節が「すべてのゾーンで必須」と書いているレコードです。消した時点で example.com はゾーンでなくなり、権威サーバーはそのゾーンを読み込めません。

つまりapex CNAMEが成立しないのは、CNAMEの排他規則とapexのSOA/NS必須規定が同時に適用されるからです。片方だけなら問題になりません。www.example.com でCNAMEが使えるのは、www がゾーンのoriginではないため、SOAとNSを持たないからです。

CloudflareやFastlyが独自に設けた制限ではない、という説明はここまでで足ります。ただ、そうすると次の疑問が出ます。なぜ1987年のRFCと1997年のRFCに分かれているのか。そして1997年のRFCは、この制約を新しく作ったのか。

HOSTS.TXTを1つのファイルで配っていた時代

DNSが生まれる前、インターネット上のホスト名とアドレスの対応は HOSTS.TXT という1つのファイルで管理されていました。

HOST-A      192.0.2.10
HOST-B      192.0.2.20
HOST-C      192.0.2.30

現代の /etc/hosts と同じ形式です。違うのは、これがインターネット全体で1つしかなかったことです。

RFC 1034 の 2.1 節は、DNS開発の動機を「インターネットの成長」とし、その内訳を3つ挙げています。1つ目が配布コストです。

Host name to address mappings were maintained by the Network Information Center (NIC) in a single file (HOSTS.TXT) which was FTPed by all hosts [RFC-952, RFC-953]. The total network bandwidth consumed in distributing a new version by this scheme is proportional to the square of the number of hosts in the network, and even when multiple levels of FTP are used, the outgoing FTP load on the NIC host is considerable. Explosive growth in the number of hosts didn't bode well for the future.

ホスト名からアドレスへの対応付けは、Network Information Center (NIC) が単一のファイル (HOSTS.TXT) として維持し、すべてのホストがFTPで取得していた。この方式で新しい版を配布するために消費されるネットワーク帯域の総量は、ネットワーク内のホスト数の2乗に比例する。多段のFTPを使った場合でも、NICホストの送出負荷は相当なものになる。ホスト数の爆発的な増加は、先行きが思わしくなかった。

ホスト数の2乗という記述が、この方式の限界を示しています。2つ目は管理権限です。

Local organizations were administering their own names and addresses, but had to wait for the NIC to change HOSTS.TXT to make changes visible to the Internet at large.

各組織は自分たちの名前とアドレスを管理していたが、変更をインターネット全体へ見えるようにするには、NICがHOSTS.TXTを書き換えるのを待たなければならなかった。

3つ目は用途の広がりで、アプリケーションが高度になり汎用の名前サービスが必要になった、と書かれています。

そして同 2.2 節が挙げる設計目標に、次の1文があります。

The costs of implementing such a facility dictate that it be generally useful, and not restricted to a single application.

こうした仕組みの実装コストを考えれば、単一のアプリケーションに限定せず、汎用に使えるものにする必要がある。

DNSは名前解決を速くするために作られたのではありません。管理を分散し、かつ単一用途に縛らないことが目標に置かれています。apexとCNAMEの制約も、この汎用データベースというデータモデルの帰結です。

1983年のRFC 882/883による名前空間の階層化

RFC 1034の2.1節は、この問題に対して複数の提案が出たこと、そして共通していた考え方を記述しています。

The proposals varied, but a common thread was the idea of a hierarchical name space, with the hierarchy roughly corresponding to organizational structure, and names using "." as the character to mark the boundary between hierarchy levels.

提案はさまざまだったが、共通していたのは階層的な名前空間という考え方だった。階層はおおよそ組織構造に対応し、名前は階層の境界を示す文字として "." を使う。

この方向で分散データベースと汎用のリソースを設計したのが、1983年にPaul Mockapetrisが公開したRFC 882RFC 883です。RFC 882が考え方を、RFC 883が実装方法を記述しています。

                .
                |
        ┌───────┼────────┐
       com      net      jp
        |
     example
        |
       www

木にすると、管理を枝ごとに切り離せます。ルートが知っているのは comjp の管理者だけです。.com の管理者は example.comother.com の管理者を把握します。さらに example.com の管理者が www.example.comapi.example.com を自由に管理できます。

階層化そのものが分散管理の手段になっています。1つのファイルを配る方式をやめ、問い合わせを木の上から下へ委譲する構造に置き換えています。名前解決の仕組みに見えるものが、同時に組織間の権限分割の仕組みでもあります。

1987年のRFC 1034/1035とSTD 13

RFC 882/883からRFC 1034/1035までの経緯を、RFC 1034自身が1文で書いています。

Based on experience with several implementations, the system evolved into the scheme described in this memo.

いくつかの実装での経験を踏まえて、このシステムは本メモに記述された方式へ発展した。

その方式を記述したのが、1987年11月公開の次の2本です。

  • RFC 1034「Domain names - concepts and facilities」
  • RFC 1035「Domain names - implementation and specification」

この2本は現在もDNSの基本仕様を構成しており、まとめてInternet StandardのSTD 13になっています。RFC 1034がドメイン名空間・ゾーン・ネームサーバー・リゾルバー・キャッシュ・委任といった概念を扱い、RFC 1035がDNSメッセージの形式とA・CNAME・MX・NS・SOA・PTRといった具体的な形式を規定しています。

冒頭に引用したCNAMEの排他規則も、このRFC 1034に入っています。apex CNAMEの制約は、1987年の時点ですでに成立していたことになります。

なお、TCPを使ったDNS通信もこの時点で「4.2.2 TCP usage」として規定されています。DNS over TLSやDNS over HTTPSと並べて「後から足されたトランスポート」として紹介されることがありますが、TCPだけは最初からあります。

現代のCloudflare、Route 53、Google Cloud DNS、BINDUnboundも、先祖をたどればこの2本に行き着きます。

名前と種類の組で引くデータベース

DNSでは、ある名前に対して「情報の種類」を指定して問い合わせます。example.com についてAを問い合わせればIPv4アドレスを探し、MXならメールサーバー、NSならそのドメインを担当するネームサーバーを探します。

example.com + A
    → IPv4アドレス

example.com + MX
    → メールサーバー

example.com + NS
    → ネームサーバー

この「情報の種類」を指定するのがRR TYPEで、A・MX・NS・SOAなどがそれにあたります。サーバーが実際に返す個々のレコード、つまり所有者名・種類・クラス・TTL・値をまとめた1件分のデータがResource Record (RR) です。日常的には両者をまとめてRRと呼びますが、RFC 1035やRFC 9499の用語では区別されています。

問い合わせのキーが「名前」ではなく「名前と種類の組」である点が、apexの話につながります。同じ名前に別種類のデータを持たせられる設計だからこそ、「この名前には他の種類を置いてはいけない」というCNAMEの例外規定が必要になりました。

RFC 2181が扱った8つの問題

1997年7月、RFC 2181「Clarifications to the DNS Specification」が公開されました。abstractは、扱う問題を8つ列挙しています。

  • マルチホームサーバーが返信に使う送信元アドレス
  • 同じ名前・クラス・種類を持つレコード群のTTL
  • zone cutの正しい扱い
  • SOAレコードとその使い方に関する3つの小さな問題
  • TTLの厳密な定義
  • TC (truncated) ヘッダービットの使い方
  • authoritativeまたはcanonicalな名前とは何か
  • 何が正当なDNSラベルなのか

そして同じabstractが、この8つを2種類に分けています。

The first six of these are areas where the correct behaviour has been somewhat unclear, we seek to rectify that. The other two are already adequately specified, however the specifications seem to be sometimes ignored. We seek to reinforce the existing specifications.

前半の6つは、正しい挙動がやや不明確だった領域であり、これを正すことを目指す。残る2つはすでに十分に規定されているが、その規定がときどき無視されているように見える。既存の規定を補強することを目指す。

apexとCNAMEに関わるのは後半2つです。RFC 2181自身が「すでに十分に規定されている」と書いている以上、apex CNAMEの禁止をRFC 2181が新しく決めたわけではありません。1987年のRFC 1034にあった規則を、無視されないように書き直したものです。

「apexにCNAMEを置けないのはRFC 2181で禁止されたから」という説明は、この点で順序が逆になっています。

RFC 2181による明確化の中身

「曖昧な部分を明確化した」と要約されがちですが、中身は具体的で、しかも実務に直結しています。代表的なものを挙げます。

RRSet内のTTLは揃っていなければならない

同じ名前・同じクラス・同じ種類のレコード群をRRSetと呼びます。次の2行はAレコードのRRSetです。

example.com A 192.0.2.1
example.com A 192.0.2.2

RFC 2181 の 5.2 節は、この2行に別々のTTLを付けた場合に何が起きるかを書いています。

This can, however, cause partial replies (not marked "truncated") from a caching server, where the TTLs for some but not all the RRs in the RRSet have expired.

ただしこれは、RRSet内の一部のRRだけがTTL切れになったキャッシュサーバーから、部分的な応答 (truncatedの印は付かない) が返る原因になりうる。

負荷分散のために2件並べたつもりが、片方だけ返る状態が起こりえます。そこで同節は、TTLが一致しないRRSetを廃止し、RRSet内のすべてのTTLは同じでなければならないと決めました。

データの信頼度の順位

DNSの応答には、answer・authority・additionalという3つの区画があります。同じ名前について、権威サーバーからの回答と、他の応答に付随してきたadditional情報とで内容が一致しない場合もあります。どちらを信じるのか。

RFC 2181 の 5.4.1 節は、この順位を明文化しました。上からプライマリゾーンファイル、ゾーン転送で得たデータ、権威応答のanswer区画、権威応答のauthority区画と続き、非権威応答のadditional区画が最下位です。そのうえで、最下位のデータの扱いを次のように定めています。

Unauthenticated RRs received and cached from the least trustworthy of those groupings, that is data from the additional data section, and data from the authority section of a non-authoritative answer, should not be cached in such a way that they would ever be returned as answers to a received query.

信頼度が最も低い区分、すなわちadditionalデータ区画と非権威応答のauthority区画から受け取ってキャッシュした未認証のRRは、受け取った問い合わせへの回答として返されうる形でキャッシュすべきではない。

この規定がなければ、信頼度の低いデータを応答に混ぜるだけで、そのデータの格を上げられてしまいます。

TTLは符号なしで、上限は2147483647

RFC 2181 の 8 節は、TTLフィールドの解釈が定まっていなかったと述べたうえで、範囲を確定させています。

It is hereby specified that a TTL value is an unsigned number, with a minimum value of 0, and a maximum value of 2147483647. That is, a maximum of 2^31 - 1. (中略) Implementations should treat TTL values received with the most significant bit set as if the entire value received was zero.

ここに、TTL値は符号なしの数値であり、最小値0、最大値2147483647、すなわち2^31 - 1を上限とすることを規定する。(中略) 実装は、最上位ビットが立った状態で受け取ったTTL値を、受け取った値全体が0であるかのように扱うべきである。

同じ節には、実装が受け取ったTTLに独自の上限を設けてよいことも書かれています。TTLは最大の生存時間を示す値で、その期間の保持を義務づけるものではありません。

ラベルに使えるのは任意のバイト列

RFC 2181 の 11 節は、DNSがラベルに課す制限が長さだけであることを明示しています。

Those restrictions aside, any binary string whatever can be used as the label of any resource record. (中略) Implementations of the DNS protocols must not place any restrictions on the labels that can be used.

それらの制限 (長さ) を別にすれば、いかなるバイト列もリソースレコードのラベルとして使える。(中略) DNSプロトコルの実装は、使用できるラベルにいかなる制限も課してはならない。

「ドメイン名に使えるのは英数字とハイフンだけ」という制限は、RFC 1123が定めるホスト名の規則であって、DNSの規則ではありません。同じ11節が、その切り分けを次のように書いています。

Note however, that the various applications that make use of DNS data can have restrictions imposed on what particular values are acceptable in their environment.

ただし、DNSのデータを利用するさまざまなアプリケーションは、その環境で受け入れ可能な値に制限を課しうる点に注意すること。

この分離があったからこそ、後に国際化ドメイン名やDNSSEC、SVCBのような新しい使い方をDNSの上へ載せられました。RFC 1034が設計目標に挙げた「単一のアプリケーションに限定しない」が、具体的な形で現れている箇所です。

数十本に増えたDNSのRFC

DNSはRFC 1034/1035で完成して止まったわけではありません。その後、次のような機能が追加されています。

DNSSEC
IPv6
EDNS
国際化ドメイン名
Negative Caching
DNS over TLS
DNS over HTTPS
SVCB
HTTPS RR

DNS用語を整理したRFC 8499は、DNSが「文字通り数十本のRFC」で定義されていると説明しています。「DNSの仕様書」という1冊の完成品は存在しません。実態は次のような積み重ねです。

RFC 1034
RFC 1035
   +
RFC 2181
   +
RFC 2308
   +
RFC 4033〜
   +
……

ソフトウェアでいえば、40年間パッチを当て続けている巨大プロジェクトに近いところがあります。ただし、古いコードを捨てての全面リライトはできません。

後方互換を壊せない理由

仮に新しいDNSを作り、apexでもCNAMEを自由に使えるようにしたとします。しかし、古い権威DNS、古いリゾルバー、企業内DNS、家庭用ルーター、ISP、OS、ライブラリ、CDN、ロードバランサーが一斉に更新されることはありません。一部だけ新仕様へ移行すると、次の状態になります。

このDNSでは動く
このISPでは動かない
このルーターを経由すると壊れる

しかもDNSは、どこで壊れているかの切り分けが難しい層です。「一部の利用者からだけ見えない」という形で表面化するため、原因がDNSにあると気づくまでに時間がかかります。互換性を壊した代償は、壊した側ではなく、事情を知らない運用者が払うことになります。

したがってインターネット標準では、過去との互換性を壊さずに新機能を追加することが重視されます。DNSが古い仕様を残しているのは、保守的だからではありません。40年前のクライアントと現代のクラウドを同じインターネットにつなぎ続ける必要があるからです。

SVCB/HTTPSレコード (RFC 9460) の設計にも、この制約が表れています。apexで別名を指定したいという要求に対して、CNAMEの排他規則を緩めるのではなく、新しいRR TYPEを足すという解き方をしました。RR TYPEを増やすのは、RFC 1035が最初から用意していた拡張点です。

用語の不一致とRFC 7719/8499/9499

DNSのRFCが増えると、別の問題が起きました。RFC 9499 の 1 節が、その状況を書いています。

It is important to note that, during the development of this document, it became clear that some DNS-related terms are interpreted quite differently by different DNS experts. Further, some terms that are defined in early DNS RFCs now have definitions that are generally agreed to, but that are different from the original definitions.

本文書の作成過程で、DNS関連の用語のいくつかが、DNSの専門家によって大きく異なる解釈をされていることが明らかになった点は重要である。さらに、初期のDNS RFCで定義された用語のいくつかは、現在では一般に合意された定義を持つものの、それが元の定義とは異なっている。

同じ節には、次の記述もあります。

Note that there is no single consistent definition of "the DNS".

「the DNS」について、単一の一貫した定義は存在しない点に注意すること。

対象になった語には、resolver、recursive resolver、authoritative server、forwarder、stub resolverなどがあります。この整理のため、2015年にRFC 7719「DNS Terminology」が公開されました。2019年のRFC 8499を経て、2024年3月公開のRFC 9499が現在の版です。いずれも新しいプロトコルを定義する文書ではありません。

積み重なる層としての現在のDNS

RFC 9499は新しい文書ですが、「RFC 1034/1035はもう読まなくてよい」という意味ではありません。RFC 9499の1節が、プロトコルとメッセージ形式はRFC 1034とRFC 1035で定義されている、と明記したうえで用語を並べています。

つまり現在のDNSは「2024年版DNS」へ丸ごと置き換わったのではなく、次の積み重ねとして動いています。

1987年の基本設計
   +
1990年代以降の明確化
   +
2000年代以降の拡張
   +
2024年の用語整理

ここがWebフレームワークのバージョンアップとは違う点です。React 18からReact 19へ移行するように「DNS 1987」が「DNS 2024」へ交換されたわけではありません。古い規定が残ったまま、その上に新しい規定が積み重なっています。

まとめ

apexに普通のCNAMEを置けない理由は、次の2つの規定が同時に適用されることにあります。

  • CNAMEがある名前には他のデータを置けない (RFC 1034 §3.6.2、RFC 2181 §10.1で再整理)
  • SOAとNSはすべてのゾーンで必須で、ゾーンのorigin、つまりapexに置かれる (RFC 2181 §6.1)

どちらか片方だけなら問題は起きません。www.example.com でCNAMEが使えるのは、そこがゾーンのoriginではないからです。

そしてこの制約は、RFC 2181が新しく作ったものではありません。RFC 2181のabstract自身が、CNAMEとラベルに関する2項目を「すでに十分に規定されている」ものとして、既存規定の補強に分類しています。

HOSTS.TXT
中央の巨大な名前一覧
        ↓

RFC 882 / 883
1983年
名前空間を木にして管理を分散する

        ↓

RFC 1034 / 1035
1987年
現在まで続くDNSの基本設計 (STD 13)
CNAMEの排他規則もここ

        ↓

RFC 2181
1997年
不明確だった6項目を正し、
無視されがちな2項目を補強する

        ↓

RFC 9499
2024年
数十年で増えたDNS用語を整理する

RFC 1034が設計目標に挙げたのは、管理を分散すること、そして単一のアプリケーションに限定しないことでした。この2点があったため、DNSSEC・EDNS・国際化ドメイン名・SVCBといった後年の要求を、基本設計を変えずに載せられています。

一方で、その基本設計に含まれる決めごとは動かせません。apexにCNAMEを置けないという制約は、DNSが古いから生まれたのではなく、1987年に決めた不変条件を守り続けているから残っています。

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?