ハクソク

世界を動かす技術を、日本語で。

最初に登場したのはCNAMEレコードか、それともAレコードか?

概要

2026年1月8日、1.1.1.1のメモリ使用量削減を目的としたアップデートがDNS解決障害を引き起こした事例
CNAMEレコードの順序変更が一部DNSクライアントの不具合の原因
40年以上前のDNSプロトコル仕様の曖昧さが根本要因
障害の詳細なタイムラインと影響範囲の解説
CNAMEチェーンやRFCの曖昧な記述についても考察

2026年1月8日発生 DNS解決障害の概要

  • 2026年1月8日、1.1.1.1の定期アップデートによりDNS解決障害が発生
  • 原因はDNS応答内のレコード順序変更によるもの
  • 多くのソフトウェアは順序を無視するが、一部実装ではCNAMEレコードが先頭であることを期待
  • この順序変更により、特定のDNSクライアントで名前解決が失敗
  • 攻撃や大規模障害ではなく、仕様解釈の違いによるもの

障害発生までのタイムライン

  • 2025-12-02: レコード順序変更のコードが1.1.1.1コードベースに導入
  • 2025-12-10: テスト環境でリリース
  • 2026-01-07 23:48: グローバルリリース開始
  • 2026-01-08 17:40: 90%のサーバーに展開完了
  • 2026-01-08 18:19: インシデント宣言
  • 2026-01-08 18:27: リリースリバート開始
  • 2026-01-08 19:55: 復旧完了

CNAMEチェーンとDNS動作の基礎

  • ドメイン問い合わせ時、**CNAME(Canonical Name)**レコードで別名解決が行われる
  • 例: www.example.com → cdn.example.com → server.cdn-provider.com → 198.51.100.1
  • 1.1.1.1はこのチェーンを辿り、各レコードをキャッシュ
  • 各レコードは独自のTTL(有効期限)を持つ
  • チェーンの一部が失効しても、有効部分のみ再解決し、全体を再構築

問題の発生した実装変更

  • 以前は「CNAMEチェーン→新しいレコード」の順で応答を構築
  • メモリ最適化のため「既存回答にCNAMEを追加(CNAMEが後ろ)」方式に変更
  • これにより、CNAMEレコードが末尾に現れる場合が発生

影響を受けたDNSクライアント

  • 一部クライアントはCNAMEが先頭であることを前提
  • glibcのgetaddrinfo関数などが該当
    • レコードを順に処理し、CNAME発見時に参照名を更新
    • CNAMEが後ろにある場合、期待通りに動作せず解決失敗
  • Ciscoスイッチの一部モデルでは、CNAME順序変更で再起動ループが発生

影響を受けない実装例

  • systemd-resolvedなどは、全レコードを順不同のセットとして扱う
    • CNAMEがどこにあっても正しくチェーンを辿れる

RFC(仕様書)における解釈の曖昧さ

  • RFC 1034(1987年発行)がDNSプロトコルの基礎を定義
  • CNAMEレコードが先頭に来る可能性がある」と記載
    • ただしMUST/SHOULDなどの強制表現は未使用
  • RRset(同名・同タイプのレコード集合)内の順序は重要でないと明記
  • ただし、異なるRRset間の順序は明確に規定されていない
  • 例示ではAレコード同士の順序のみ扱い、CNAMEやAの混在順序は未記述

CNAMEチェーン順序のさらなる問題

  • CNAMEチェーン自体の順序もRFCで明確な規定なし
  • チェーン順がバラバラだと、逐次処理型クライアントで不具合
  • 例: www.example.com→cdn.example.com→server.cdn-provider.com の順序が崩れると解決失敗

レゾルバ(DNSクライアント)が取るべき対応

  • RFC 1034は「CNAME発見時に新しい名前で再クエリ」を推奨
  • ただし、フルレゾルバ向けの記述が中心
  • スタブレゾルバ(glibcなど簡易クライアント)は仕様通り動かない場合も

DNSSEC仕様との比較

  • RFC 4035(DNSSEC)は「RRSIGは他RRsetより優先して含めるべき」と明確に規定
  • MUSTなどの強制表現を使用し、曖昧さを排除
  • DNSSECのような明示的な優先順位指定が従来DNSには存在しない

まとめ

  • DNS応答のレコード順序は、古いRFCの曖昧な記述と実装依存によりトラブルの温床
  • 今回の障害は仕様解釈の違いテスト不足が要因
  • 安定運用には実装間の互換性明確な仕様遵守が重要

Hackerたちの意見

ハイラムの法則のいい例だね。「APIのユーザーが十分にいる場合、契約で何を約束しても関係ない。システムのすべての観察可能な動作は誰かに依存される。」これに、ポステルの法則を守らないことが組み合わさってる。「送信するものには保守的で、受け入れるものには寛容であれ。」
ポステルの法則は、業界が進化するにつれて、ますます有害だと見なされているね。
それは確かだけど、Hyrumの法則の精神をちょっと外してるね(つまり、世の中には obscure なエッジケースがたくさんあるってこと)。この場合、壊れたリゾルバーはGNU Cライブラリのもので、全然 obscure な状況じゃないよ! ここでのニュースは、実はストーリーの中に埋もれてる。要するに、Cloudflareはこれをテストしなかったってことだね。世界中のデータセンターがこの変更で失敗することになるだろうし、彼ら自身のも含まれてるかもしれない。
Hyrumの法則についての必須のxkcd: https://xkcd.com/1172
RFCの表現がそんなに曖昧だとは思わないな。 > 「クエリへの回答は、回答に至る途中で遭遇したエイリアスを指定する1つ以上のCNAMEレコードで前置きされる可能性がある。」この「可能性がある」というのは、明らかに「CNAMEレコードがあれば、そのクエリの回答はそれらのCNAMEレコードで前置きされるべき」と理解すべきで、「クエリをCNAMEレコードで前置きすることもできるし、好きなところに置いてもいい」という意味ではないよね。
100%同意!私も同じことをコメントしたよ。「可能性がある」というのはCNAMEレコードの存在を指していて、順序のことじゃないのは明らかだね。
それには同意するよ。RFCの例6.2.1の解釈がちょっと意味不明だと思う。そこには「回答セクションのRRの順序の違いは重要ではない」と書いてあるけど、RFCから見ると、このコメントは特定の例にのみ関連していることは明らかだよね。二つのレスポンスを比較して、この場合は異なる順序が意味的な影響を持たないと言っているだけだし。まあ、ちょっと細かいことを言うけど、「RFC 1034のセクション3.6では、リソースレコードセット(RRset)を同じ名前、タイプ、クラスのレコードの集合として定義している」とも書いてあるけど、RFCを見てもそんな用語は定義されてないんだよね。「特定の名前に関連付けられたRRのセット」内では順序が問題にならないとは言ってるけど、「特定の名前、タイプ、クラスの組み合わせに関連付けられた」とは言ってないから、どうしてそれが曖昧さを生むのか理解できない。一般的なルールに対する例外を指定しているわけだから、例外が適用されないなら一般的なルールに従うべきだよね。まあ、CloudflareはDNSを僕よりよく知ってるだろうけど、この記事は特に説得力があるとは思わなかった。曖昧さは実際には誤解から来ていると思うし、RFCはCNAMEレコードの特定の順序を要求していると思う。(追記)確かに、RFCにはCNAMEがAの前に来るべきだと書いてあるけど、CNAMEチェーンの順序については明確なルールがあるとは思わない。RFCには「別の名前を指すRRのドメイン名は、常にプライマリ名を指し、エイリアスを指してはいけない」としか書いてないし... もちろん、ロバストネス原則に従って、ドメインソフトウェアはCNAMEチェーンやループに直面しても失敗すべきではないし、CNAMEチェーンは追従されるべきだとも書いてある。だから、実際にCNAMEチェーンを含むレスポンスに関しては、ある程度の曖昧さがあることには同意するかな。
記事では、曖昧さが別のフレーズから生じることがはっきり示されてるよ。「回答セクションのRRの順序の違いは重要ではない」というのは例に適用されているけど、例の問題は、例が説明的で一般化可能なものであるため、どこでも再配置を許可する可能性があるってこと。だから、再配置すべきかどうかは実用的な文脈の問題になってくる。つまり、一人の「明らかな理解」が他の人にとっては「全体の文書を読んだのか?」ってことになるわけだ。これもまた、規範的な言語の価値を強調することになるけど、それは後の話だね。
この記事にそれが明記されてるんじゃない? 記事では、RFCが規範的な言葉がハード要件として標準化される前のものであることも指摘してるよ。
これ、あんまり曖昧じゃないと思うよ。「これをやってもいいよ」と言って、「逆のことをやるかもしれない」と言ってる。もし「何かを前に付けることができる」と言ったら、代わりに後ろに付けることができるわけじゃない。でもさ、世界で最も重要な(エンドユーザー向けの)DNSサーバーのソフトウェアを作ってるプログラマーたちが、 1. CNAMEレスポンスの形成ロジックを変更して、 2. いくつかのテストが壊れて「修正が必要」になったと思う(「CNAMEがクエリされたとき、これが返ってくると思ってた」みたいな)。 3. 誰もこのテストの挙動の変化を見て「この順番って重要なのかな?」とか「もっと調査すべきだ」とか「他のDNSサーバーも順番を変えてるのかな?」とか「これは非常に段階的なリリースのためにフラグを立てるべきだ」と思わなかった。 4. テスト環境に入って、何、1ヶ月くらい… glibcからのgetaddrinfoを使ってこの環境をテストする人もいなかったし、壊れてることに気づいた人もいなかった。Cloudflareは物事を壊して透明性を持つことに慣れてきてるみたいだけど、これは本当に「知ってた?」っていう面白い話に見えるだけで、「また壊しちゃったよ、でもまだ使ってね」って感じじゃない。実際の原因分析はRFCを責めることしかないけど、正直、こんな大規模な運用でこれが見逃されるのはかなり大きな問題だと思う。サウスパークのオイルのジョークを言いたいけど、「ごめん」って感じじゃないみたい。
「おそらく前に付ける」って解釈される場合でも、CNAMEが複数ある場合にCNAME RRセットの順番に依存しているリゾルバがいくつかいるのは壊れてるよ。この順番の期待は関連するRFCでは約束されてないからね。
> RFCの文言がそんなに曖昧だとは思わないな。あなたは曖昧じゃないと思うかもしれないけど、実際は曖昧で、修正しようとした試みもあったよ。このトピックについての熱い議論はここで見つけられるよ: https://mailarchive.ietf.org/arch/msg/dnsop/2USkYvbnSIQ8s2vf...
> 私たちの解釈では、RFCはCNAMEが特定の順序で現れることを要求していないが、少なくとも一部の広く展開されているDNSクライアントはそれに依存していることは明らかだ。これらのクライアントを使用しているシステムの中には、あまり更新されないか、全く更新されないものもあるため、CNAMEレコードは他のレコードの前に順序通りに現れるべきだと考えている。それが唯一の合理的な結論だね。
それに気づいてくれて嬉しいよ。みんなが間違ってるとしても(間違ってるとは言ってないけど)、時には流れに乗ることも大事だよね。
ランダムな順序でレコードを送信し始めて、そんな脆弱な特性に依存している壊れた実装を排除してほしいな。
回答が構築されるために解決が行われた順番で並んでいるという特性は、そんなに脆いの?最終的な回答RRセット内のランダム化は大丈夫だし(多くの場合、むしろ好ましいかも)。
glibcの普通のDNSルックアップ機能が、レコードが正しい順序でないと動かないのは驚きだよ。20年以上もそれがもっと問題を引き起こさなかったのが信じられない。多くの人がDNSレコードを公開する際、実際には順序が重要だってなんとなく知ってたんじゃないかな、初期のテストで気づいたりして。
これはサーバー側の順序の問題だと思う。あまり多くのDNSサーバーがなかった時代で、順序を保たないサーバーは相互運用性のためにすぐに挙動を変えたんだよね。CNAMEは本当に厄介だよ(DJBが指摘してる通りだね)。
インターネットは、非常に少数の権威あるサーバー実装に依存していて、その中でこの順序のクセがあるからだと思う。
今、うちの会社でDNSの管理を任されることになって、以前は気づかなかったDNSのいくつかの問題を見つけたよ。一番の問題は、上流のDNSサーバーがSERVFAILを返すと、クエリしているサーバーが故障しているのか、実際の権威サーバーが壊れているのかの区別がつかないことだね(EDEについては知ってるけど、あまり解決にはならない)。壊れたドメインをクエリするクライアントは、設定されているDNSサーバーをそれぞれ再試行するし、うちのキャッシュレイヤー(Unbound)もそれぞれの上流を再試行することになる... 結果的に、無駄な上流クエリが増えて、まるで増幅攻撃みたいになっちゃう。あと、検索パスがNXDOMAINでバカなクエリをする問題もあるよ。例えば、badname.company.comやbadname.company.othername.comみたいなやつ。
あなたのSERVFAILの観察についてだけど、1年くらい前に特定のゾーンでこの問題に直面したことがあるよ。キャッシングサーバーでトラブルシューティングしてただけだったんだけど、認証サーバーを見に行くのに1、2日かかったら、実際の問題はそこから来てたんだ。
この規模の1.1.1.1みたいなDNSサーバーは、glibcのような実際のリゾルバーを使った統合テストを行っていると思うんだけど、どうしてこの問題が本番環境でしか発見されなかったのかな?
このケースは、CNAMEチェーンがまずキャッシュから間違った順番で期限切れになって、その後glibc経由でクエリされた場合にのみ発生するよ。彼らのテストはglibcの解決が機能することと、期限切れのレコードを再クエリすることが機能することをテストするかもしれないけど、その2つの組み合わせはテストしてないんだ。
DNSはワイヤープロトコル、ペイロード仕様、アプリケーションプロトコルだよ。それに関して、個人的にはその持続的な成功は、コーナーケースに入ると驚くほど仕様が不十分だからじゃないかと思う。しかも、量が多いし、大体はうまく動いてる。これが人間の効果の判断にヒステリシスループを作り出すんだよね。盲目的な鶏でも、コーンの中に立ってればコーンをもらえるし。シスコがciscoを買収したけど、(10年前、ファイアホースにアクセスできた頃)ある日のbelkinはNXDOMAINトラフィックを見たらトップ10のTLDに入ってた。クライアントはTCPを試そうとしない(仕様的にはそうすべきじゃないけど…)、でもDoTはある(実際にはすべきだけど)。私のISPの逆引きDNSの実装はひどくて、qname最小化が壊れちゃう…でも「逆引きDNSにqname最小化を使うべきじゃない」とか「Spamhausはqname最小化に影を落として法律を破ってる」って言われてる。「4096は誰にとっても十分なはずだ」(いや、フラグメントは悪い。上のTCPを見て)。TCP接続には常に1つのリクエストしかない…ねえ、TCP接続のペイロードの前にあるこの2バイトは何なの?自分のプロプライエタリヘッダーが、任意の数の中間プロキシやフォワーダーを通してアプリケーションプロトコルを転送しても保存されると思いたい人たち(だって、セグメントエッジで本物のDNSを運営してクライアント情報をアプリケーションレベルでログするよりずっと簡単だから)。ちょっと脱線するけど、「でも、もっとあるんだ。こういうことをする人たちは、通常は自分たちにとってどう機能するかを説明する(どう機能しないかは言わない)から、注意を払わない見物人は『うまくいってる』と結論づける」って感じ。http://consulting.m3047.net/dubai-letters/dnstap-vs-pcap.htm...
この投稿を乗っ取って、CloudFlareがRFC1034を全然理解してないことを指摘したい。彼らのDNS権威インターフェースは、CNAMEが定義されている場合にのみAとAAAAをブロックするんだ。例えば、これを見てみて:$ echo "A AAAA CAA CNAME DS HTTPS LOC MX NS TXT" | sed -r 's/ /\n/g' | sed -r 's/^/rfc1034.wlbd.nl /g' | xargs dig +norec +noall +question +answer +authority @coco.ns.cloudflare.com ;rfc1034.wlbd.nl. IN A rfc1034.wlbd.nl. 300 IN CNAME www.example.org. ;rfc1034.wlbd.nl. IN AAAA rfc1034.wlbd.nl. 300 IN CNAME www.example.org. ;rfc1034.wlbd.nl. IN CAA rfc1034.wlbd.nl. 300 IN CAA 0 issue "really" ;rfc1034.wlbd.nl. IN CNAME rfc1034.wlbd.nl. 300 IN CNAME www.example.org. ;rfc1034.wlbd.nl. IN DS rfc1034.wlbd.nl. 300 IN DS 0 13 2 21A21D53B97D44AD49676B9476F312BA3CEDB11DDC3EC8D9C7AC6BAC A84271AE ;rfc1034.wlbd.nl. IN HTTPS rfc1034.wlbd.nl. 300 IN HTTPS 1 . alpn="h3" ;rfc1034.wlbd.nl. IN LOC rfc1034.wlbd.nl. 300 IN LOC 0 0 0.000 N 0 0 0.000 E 0.00m 0.00m 0.00m 0.00m ;rfc1034.wlbd.nl. IN MX rfc1034.wlbd.nl. 300 IN MX 0 . ;rfc1034.wlbd.nl. IN NS rfc1034.wlbd.nl. 300 IN NS rfc1034.wlbd.nl. ;rfc1034.wlbd.nl. IN TXT rfc1034.wlbd.nl. 300 IN TXT "私のクールなラベルがTXTとCNAMEを提供してるのをチェックして、RFC1034に違反してるよ" 結果として、DNSリゾルバ(CloudFlare Public DNSを含む)は、例えばTXTレコードを問い合わせると、CNAMEがキャッシュされているかどうかに依存した結果が出る。internet.nl(https://github.com/internetstandards/)では、ある人たちがTXT DMARCレコードを持っていると主張しつつ、このレコードをCNAMEしていることが分かった(これがキャッシュ依存の結果を生む)。internet.nlはRFC 9156 QName最小化を使っているので、最初にAを解決してCNAMEをキャッシュし、TXTを見ることができなくなる。人々は、https://mxtoolbox.com/dmarc/dmarc-setup-cname の指示に似た設定をしている(これはRFC1034に矛盾していると思う)。
> 人々は、https://mxtoolbox.com/dmarc/dmarc-setup-cname の指示に似た設定をしている(これはRFC1034に矛盾していると思う)。 彼らが誰かに同じラベルでCNAMEとTXTの両方を作るようにアドバイスしているとは思わないけど、ステップ5の変なスクリーンショットを見ると、そう見えるよね(テキストと合ってないし)。これは、完全に第三者のDMARCサービスにCNAMEを指す方法と、自分でDMARCレコードをホストする方法の2つの異なるガイドが混ざってしまった誤解だと思う(RUAがどこに行くかは関係なく)。
> 私たちの解釈では、RFCはCNAMEが特定の順序で現れることを要求していない。 それは私にはダブルスタンダードのように思える。なぜなら、彼らは以前に「MUSTやSHOULDを使っていないから曖昧だ」と言っているからだ。これらはDNS RFCの10年後に導入されたものだ。RFCにはこう書いてある:>「クエリへの回答は、回答に至る過程で遭遇したエイリアスを指定する1つまたは複数のCNAME RRによって前置きされる可能性がある。」 それを「MUST」が10年後に定義されたことを考慮して「CNAMEを回答に追加してもいいかな?」と解釈するのはどういうことなんだろう。「RFCが許可していると思う」という考えを持ち続けるのは問題だよ。自分の間違いを認めて前に進むことができれば、世界はもっと良くなる。私は家でも仕事でもこれを心がけている。間違っていることから逃げようとするのは、世界を悪くするだけだから。