最初に登場したのは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の曖昧な記述と実装依存によりトラブルの温床
- 今回の障害は仕様解釈の違いとテスト不足が要因
- 安定運用には実装間の互換性と明確な仕様遵守が重要