13 ポイント 投稿者 GN⁺ 2026-01-20 | 1件のコメント | WhatsAppで共有
  • 2026年1月8日、Cloudflareの1.1.1.1サービス更新がDNS応答内のレコード順序を変更し、世界中の一部ユーザーでDNS名前解決の失敗が発生
  • 問題の原因は、CNAMEレコードがA/AAAAレコードの後ろに移動したコード変更で、一部のDNSクライアント実装が順序に依存していたため
  • 特にglibcのgetaddrinfo関数CiscoスイッチのDNSCプロセスが影響を受け、後者では再起動ループまで発生
  • RFC 1034は「CNAMEが先に来ることがある(possibly preface)」としか定めておらず、レコード順序に関する明確な標準が存在しない
  • CloudflareはCNAMEを常に先頭に配置する方式へ復帰し、明確な標準定義のためのInternet-DraftをIETFに提出

1. 事案の概要

  • 2026年1月8日、1.1.1.1のメモリ使用量削減アップデートが展開され、DNS応答内のレコード順序変更が発生
    • 変更は2025年12月2日にコードベースへ導入、12月10日にテスト環境へ展開、2026年1月7日にグローバルリリース開始
    • 1月8日18:19 UTCにインシデントを宣言、18:27にロールバック開始、19:55に復旧完了
  • 大半の現代的なDNSクライアントは応答内のレコード順序を無視するが、一部実装はCNAMEが常に先に来ることを前提にしていた
  • この順序が変わると、一部クライアントが応答を空とみなして名前解決に失敗

2. CNAMEチェーンとキャッシュ動作

  • ドメイン問い合わせ時、たとえばwww.example.comは複数のCNAMEチェーンを経て最終IPへ解決される
    • 例: www.example.com → cdn.example.com → server.cdn-provider.com → 198.51.100.1
  • 各CNAMEリンクは**TTL(Time-To-Live)**を持ち、一部だけが期限切れになることがある
  • 1.1.1.1は期限切れになった部分だけを再問い合わせし、既存キャッシュと新しいレコードをマージして応答を構成

3. コード変更の詳細

  • 以前のコードではCNAMEチェーンを先に挿入し、その後にA/AAAAレコードを追加
    • answer_rrs.extend_from_slice(&self.records); // CNAMEs first
  • 変更後のコードではCNAMEを最後に追加
    • entry.answer.extend(self.records); // CNAMEs last
  • これにより応答内でCNAMEが下側へ移動し、一部クライアントがこれを処理できなくなった

4. 影響を受けた実装例

  • glibcのgetaddrinfo関数は応答を順次パースし、CNAMEが先に現れることで次の名前を追跡できる
    • CNAMEが後ろに来ると「期待している名前」が更新されず、結果が空になる
  • Cisco Catalystスイッチ3モデルDNSCプロセスも影響を受け、1.1.1.1を使用中の場合は致命的エラーによる再起動ループが発生
    • Ciscoは関連するサービス文書を公開

5. 影響を受けなかった実装

  • systemd-resolvedは応答をOrderedSet構造体としてパースするため、CNAMEの位置に関係なく全体集合を探索できる
    • そのためレコード順序の変更後も正常に動作

6. RFC 1034の曖昧さ

  • RFC 1034(1987年)は「応答は1つ以上のCNAMEでprefaceされることがある」と記述
    • しかしMUST/SHOULDのような規範的キーワードがなく、明示的な要求事項ではない
  • RFC 2119(1997年)で初めてこのようなキーワードが標準化され、当時の文書には明確な義務表現がなかった
  • Cloudflareは初期実装でCNAMEを先に配置していたが、テストでそれを保証してはいなかった

7. RRsetとメッセージセクションの区別

  • RFC 1034 §3.6は、**RRset(同一の名前・タイプ・クラスを持つレコード集合)**の順序は重要でないと明記
  • しかし異なるRRset間の順序については言及がない
  • §6.2.1の例も同じ名前のAレコード2件だけを扱っており、CNAMEとAの相対順序は扱っていない
  • したがってCNAMEとAレコード間の順序定義は空白状態

8. CNAMEチェーン内部の順序問題

  • CNAMEが複数段ある場合、チェーン自体の順序が入れ替わっても逐次パースが失敗する
    • 例: cdn.example.com CNAME server.cdn-provider.comが先に来ると、www.example.com CNAME cdn.example.comを見つけられない
  • RFC 1034にはCNAMEチェーン順序に関する要求事項もない

9. リゾルバの動作基準

  • RFC 1034 §5.2.2は「リゾルバはCNAMEに出会ったら新しい名前で問い合わせを再開しなければならない」と定める
  • しかしこれは**完全なリゾルバ(例: 1.1.1.1)**を対象とした説明であり、
    glibcのようなスタブリゾルバはこのロジックを実装していない
  • 結果として一部のスタブリゾルバはRFCが期待する動作に従っていない

10. DNSSECの明示的規定との比較

  • RFC 4035(DNSSEC)はRRSIGレコードの含有優先順位を「MUST」で明示
    • ただしこれは「含めるかどうか」の規定であり、「順序」そのものではない
  • DNSSECは明確な含有ルールを提供する一方、**署名されていないゾーン(Unsigned zones)**では依然としてRFC 1034の曖昧さが残る

11. Cloudflareの結論と対応

  • RFC上でCNAME順序は必須ではないが、一部クライアントがこれを前提としているため、
    CNAMEを常に先頭へ配置する方針に復帰
  • 今後同じ問題を防ぐためIETFへInternet-Draftを提出
  • Cloudflareはこの事案を通じて、40年前のプロトコルの曖昧さが今なお実務に影響していることを確認

12. 追加情報

  • Cloudflareは1.1.1.1を含むConnectivity Cloudを通じて、
    企業ネットワーク保護インターネット規模アプリケーションの高速化DDoS防御Zero Trust導入支援を提供
  • 無料アプリ1.1.1.1によりより高速で安全なインターネット接続が可能

1件のコメント

 
GN⁺ 2026-01-20
Hacker News のコメント
  • 私は RFC の文言はそこまで曖昧ではないと感じた
    「possibly preface」という表現は「CNAME レコードがあるなら、それを先頭に付ける」という意味に読めて、「好きな場所に付けてよい」という意味には解釈されない

    • 私もそう思う。「prefix できる」というのは「suffix してもよい」という意味ではない
      ただしこれは単なる文の解釈の問題ではなく、世界で最も重要な DNS サーバーの 1 つを運用するチームがCNAME 応答ロジックを変更したことが核心だ
      テストで明らかに壊れたはずなのに、誰も「この順序は重要か?」と尋ねなかったのが驚きだ
      Cloudflare は最近、問題を透明に公開しているが、今回の件は「面白い事実の共有」のように聞こえる
      大規模システムでこうした変更がテストを通過したというのは、かなり大きなミスに見える
    • 記事では、曖昧さは別の文に由来すると説明している — 「応答セクションの RR の順序差は重要ではない」という一節のためだ
      例が一般化できてしまうので、「すべての場合で順序は関係ない」と誤解される余地がある
      結局、ある人の「明確な理解」が別の人には「文書をちゃんと全部読んだのか?」に見えることもある
      こうした事例は規範的言語 (normative language) の重要性を示している
    • 君は曖昧ではないと感じるかもしれないが、実際には曖昧で、それを修正しようとする試みもあった
      関連する議論は IETF メーリングリスト で見られる
    • 私も君の意見に同意する。RFC の例 6.2.1 の解釈は誤っているようだ
      「順序差は重要ではない」というのは特定の例でのみ当てはまるのであって、一般規則を無視してよいという意味ではない
      RFC 1034 が RRset を定義したと言われることがあるが、実際にはその用語定義はない
      Cloudflare の解釈は例外条項を一般規則と取り違えたものに見える
      ただし CNAME チェーンの順序については明確な規定がないので、その点には多少の曖昧さが残っている
    • それは記事でも触れられている内容だ。RFC が規範的な語 (MUST, SHOULD) が標準化される前の文書である点を指摘している
  • これは Hyrum’s LawPostel’s Law が同時に作用した例のようだ
    「API の利用者が十分に多ければ、システムの観測可能なあらゆる挙動に誰かが依存するようになる」ということと、
    「送るものには厳格に、受け取るものには寛容に」という原則が衝突した結果だ

    • ただ、Postel の法則はいまや有害な原則と見なされる流れになっている
    • その通りだが、Hyrum’s Law の核心は世の中には無数のエッジケースが存在するという点だ
      今回は glibc の resolver が壊れたことがポイントだ — 決して珍しい状況ではない
      Cloudflare がきちんとテストしていなかったことこそ本当のニュースだ
    • 結局これは人間レベルの漏れた抽象化 (leaky abstraction) の問題だ
    • Hyrum’s Law を完璧に表した xkcd の漫画 がある
  • 今回のバグは、私に古い記憶を思い出させた
    2011 年、Cloudflare が RFC を無視してドメイン apex に CNAME を許可したときのことだ
    当時のブログ記事 を見ると、「RFC など無視して現実の問題を解決する」と言っていた
    しかし CNAME は名前レベル (alias) の概念なので、apex に置くと NS、MX、SOA のキャッシュが壊れる
    当時、多くのエンジニアが警告したが、「move fast and break things」だった
    それでも今回は CNAME チェーンと A レコードの順序を細かく扱っているのを見ると、進歩はしている

    • 君の言うことはよく分かる。昔の BIND で「cannot have CNAME and other data」というエラーを数え切れないほど見た
      CNAME と alias の概念は昔から混乱を生み、RFC1034 の非規範的な言語がその混乱をさらに大きくした
      こうした曖昧さが積み重なった結果だが、大規模サービス提供者がこの種のミスをしたのは依然として容認しがたい
    • だが、仕様を意図的に破ったことは本当に「バグ」なのか?
      むしろ仕様そのものが問題だったのだと思う
  • glibc の一般的な DNS lookup がレコード順序に依存していることに驚いた
    20 年以上も大きな問題がなかったのが不思議なくらいだ
    おそらく大半の DNS 運用者は、テストの中で順序が重要だと経験的に知っていたのだろう

    • おそらくこうした問題は以前からよくあったが、規模の小さいサービスでは見過ごされていただけだろう
      Cloudflare のように世界中の数百万台のデバイスに影響したケースは初めてで、それで注目されたのだ
      ただ、Cloudflare が今回 glibc のようなオープンソース resolver にパッチを送ったのかは気になる
    • サーバー側で順序を保つのが一般的で、そうでないサーバーは互換性問題のためすぐ修正されていた
      CNAME は本当に扱いにくい存在だ(DJB のメモ 参照)
    • インターネットは実際には少数の主要な権威サーバー実装に依存しており、みな同じ順序ルールに従っている
    • 順序制約をなくすには、DNS 名を高速に検索できるデータ構造が必要になる
      glibc のような単純な resolver にはキャッシュがないため、これを実装するには大幅なコード変更が必要だ
  • Cloudflare が「RFC は CNAME の順序を要求していない」と主張したのは言葉尻を捉えた議論のように聞こえる
    「MUST」がないからといって「どんな順序でもよい」とするのは無理がある
    間違いを認めて先に進む方が、世の中をより良くすると私は思う
    言葉の議論で責任を回避するのは、むしろ信頼を損なう

  • Cloudflare は RFC1034 を正しく理解していないようだ
    彼らの DNS インターフェースでは、CNAME があると A、AAAA だけを禁止し、他のレコードは許可している
    そのため CNAME と TXT が共存するとキャッシュ依存の結果が発生する
    internet.nl でもこの問題が見つかっていた
    一部の利用者は mxtoolbox ガイド に従って設定していたが、これは RFC1034 と衝突する

    • そのガイドはおそらく 2 つの異なる説明が混ざっているのだろう
      1 つは「DMARC サービスを CNAME で委任する方法」、もう 1 つは「自前でホストする方法」だ
      スクリーンショットが混乱を招いたようだ
  • Cloudflare が最終的に「CNAME は他のレコードより前に来るべきだ」という結論に達したのは妥当だ

    • 私もその結論を歓迎する。たとえ全員が間違っていたとしても、時には現実に合わせる必要がある
  • 会社で DNS を管理する中で、DNS のさまざまな限界を実感した
    特に SERVFAIL が発生すると、クライアントはどのサーバーに問題があるのか区別できない
    その結果、複数の DNS サーバーとキャッシュ層が不要な再試行の殺到を引き起こす
    また search path が誤ったドメインに NXDOMAIN クエリを繰り返してしまう

    • 私も似た問題を経験した。キャッシュサーバーばかり見ていて一日以上原因を特定できなかったが、結局は権威サーバー (auth server) 側の問題だった
    • BIND 9 にはこれを緩和するservfail-ttl オプションがある
      RFC2308 セクション 7.1 によれば、SERVFAIL 応答をキャッシュすることは許可されている
      古い標準だが、今でも有効なアプローチだ
  • Cloudflare はしばしば標準を破り、それを正当化する新しい RFC を書く
    RFC 8482 のような事例は業界の不名誉だと思う
    「今回も混乱を防ぐために新しい Internet-Draft を提出した」という話が皮肉に聞こえる

  • 1.1.1.1 のような大規模 DNS サーバーなら、glibc のような実際の resolver を含む統合テストがあるべきだ
    それなのに、なぜこんな問題が本番環境でしか発見されなかったのか疑問だ

    • おそらくキャッシュ失効の順序が絡んだあと、glibc で再問い合わせしたときにだけ起きるまれな組み合わせだったのだろう
      個別テストは通っていても、2 つの条件が重なるケースは漏れていた可能性が高い