接受條件與競爭 — ID / port / TTL / time window
用 ID / source port / TTL 的具體數字來掌握回應接受條件與 race window。
前章回顧: 第 2 章中,我們將 referral / glue / bailiwick 加以區分,並整理 Additional 中的附加資料可以信任到何種程度。本章將以此為基礎,用具體數字來掌握 resolver「在何種條件下會接受回應」,以及為了繞過這些條件所需的 race window 與 entropy 之間的關係。
接受條件不只一項
resolver 會用多個屬性比對,判斷回來的 packet 是否為「目前正在等待的 query 的回應」,並不只看 ID。必須連同 question、source / destination address、source / destination port 全部一致,才會被視為「同一個 transaction」。
練習 3-1 — 要比對的是什麼
如果只停在「transaction ID 只有 16 bit 所以很弱」的說法,就會忽略 port 與 address 的意義。RFC 5452 是「彙整提升 DNS 對偽造回應之耐受度的對策的 RFC」,定義了在接受回應時應該比對什麼。
Q1. 依照 RFC 5452 的說明,下列何者不屬於遞迴解析伺服器在接受回應時會比對的屬性?
DNS 不會用 HTTP 的標頭來判斷是否接受回應。
RFC 5452 要求比對 question section、transaction ID、來源 / 目的 address、來源 / 目的 port。HTTP Host header 是 HTTP 層的值,不包含於 DNS 回應的接受條件中。
Q2. 如果 transaction ID 只有 16 bit,候選共有幾種?
就是 2 的 16 次方。
16 bit 的 transaction ID 共有 65,536 種。單靠這點對 off-path 的 guessing 來說不算夠寬,因此 source port 等其他一致條件也很重要。
race window 雖短,但不是零
off-path 的 forged response 會有意義,是因為在真正的 authoritative response 還沒到達之前有一段短暫時間窗。實際 network 條件很多樣,概念上可以想成「在等待期間,先到且又符合條件的東西一來就危險」。
| 時間軸上的點 | 意義 |
|---|---|
| 發出 query | resolver 開始抱有 outstanding query |
| forged response 群 | 抵達的偽造回應。若符合接受條件就可能進入 cache |
| authoritative response | 真正的回應抵達後,之後的偽造回應就不會被接受 |
練習 3-2 — race window 與 entropy
off-path 的 forged response 會有意義,是因為在真正的 authoritative response 還沒到達之前有一段短暫時間窗。
Q3. 要讓 off-path 的 forged response 贏,哪一段時間特別重要?
要意識到真正的回應還沒到達的「等待時間」。
重點是 query 還 outstanding 的期間,也就是真正的 authoritative response 抵達之前的那段短暫 race window。若偽造回應在這個時間窗內先滿足比對條件,就會產生危險。
用簡易模型看 race 與 entropy
在腦中組裝一個把 RFC 5452 的思考方式為了說明而簡化過的概念模型。忽略實作差異與 network 條件,直觀地理解「比對空間越寬越難猜中」「嘗試次數越多越危險」。
| 輸入 | 角色 |
|---|---|
| transaction ID bits | 提供最多 16 bit 的比對空間 |
| source port bits | 在高範圍 ephemeral port 帶中,最多可提供近 16 bit 的額外空間 |
| 額外 entropy(例如 0x20) | 利用標籤大小寫變化等,再疊上幾個 bit |
| 每個 window 的 forged packets | 攻擊方能在 race window 內送入的封包數量 |
| identical outstanding queries | 並行保留相同查詢的條數 |
| attempts | 觸發 fresh miss 重複 race 的次數 |
什麼是 0x20 編碼: DNS 的名稱解析本質上是 case-insensitive(不區分大小寫)的。例如 www.example.com 與 WwW.ExAmPlE.cOm 會被視為相同名稱。利用這個特性,resolver 在送出查詢時可隨機混合大小寫字母,並驗證回應中是否回傳相同的字母排列,如此便可將標籤字元數對應的 bit 數作為額外 entropy 使用。這種技術稱為 0x20 編碼(因大寫與小寫字母的 ASCII 差距為 0x20 而得名)。
請記住:即使一次的成功機率很小,只要 attempts 增加,累積成功機率就會上升。
port entropy 與 NAT
source port randomization 是有效的 hardening,但如果從外部看到的 port 空間很窄,效果就會打折。當 NAT 或 middlebox 會把 port 改寫成 sequential / small-range 時,這一點必須留意。
練習 3-3 — port entropy 與 NAT
source port randomization 是有效的 hardening,但如果從外部看到的 port 空間很窄,效果就會打折。
Q4. 對每次查詢都隨機化 source port 的主要效果是哪一個?
想想除了 ID 之外,還必須猜中什麼。
source port randomization 會在 transaction ID 之外再擴大必須一致的空間,讓 forged response 的猜測更難。這和 DNSSEC 是不同的 hardening 手段。
Q5. 當 NAT 把 recursive resolver 對外的 UDP source port 改寫為一個小的連續範圍時,最容易發生什麼?
重點是真正對外發出的 port 多樣性是否還保得住。
當 NAT 將對外 source port 擠壓為小而可預測的範圍時,實效 entropy 就會下降。即使內部是 random,從外部看到的 port 空間一旦變窄,hardening 的效果就會跟著打折。
複習專欄 — 用秒數追蹤 TTL 的剩餘秒數
雖然稍微偏離本章的主軸 (接受條件、entropy、race window),但藉此再次確認在第 1 章談過的 TTL 計算方式。能立即回答剩餘秒數的感覺,在第 6 章維運觀察中分辨「stale」與「異常」時也會反覆使用。
複習專欄 — 用秒數追蹤 TTL 的剩餘秒數
雖然稍微偏離 race / entropy 的主軸,但藉此再次確認在第 1 章談過的 TTL 計算方式。能立即回答剩餘秒數的感覺,在第 6 章的維運觀察中也會反覆使用。
Q6. 有一筆錯誤答案在 13:00:00 以 TTL 240 秒被 cache。13:02:30 時剩下的 TTL 是幾秒?
2 分 30 秒就是 150 秒。
從 TTL 240 秒減去經過的 150 秒,剩下 TTL 就是 90 秒。在維運時能用秒數掌握「目前看到的值還剩多少秒」,就比較容易分辨是 stale 還是異常。
第 3 章重點整理
- DNS 回應的接受條件不只 ID,還包含 question / address / port
- 真正關鍵的是 authoritative response 抵達之前的短暫 race window
- source port randomization 有效,但 NAT 可能會把 entropy 壓垮