Cloudflare 1.1.1.1 DoH JSON 變了怎麼辦?先避免硬編碼 data 格式
如果你的程式把 Cloudflare 1.1.1.1 的 DoH JSON response 當成固定字串格式,最近可能遇到一種很難從 HTTP status 看出來的錯誤:查詢成功了,但 data 的內容和原本測試 fixture 不一樣,解析器因此失敗。
Cloudflare 在 2026-07-28 公告正在調整 application/dns-json 的 data 顯示方式,而且 rollout 期間可能同時收到舊格式與新格式。這次不是 endpoint 被移除,而是 JSON schema 本來就沒有正式 RFC;關鍵修正是不要把 data 當成可以跨 provider、跨時間固定不變的 wire format。
先確認是資料格式差異,不是 DNS 查詢失敗
先保留 HTTP 狀態、JSON 的 Status、record type 和 data,不要只記錄最後的解析例外:
curl -fsS \ -H 'accept: application/dns-json' \ 'https://cloudflare-dns.com/dns-query?name=cloudflare.com&type=HTTPS'成功 response 仍然可能是 JSON,例如:
{ "Status": 0, "Answer": [ { "name": "cloudflare.com", "type": 65, "TTL": 300, "data": "1 . alpn=h3,h2 ipv4hint=..." } ]}這裡要分開看三個層次:
- HTTP 是否成功,例如 200。
- DNS response 的 Status 是否代表查詢成功。
- 你的程式是否能依 type 解讀 data。
前兩層都成功,第三層仍可能因格式差異失敗。用 type 而不是只看文字內容判斷 record 類型,才能把問題定位在解析邏輯。
Cloudflare 這次改了哪些 data 格式
官方公告列出三組變更:
- CAA、NAPTR、RP、IPSECKEY、SVCB、HTTPS、TLSA、SSHFP、OPENPGPKEY 等額外 record,可能從 RFC 3597 的泛用十六進位格式改成標準 presentation format。
- RRSIG、DS、CDS、DNSKEY、CDNSKEY 的 DNSSEC algorithm identifier 改用數字,例如 RSASHA256 對應 8;DS digest type 也改用數字,例如 SHA-256 對應 2。
- HINFO 的 character-string 會個別加上引號,避免值內有空白時產生歧義。
另外,Cloudflare 明確提醒 rollout 期間可能同時拿到新舊格式。因此只替一個 fixture 加判斷,並不能保證其他 record type 已經完成遷移。
解析程式要依 record type 分流
如果你的需求只是列出 DNS 查詢結果,至少先保留型別與原始資料,讓日後能回放問題:
function normalizeAnswers(payload) { return (payload.Answer ?? []).map((record) => ({ name: record.name, type: record.type, ttl: record.TTL, data: record.data, }));}接著依 type 對應到 DNS library 或自己的 parser。不要寫成「只要把 data 用空白切開,固定取第 2、3 欄」;SVCB、HTTPS、NAPTR 和 DNSSEC record 的欄位規則不同,呈現格式也可能在 rollout 中改變。
可以把測試拆成以下幾組:
| 測試案例 | 要驗證的邊界 |
|---|---|
| A、AAAA、CNAME | 一般 address 與 target 的基本解析 |
| CAA、SVCB、HTTPS | quoted value、parameter 與空白分隔 |
| RRSIG、DS、DNSKEY | algorithm 與 digest type 使用數字 |
| 舊 fixture 與新 fixture | rollout 期間 parser 能否安全拒絕或相容 |
若你不需要把 record 內容轉成自己的結構,最安全的選擇是把 data 視為供顯示或記錄的文字,不要再對它做沒有規格依據的二次解析。
重要用途改用 DoH wireformat
Cloudflare 文件將 JSON 定位為方便查詢的格式,並指出關鍵用途應使用符合 RFC 1035 的 DNS wireformat。wireformat 的請求不是把 name、type 放在 JSON 裡,而是先由 DNS library 產生二進位 query:
# <base64url-encoded-dns-query> 要由 DNS library 產生curl -fsS \ -H 'accept: application/dns-message' \ 'https://cloudflare-dns.com/dns-query?dns=<base64url-encoded-dns-query>' \ --output response.bin若使用 POST,則將二進位 query 放在 request body,並使用 content-type: application/dns-message。回應也要交給支援 DNS wireformat 的 library 解碼,不要把 binary response 當 JSON 讀取。
這個分流適合:
- DNSSEC 驗證或稽核。
- 需要穩定欄位結構的監控與資料管線。
- 不希望被特定 resolver 的 JSON 顯示習慣綁住的服務。
使用 wireformat 不代表所有錯誤都消失;你仍要處理 HTTP 400、413、415、504,以及 DNS response code。
一個可回滾的遷移流程
不要直接把 production parser 改成「接受任何字串」。可以按這個順序處理:
- 把目前 JSON response、查詢參數、HTTP status 和查核日期存成 fixture。
- 依 type 補上 CAA、SVCB、HTTPS、DNSSEC 的新舊資料案例。
- 對只需要穩定結構的流程,改評估 wireformat。
- 先在 shadow 或測試流程同時執行新舊 parser,記錄差異但不改主流程。
- 確認監控能區分「DNS 查詢失敗」和「解析器拒絕未知格式」後,再切換 production。
結論是:Cloudflare 1.1.1.1 的 DoH JSON 仍可用,但 data 不應被當成固定 schema。查詢型工具可以保留 JSON 並依 record type 驗證;關鍵資料管線則應使用 wireformat,或至少把格式差異納入測試與可觀測性。
常見問題
Q: Cloudflare DoH JSON API 是不是要停用了?
A: 不是。Cloudflare 仍提供 GET JSON 查詢;這次公告是 data 的格式 rollout,而且可能同時出現新舊回應。真正需要調整的是依賴固定文字格式的 parser。
Q: 所有 DNS record 的 data 都會一起改嗎?
A: 官方列出的是額外 record、DNSSEC 相關 record 和 HINFO 的格式變更。不要假設每種 record 都改了,也不要假設尚未列出的格式永遠不會變;程式仍應依 type 和官方文件處理。
Q: JSON 和 wireformat 要怎麼選?
A: 只是查詢或顯示結果時,JSON 比較容易使用;若是 DNSSEC、監控、稽核或需要穩定結構的資料管線,優先使用 wireformat,讓 DNS library 解碼標準格式。
參考資料:
Cloudflare Changelog:Improved DoH JSON formatting
回報錯字、失效連結,或告訴我你想看的延伸主題。