DNS 回應裡到底該先出現 CNAME,還是 A 紀錄? (★ 109 分)
Cloudflare 表示,2026-01-08 對公共 DNS 遞迴解析器 1.1.1.1 的例行更新,原本只是為了降低快取實作的記憶體用量,卻意外引爆全球一波 DNS (Domain Name System,網域名稱系統) 解析失敗。主因不是攻擊或機房停擺,而是回應封包中資源紀錄 RR (Resource Record,資源紀錄) 的排序被「微小地改變」:部分用戶端實作假設 CNAME (Canonical Name,別名紀錄) 必須出現在答案區段最前面,一旦順序顛倒就會判定沒有答案。這個變更在 2025-12-02 進入程式碼、12-10 進測試環境,2026-01-07 晚間開始全球部署,01-08 18:19 UTC (Coordinated Universal Time,世界協調時間) 宣告事件並回復版本,19:55 回復完成後影響結束。
文章用 CNAME 鏈解釋問題如何發生:查詢 `www.example.com` 可能得到多段別名,最後才落到 A 紀錄 (IPv4 位址紀錄) 或 AAAA 紀錄 (IPv6 位址紀錄)。遞迴解析器會把鏈上的每一段以各自的 TTL (Time-To-Live,快取存活時間) 快取起來;當鏈的一部分過期時,只需重新解析過期那段,然後把「仍有效的 CNAME 鏈」與「新解析出的 A/AAAA」合併回一個回應。Cloudflare 為了減少記憶體配置與拷貝,把原本「先放 CNAME、再放 A/AAAA」的合併邏輯,改成直接把 CNAME 追加到既有答案清單尾端,導致某些情況下 CNAME 反而出現在 A/AAAA 之後。對採「逐筆序列掃描」的用戶端來說,它們會用「目前期待的名稱」去比對每筆紀錄,先看到不符合的 A 會被忽略,等看到 CNAME 才更新期待名稱,但此時清單已經掃完,於是回應被當成空的。受影響案例包含 Linux 常用的 glibc (GNU C Library,GNU C 函式庫) `getaddrinfo` 解析流程,以及部分設定使用 1.1.1.1 的 Cisco 乙太網路交換器,其 DNSC 行程甚至會因此進入重開機迴圈;相對地,systemd-resolved 這類會先把所有答案收集成可查詢集合、再依名稱搜尋追鏈的實作則不受影響。
Cloudflare 進一步把矛頭指向標準文字的「歷史性含糊」。DNS 核心規範 RFC 1034 (Request for Comments,網際網路標準文件) 在描述遞迴回應時用到「possibly preface」這種非強制語氣,且年代早於 RFC 2119 對 MUST/SHOULD 等規範用語的標準化;同時,RFC 對 RRset (Resource Record Set,同名同型別同類別的一組紀錄) 只明確說「同一個 RRset 內順序不重要」,卻沒有清楚規定「不同 RRset 在同一個答案區段的相對順序」,讓 CNAME 與 A/AAAA 的排列空間出現灰色地帶。文章也指出,即使都放在前面,CNAME 鏈本身若不是照鏈順序排列,序列掃描同樣會斷鏈。就實作者責任而言,RFC 提到遇到 CNAME 會「重啟查詢」,但那多以完整解析器為前提;實務上多數應用程式使用的是 stub resolver (簡化版本機解析器,如 glibc),未必照該模型處理。Cloudflare 最終決定尊重既有生態:回復原排序,未來也打算固定讓 CNAME 依序出現在其他答案之前,並提出 IETF (Internet Engineering Task Force,網際網路工程任務組) Internet-Draft,希望把「答案區段需有序」正式寫進可落地的標準。
Hacker News 討論多把此事視為 Hyrum’s Law(使用者夠多時,任何可觀察行為都會被依賴)在基礎網路協定上的示範,並延伸到 Postel’s Law(傳送要保守、接收要寬鬆)是否仍適用:有人主張「寬鬆接收」會縱容更糟的送出行為,甚至認為應該「盡早失敗」;也有人認為可寬鬆但要有警告期,隨即遭反問「像 DNS 這種協定要把警告放哪裡」。不少留言質疑 Cloudflare 竟未用 glibc 這類最常見用戶端做相容性測試;也有人替其解釋,測試可能只驗證紀錄「存在」而非「順序」,加上標準文字不夠硬,使得排序檢查未被寫成斷言。另有一派直指 RFC 1034 的句子其實不含糊,「possibly」是在說 CNAME 不一定存在、但存在就應該放前面;不過即便爭論標準解讀,許多人仍認同 Cloudflare 的務實結論:面對難以更新的舊設備,只能配合既成事實。討論也觸及營運面:回復部署耗時約 1 小時 28 分鐘,有人慶幸它不至於更快、並強調全球變更(含回復)也該分批觀察;另有人建議除提新草案外,應考慮對舊 RFC 提 errata (勘誤) 或在被取代文件上加醒目提示。最後,還有讀者趁機吐槽「It’s always DNS」:例如 SERVFAIL(伺服器失敗)無法區分是遞迴端故障或權威端出錯,EDE (Extended DNS Error,延伸 DNS 錯誤) 也難完全解;以及 search path 造成大量 NXDOMAIN(不存在網域)嘗試、加上遞迴與快取解析器(如 Unbound)層層重試,讓上游流量看起來像被放大攻擊。
👥 38 則討論、評論 💬
https://news.ycombinator.com/item?id=46681611