- 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を使用中の場合は致命的エラーによる再起動ループが発生
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件のコメント
Hacker News のコメント
私は RFC の文言はそこまで曖昧ではないと感じた
「possibly preface」という表現は「CNAME レコードがあるなら、それを先頭に付ける」という意味に読めて、「好きな場所に付けてよい」という意味には解釈されない
ただしこれは単なる文の解釈の問題ではなく、世界で最も重要な DNS サーバーの 1 つを運用するチームがCNAME 応答ロジックを変更したことが核心だ
テストで明らかに壊れたはずなのに、誰も「この順序は重要か?」と尋ねなかったのが驚きだ
Cloudflare は最近、問題を透明に公開しているが、今回の件は「面白い事実の共有」のように聞こえる
大規模システムでこうした変更がテストを通過したというのは、かなり大きなミスに見える
例が一般化できてしまうので、「すべての場合で順序は関係ない」と誤解される余地がある
結局、ある人の「明確な理解」が別の人には「文書をちゃんと全部読んだのか?」に見えることもある
こうした事例は規範的言語 (normative language) の重要性を示している
関連する議論は IETF メーリングリスト で見られる
「順序差は重要ではない」というのは特定の例でのみ当てはまるのであって、一般規則を無視してよいという意味ではない
RFC 1034 が RRset を定義したと言われることがあるが、実際にはその用語定義はない
Cloudflare の解釈は例外条項を一般規則と取り違えたものに見える
ただし CNAME チェーンの順序については明確な規定がないので、その点には多少の曖昧さが残っている
これは Hyrum’s Law と Postel’s Law が同時に作用した例のようだ
「API の利用者が十分に多ければ、システムの観測可能なあらゆる挙動に誰かが依存するようになる」ということと、
「送るものには厳格に、受け取るものには寛容に」という原則が衝突した結果だ
今回は glibc の resolver が壊れたことがポイントだ — 決して珍しい状況ではない
Cloudflare がきちんとテストしていなかったことこそ本当のニュースだ
今回のバグは、私に古い記憶を思い出させた
2011 年、Cloudflare が RFC を無視してドメイン apex に CNAME を許可したときのことだ
当時のブログ記事 を見ると、「RFC など無視して現実の問題を解決する」と言っていた
しかし CNAME は名前レベル (alias) の概念なので、apex に置くと NS、MX、SOA のキャッシュが壊れる
当時、多くのエンジニアが警告したが、「move fast and break things」だった
それでも今回は CNAME チェーンと A レコードの順序を細かく扱っているのを見ると、進歩はしている
CNAME と alias の概念は昔から混乱を生み、RFC1034 の非規範的な言語がその混乱をさらに大きくした
こうした曖昧さが積み重なった結果だが、大規模サービス提供者がこの種のミスをしたのは依然として容認しがたい
むしろ仕様そのものが問題だったのだと思う
glibc の一般的な DNS lookup がレコード順序に依存していることに驚いた
20 年以上も大きな問題がなかったのが不思議なくらいだ
おそらく大半の DNS 運用者は、テストの中で順序が重要だと経験的に知っていたのだろう
Cloudflare のように世界中の数百万台のデバイスに影響したケースは初めてで、それで注目されたのだ
ただ、Cloudflare が今回 glibc のようなオープンソース resolver にパッチを送ったのかは気になる
CNAME は本当に扱いにくい存在だ(DJB のメモ 参照)
glibc のような単純な resolver にはキャッシュがないため、これを実装するには大幅なコード変更が必要だ
Cloudflare が「RFC は CNAME の順序を要求していない」と主張したのは言葉尻を捉えた議論のように聞こえる
「MUST」がないからといって「どんな順序でもよい」とするのは無理がある
間違いを認めて先に進む方が、世の中をより良くすると私は思う
言葉の議論で責任を回避するのは、むしろ信頼を損なう
Cloudflare は RFC1034 を正しく理解していないようだ
彼らの DNS インターフェースでは、CNAME があると A、AAAA だけを禁止し、他のレコードは許可している
そのため CNAME と TXT が共存するとキャッシュ依存の結果が発生する
internet.nl でもこの問題が見つかっていた
一部の利用者は mxtoolbox ガイド に従って設定していたが、これは RFC1034 と衝突する
1 つは「DMARC サービスを CNAME で委任する方法」、もう 1 つは「自前でホストする方法」だ
スクリーンショットが混乱を招いたようだ
Cloudflare が最終的に「CNAME は他のレコードより前に来るべきだ」という結論に達したのは妥当だ
会社で DNS を管理する中で、DNS のさまざまな限界を実感した
特に SERVFAIL が発生すると、クライアントはどのサーバーに問題があるのか区別できない
その結果、複数の DNS サーバーとキャッシュ層が不要な再試行の殺到を引き起こす
また search path が誤ったドメインに NXDOMAIN クエリを繰り返してしまう
RFC2308 セクション 7.1 によれば、SERVFAIL 応答をキャッシュすることは許可されている
古い標準だが、今でも有効なアプローチだ
Cloudflare はしばしば標準を破り、それを正当化する新しい RFC を書く
RFC 8482 のような事例は業界の不名誉だと思う
「今回も混乱を防ぐために新しい Internet-Draft を提出した」という話が皮肉に聞こえる
1.1.1.1 のような大規模 DNS サーバーなら、glibc のような実際の resolver を含む統合テストがあるべきだ
それなのに、なぜこんな問題が本番環境でしか発見されなかったのか疑問だ
個別テストは通っていても、2 つの条件が重なるケースは漏れていた可能性が高い