理解 DNS 快取
學渣出品,技術/英文學習記錄,難免會有理解/翻譯瑕疵甚至錯誤,歡迎指正。
建議閱讀原文: Understanding DNS cache
當我第一次學習 DNS 解析 時,我被這個漫長和複雜的過程驚到了。想象一下你每天要訪問多少網站,再想一下你每天要訪問多少次。現在想象一下你每次訪問時,在另一端的 ISP DNS 伺服器必須重複整個遞迴過程,並查詢遞迴鏈中的所有域名伺服器。
以此為背景,想象一下你的手機。當你想跟你一個定期聯絡的朋友通個電話時,你很容易在最近通話中找到他們的名字並撥打。但是,如果這些資訊並沒有準備好,你就得打 114 來去獲取他們的號碼,然後手動撥出。看起來是不是很繁瑣?
實際上將域名轉化為 IP
地址 需要大量步驟,並且要消耗大量時間。幸運的是,DNS
的設計者考慮到了如何加速 DNS
,並實現了快取。DNS
快取使得 DNS Server
或者 客戶端本地儲存 DNS
記錄並在以後複用,減少了對新 DNS
請求的查詢需求。
域名系統為每一條 DNS
記錄實現了存活時間(TTL
)。TTL
指定了一條 DNS 記錄在 DNS
伺服器和客戶端可以被快取的秒數。當快取中存在該 DNS
記錄時,也會儲存其存活時長。伺服器會持續更新快取中的 TTL
,以秒為單位倒數計時。當它變為 0
時,該記錄會從快取中被刪除或者清除。此時,如果快取過期以後再次收到該記錄的請求,DNS
伺服器就必須啟動解析流程。
要理解快取,讓我們來看下上一篇文章中的例子,解析 www.google.com
。 當你在瀏覽器裡輸入 www.google.com
時,瀏覽器向作業系統詢問 IP
地址。作業系統有 stub resolver
或者 DNS client
(參考:什麼是 DNS Server
, resolver
以及 stub resolver
),一個作業系統響應所有 DNS
查詢的解析器。DNS 解析器會傳送 DNS 請求(並開啟遞迴查詢標記)給特定的遞迴解析器(域名伺服器)並根據其 TTL
值儲存其 DNS
記錄到快取。
當 Stub Resolver
收到一個應用程式的請求,它會先檢視自己的快取,如果快取中有該記錄,它會將快取中的資訊直接返回給應用程式。如果快取中沒有,則傳送 DNS
請求(並開啟遞迴標記)遞迴解析器(ISP
的 DNS
伺服器)。
當 Recursive Resolver
收到請求,它會先檢視快取中有 www.google.com
的哪些資訊。如果快取中有 A
記錄,則把記錄傳送給 Stub Server
。如果沒有 A
記錄,但是有權威域名伺服器的 NS
記錄,它將會請求這些權威域名伺服器(繞過根伺服器和 com gTLD
伺服器)。
如果沒有權威域名伺服器,它會請求 com gTLD
伺服器。
graph TD;
google.com-->Browser;
Browser-->OS;
OS-->Stub-Resolver;
Stub-Resolver-->Cached;
Cached-->Browser;
Stub-Resolver-->Not-Cached;
Not-Cached-->ISP-DNS;
ISP-DNS-->Cached-A-Record;
Cached-A-Record-->Stub-Resolver;
ISP-DNS-->Not-Cached-A-Record;
Not-Cached-A-Record-->Cached-Auth-NS-Server;
Cached-Auth-NS-Server-->Query-Auth-NS-Server;
Query-Auth-NS-Server-->ISP-DNS;
Not-Cached-A-Record-->Not-Cached-Auth-NS-Server;
Not-Cached-Auth-NS-Server-->COM-GTLD-Server;
COM-GTLD-Server-->ISP-DNS;
注:圖表為譯者根據自己理解新增(歡迎指正)
如果沒有權威名稱伺服器,就會請求 .com gTLD
伺服器(因為他們 TTL
非常高,他們一般是存在於快取中,並且他們適用於任意 .com
域名)。只有當他們不存在於快取時, Recursive Resolver
才會向根伺服器請求 gTLDs
, 這種情況非常少見(通常是指行了 purge
操作)。
為了避免傳播過期 DNS
記錄,DNS
伺服器將會通過矯正一個請求的 TTL
,而不是這條記錄原始 TTL
值。例如,假設 一條 www.google.com
記錄的 TTL
是 4
個小時,並且它在上午 8
點被 Recursive Resolver
儲存於快取中。如果有一個新使用者,在這個解析器,在上午 9
點請求相同的域名,resolver
將會傳送一個 3
個小時的 TTL
記錄。
現在我們已經覆蓋了 DNS
在 OS
和 DNS
伺服器的快取,然後就剩下最後一層快取:應用程式。所有應用都可以選擇快取 DNS
資料,即使他們不能遵循 DNS
標準。應用依賴作業系統函式 getaddrinfo()
來解析域名(所有作業系統都是用相同的函式名)。該函式返回域名的 IP
地址列表 - 但是他不返回 DNS
記錄,所以應用程式沒有 TTL
可用。
所以,不同的應用程式快取資料時間不同。IE10+
將在其快取中儲存最多 256
個域名,固定時間為 30
分鐘。256
個域名看起來好像很多,實際上不是的 - 網路上大量網頁都會飲用 50
個域名以上,多虧第三方標記和重定向。另一方面,Chrome 將快取 DNS 資訊一分鐘,並且儲存 1000
條記錄。你可以通過訪問 chrome://net-internals#dns 檢視和清理 Chrome
的 DNS
快取。
NS 快取陷阱
人們會經常掉入一個的 DNS
快取陷阱是權威名稱伺服器記錄。就像我們之前提到的,權威名稱伺服器在請求響應中作為 NS
記錄被指定。NS
記錄有 TTL
。但並不提供名稱伺服器的 IP
地址。IP
資訊在額外的 A
或者 AAAA
記錄響應裡。
因此,一個 Recursive Resolver
同時依賴於 NS
和 A
記錄來抵達名稱伺服器。理想情況下,兩種記錄型別的 TTL
應該相同,但是偶爾有人錯誤配置 DNS zones
,他們會在 DNS
請求傳入新的 A
或者 AAAA
記錄。新記錄覆蓋老記錄,導致產生差異。
當所有的記錄都在快取裡,Recursive Resolver
將會請求其中一臺域名伺服器的 IP
地址。如果 Recursive Resolver
快取中只有 NS
記錄,沒有 A
或者 AAAA
記錄,它就必須解析 名稱伺服器域名,比如 ns1.google.com
, 獲取其 IP
地址。這樣並不好,因為它增加了解析域的時間。並且,如果它有域名伺服器的 A
或者 AAAA
記錄但是沒有 NS
記錄,它會強制發起一個 域名 www.google.com
的 DNS
查詢。
設定 TTL: 平衡行為
那麼,TTL
時間長一些還是短一些會更好的呢?合適的的情況下,使用一個更長的 TTL
,因為它會使 resolvers
快取更久並且 OSS
-- 意味著對終端使用者而言意味著更好的效能,以及它會減少到你名稱伺服器的流量,因為請求會更少。無論如何,它也會減少你的變更 DNS
,使你更容易因為遭受 DNS
劫持攻擊,並在你的資料中心不可訪問時無法設定離線錯誤頁面。
換句話說,TTL
越短人們就越會花時間在下載頁面或資源,並增加你名稱伺服器的壓力。並且使你更快的變更 DNS
配置。
DNS
解析是一個多階段的由網際網路大量伺服器參與的過程。協議內建的快取機制通過快取並複用資訊加速了未來 DNS
請求的過程。DNS
伺服器 和/或 客戶端在 TTL
上遵循該 DNS
規範,但是像瀏覽器這樣的應用程式不遵循該規範 - 因此他們的快取可以儲存任意時間。