為了測量一個 DNS 服務器的放大性能,使用dig命令向能夠放大的 DNS 服務器請求某個具有大量回復的域名的 ANY 資源,并利用 tcpdump 進行捕包。
dig @x.x.x.x xxx.gov ANY
tcpdump -i interface -n -vv '(udp) and (port 53) and (host x.x.x.x)'
問題1:
- 問題描述:收到了一個 IP 包長度為1500的分片包,但沒有收到后續的 IP 分片包。
- 解釋:這是因為除了第一個分片包,其他分片包本身并不包含 UDP 或 TCP 頭部,所以也無從得知這些 IP 包的端口號,后續的IP分片包也就被過濾掉了。
- 解決辦法:把
port 53
這一過濾條件刪除。
問題2:
- 問題描述:根據RFC 1035,使用UDP的 DNS 回復包大小被限制在512字節,但是這次回復顯然超過了512字節,這是為什么?
- 解釋:x.x.x.x DNS 服務器應該實現了 DNS 擴展機制——EDNS0,EDNS0允許大于512字節的UDP回復包。DNS 響應因為引入了一些大型數據項,如 AAAA 記錄,DNSSEC 信息(例如RRSIG或DNSKEY),或大型 TXT 記錄,導致其大小增加。EDNS 提供更大的 UDP 載荷能力可以避免 DNS 廣泛使用 TCP 進行通信,提高 DNS 的可伸縮性。關于 EDNS 詳情參考RFC 6891。
問題3
問題描述:dig提示
;; Truncated, retrying in TCP mode.
,也就是說回復太大,被DNS服務器截斷了,并沒有返回完整的資源記錄,重新使用了TCP進行查詢。對比了一下 TCP 回復的資源記錄和 UDP 回復的資源記錄,TCP 回復的資源記錄更多,也就是說即使啟用了 EDNS0,仍然會有最大長度的限制,超過這個限制仍然會轉去使用 TCP。那這個限制是多少呢?是在客戶端設置的還是服務器端設置的呢?-
解釋:在RFC 6891的 Payload Size Selection 章節中討論了這一問題:
Due to transaction overhead, it is not recommended to advertise an architectural limit as a maximum UDP payload size. Even on system stacks capable of reassembling 64 KB datagrams, memory usage at low levels in the system will be a concern. A good compromise may be the use of an EDNS maximum payload size of 4096 octets as a starting point. A good compromise may be the use of an EDNS maximum payload size of 4096 octets as a starting point.
大致意思是考慮到傳輸的開銷,不建議把可接收的UDP負載設的太大,所以把'EDNS的最大有效載荷大小為4096字節'作為一個折衷方案。
實驗表明,UDP負載大小限制是在服務器端設置的,和客戶端發送的請求包中 OPT 記錄設置沒有關系(請求包中有OPT 記錄表明客戶端支持 EDNS,如果沒有,DNS 服務器最多回復512字節,如下圖所示)。關于服務器是如何設置的以及為什么不需要看請求包的 OPT 記錄還需要查看RFC 6891進行確認。
dig-DNS請求包
實驗過程如下:
dig @x.x.x.x xxx.gov ANY +bufsize=1024
dig @x.x.x.x xxx.gov ANY +bufsize=8192
"+bufsize=xxxx"是把請求包的 OPT 資源 UDP payload size 修改成xxxx,DNS 請求包證實可以修改,如下圖所示:
但是從收到的回復包來看不管設置成1024還是8196,服務器仍然按照4096進行截斷。也就是說這個UDP負載大小限制是在服務器端設置的,和客戶端發送的請求包中 OPT 記錄設置沒有關系。
參考資料:
- 使用 DNS 的擴展名機制 (EDNS0),oschina.
- DNS系統與DDOS攻擊的關聯,51web.