DNS 線格式

最後更新: 2025-05-29 15:04:54 +0800 +0800
原文以英文撰寫。您正在閱讀AI翻譯版本。

DNS 查詢和回應以 12 位元組標頭開頭,後面依序是 Question、Answer、Authority 和 Additional 區段。所有多八位元組整數欄位都使用網路位元組順序。RFC 1035 定義了基本格式;EDNS、DNSSEC 以及後續擴充在不變更基本標頭的情況下新增記錄 和標頭語意。

標頭 #

欄位位元用途
ID16由用戶端選取並在回應中回送的識別碼
QR1查詢(0)或回應(1)
Opcode4操作;QUERY 為零
AA1回應中的權威回答指示
TC1訊息已被截斷
RD1用戶端要求遞迴
RA1伺服器提供遞迴
Z3保留的基本位元;擴充使用 AD 和 CD
RCODE4基本回應碼
QDCOUNT16Question 數量
ANCOUNT16Answer 記錄數量
NSCOUNT16Authority 記錄數量
ARCOUNT16Additional 記錄數量

RD 要求接收伺服器執行遞迴;RA 宣告伺服器能夠執行遞迴。AA 表示回應 伺服器對該回答具有權威性,不表示訊息中的每筆記錄都具有權威性。TC 告知 用戶端,當遭截斷的回應不足以完成處理時,必須透過 TCP 或其他支援的傳輸方式 重試。

名稱和 Question #

網域名稱是一連串的標籤。每個一般標籤都以長度介於 0 到 63 的八位元組開頭, 而零長度的根標籤會終止名稱:

text
03 www 07 example 03 com 00

完整的編碼名稱(包括長度八位元組和根標籤)限制為 255 個八位元組。Question 包含 QNAME、16 位元的 QTYPE 和 16 位元的 QCLASS;網際網路類別(IN) 的值為 1。

為避免重複的後綴,名稱可以使用壓縮指標。指標的前兩位元是 11,其餘 14 位元 是相對於訊息起始位置的偏移量。指標只能指向較早的位置。由於 DNS 訊息是不受 信任的輸入,剖析器必須限制指標深度、驗證偏移量並偵測迴圈。

Resource Record #

Answer、Authority 和 Additional 區段承載 Resource Record:

text
NAME | TYPE | CLASS | TTL | RDLENGTH | RDATA

TTL 編碼在 32 位元欄位中,並依據 RFC 2181 視為非負的快取存留期,有效範圍為 0 到 \(2^{31}-1\)。RDLENGTH 限定特定類型 RDATA 位元組的範圍。RRset 是具有 相同 owner name、class 和 type 的記錄集合;DNSSEC 為 RRset 簽署,而不是為個別 記錄簽署。

常見的 RDATA 包括四位元組 IPv4 位址(A)、16 位元組 IPv6 位址(AAAA)、 網域名稱(NS、CNAME、PTR),以及結構化值,例如 MX 的 preference 加 exchange name,或 SOA 的計時器。RDATA 中的名稱也可以使用壓縮,但前提是適用 的 RFC 允許如此。

EDNS 使用 Additional 區段中的 OPT pseudo-record,通告 UDP 負載大小、擴充的 RCODE 位元、旗標和選項。協商 EDNS 後,伺服器不得假設 UDP DNS 受限於 512 位元組; 但用戶端仍必須處理截斷並重試。

安全剖析 #

將接收到的資料報或串流框架視為唯一有效的位元組範圍。在讀取每個固定寬度欄位、 標籤、指標或 RDATA 值之前,驗證完整欄位仍位於該範圍內。區段計數不可信;如果 宣告的記錄數量無法容納,便停止處理。

名稱解壓需要兩個位置:呼叫端下一個尚未讀取的偏移量,以及用於重建名稱的指標 追蹤偏移量。計算指標跳轉次數或追蹤已造訪的偏移量以拒絕迴圈,拒絕保留的標籤 前綴,強制執行 63 個八位元組的標籤限制和 255 個八位元組的展開名稱限制,並且 絕不解讀訊息範圍之外的指標目標。

對於 TCP 和 TLS 傳輸,兩個八位元組的長度前綴會為每則 DNS 訊息提供框架,但它 不是 DNS 標頭的一部分。剖析前必須精確讀取指定長度的位元組。對於 OPT 記錄, 將其 TTL 欄位中的擴充 RCODE 與基本標頭 RCODE 合併,並在 RDLENGTH 與訊息範圍 兩者之內剖析每個選項。

參考資料 #

評論

在 GitHub 上閱讀或評論(發表評論需要登入)