在 DNS 名稱解析中,瀏覽器如何在眾多 DNS 伺服器中確定最近可用的 DNS 伺服器?
我知道有 13 個根伺服器,但是我的 ISP 的 DNS 伺服器如何知道要聯絡哪個根 DNS 伺服器?
答案1
你的瀏覽器沒有。您的瀏覽器將使用標準系統呼叫來解析主機名稱(通常,我相信getaddrinfo()
),並且這些通常會依次檢查 的內容/etc/resolv.conf
以查找配置的解析名稱伺服器,並查詢它們。他們將依次將桌面作業系統的查詢轉發到上游伺服器(快取任何回應)或自行執行遞歸解析。請注意,上述鏈中的大多數步驟都是可配置的,因此您的瀏覽器實際執行的操作將由本機決定;但上面的場景是典型的。
該鏈中的遞歸解析名稱伺服器(無論是本地配置的權威名稱伺服器,還是一些 ISP 的伺服器)需要知道如何找到根伺服器,並且它們透過預先配置的區域檔案來完成此操作for .
(通常透過查詢可用的根名稱伺服器定期更新)。
編輯: 沒有。它將依賴實現,但在我的情況下(BIND),它只是選擇一個並查詢它。只要及時得到答案,就會從那裡向下遞歸。是什麼讓您認為正在進行任何類型的測距操作?
答案2
在 DNS 名稱解析中,瀏覽器如何在眾多 DNS 伺服器中確定最近可用的 DNS 伺服器?
如其他答案所示,您的瀏覽器或其他客戶端程式不會執行此選擇。客戶端程式透過呼叫稱為解析器的函式庫來請求名稱服務解析。
解析器決定它應該聯繫哪些伺服器來提出查詢。這取決於解析器的實現,但是通常它按順序查閱已配置的遞歸解析器列表(透過靜態配置或透過 DHCP 等機制接收它們)。
總之:您的(使用者層級)程式要求解析器進行名稱解析,解析器詢問透過某種設定機制提供給它的名稱伺服器。
我知道有 13 個根伺服器,但是我的 ISP 的 DNS 伺服器如何知道要聯絡哪個根 DNS 伺服器?
這也取決於實現。我將描述它如何與 BIND 一起工作,因為
- BIND 是一個非常流行的名稱伺服器,您的 ISP 很有可能正在使用它,並且
- 即使您的 ISP 不使用 BIND,某些替代方案也會使用類似的機制從 NS 資源記錄集中選擇名稱伺服器。
首先,我們首先討論遞歸名稱伺服器如何知道選擇哪些名稱伺服器來與特定網域進行通訊。對於從名稱伺服器的根(“.”)層級可存取的每個網域,管理該網域的管理員在包含的父網域中發布記錄類型NS(即名稱伺服器)的資源記錄集,以公開委託給名稱伺服器資源記錄集中指定的負責解決與該網域相關的查詢。
該系統的優點之一是它允許網域名稱系統的分散式分層委託,並且是遞歸伺服器所需的唯一網域先驗knowledge 是根級別,伺服器配置為了解該級別。過去最常見的做法是透過 BIND 在啟動時載入的「提示」檔案來指定根伺服器的 NS RRset,但現在根伺服器使用的 IP 位址已在 BIND 中預先定義。 [題外話:你仍然可以透過指定根提示區域來覆蓋內建項,事實上 d.root-servers.net 的位址最近發生了變化,新的位置不會反映在內建清單中,直到新的建置並分發包含新資訊的BIND 版本。目前包含 D 根伺服器新 IP 位址的版本處於測試階段。
無論如何,這裡的關鍵要點是每個網域都有一個與其關聯的 NS 記錄 RRset,其中包含該網域公開宣布的名稱伺服器。你應該嘗試自己看一些。我們來看看根源:
$ dig . ns +edns=0 @f.root-servers.net.
我將剪掉答案部分,其中包含以不可預測的順序返回的 NS RRset(我在這裡稍微掩飾一下——順序通常由我正在交談的名稱伺服器的配置決定)不同的根可能會以不同的順序回答,但所訂購的項目應該是相同的。
;; ANSWER SECTION:
. 518400 IN NS h.root-servers.net.
. 518400 IN NS j.root-servers.net.
. 518400 IN NS c.root-servers.net.
. 518400 IN NS l.root-servers.net.
. 518400 IN NS e.root-servers.net.
. 518400 IN NS a.root-servers.net.
. 518400 IN NS f.root-servers.net.
. 518400 IN NS k.root-servers.net.
. 518400 IN NS i.root-servers.net.
. 518400 IN NS d.root-servers.net.
. 518400 IN NS m.root-servers.net.
. 518400 IN NS b.root-servers.net.
. 518400 IN NS g.root-servers.net.
這些是根(“.”)網域的所有名稱伺服器,我們可以向其中任何一個詢問有關根網域的問題。如果我們向他們詢問有關根網域之外的內容的問題,我們將收到錯誤,或者更有可能收到另一組名稱伺服器的引用(例如「example.com?我不回答有關example.com 的問題。
那麼,BIND 如何知道 NS RRset 中的哪個名稱伺服器將為其提供最快的回應呢?
答案是:最初不會。但在其預設行為下,它會隨著時間的推移進行學習並確定通常詢問伺服器最短的往返時間。
往返時間和候選名稱伺服器的選擇 BIND 依賴 RR 集中名稱伺服器的往返時間 (RTT) 來選擇哪個名稱伺服器應接收其查詢。第一次將某個網域的 NS RRset 新增到快取時,該集中的所有記錄都會被分配一個小的隨機往返時間(大約幾毫秒)。在初始啟動之後,當需要將查詢定向到為給定網域委託的名稱伺服器時,BIND 將檢查其快取並(希望)找到 RRset。它從集合中選擇 RTT 時間最低的伺服器並進行查詢。當查詢完成後,BIND 會更新 NS RRset 的 RTT,如下所示:
- 剛剛查詢的伺服器的 RTT 設定為其實際往返時間。
- RRset 中的所有其他伺服器的 RTT 都減少了一小部分(我認為約為 3-4%..)
讓我們透過一個例子來看看它是如何運作的。當我的遞歸解析器第一次遇到網域 example.com 時,它將 example.com 的 NS RRset 載入到其快取中。假設 example.com 的管理員已為 example.com 宣布了三個名稱伺服器,因此 NS RRset 如下所示:
example.com NS servera.example.com
example.com NS serverb.example.com
example.com NS serverc.example.com
在此範例中,我們還假設您的解析器需要花費以下時間來接收來自該群組中每個伺服器的回應:
servera -- 30 ms
serverb -- 45 ms
serverc -- 50 ms
現在,第一次載入 example.com NS RRset 時,RTT 權重將使用小的隨機值進行初始化。因此,在我們向 example.com 名稱伺服器詢問任何內容之前,RTT 表可能如下所示:
servera -- 8 ms
serverb -- 9 ms
serverc -- 7 ms
第一次查詢 example.com 時,我們將前往 serverc 並提出我們的問題。 Serverc 需要 50 毫秒來回應,因此在查詢完成後,我們更新 RTT 表,使其現在顯示為:
servera -- 7 ms // reduced by a small fraction
serverb -- 8 ms // reduced by a small fraction
serverc -- 50 ms // updated to reflect the actual round trip time.
下次我們顯然會選擇 servera,因為它現在的往返時間最短。在對 example.com 網域進行幾次查詢後,我們應該對哪個名稱伺服器為我們提供最快的回應有相當不錯的了解,此後我們將更喜歡該伺服器最多的時間。
為什麼最多的時間和不全部的時間?我之前提到的「RRset 中的所有其他伺服器的 RTT 都減少了一小部分」是怎麼回事?好吧,事實證明,雖然我們想要更喜歡最快的伺服器,我們不想永久註銷其他伺服器。也許伺服器 c 幾乎一直是最快的伺服器,但在我們第一次設定其 RTT 時,它異常繁忙。也許伺服器暫時停止服務,導致 RTT 非常高(在我們嘗試查詢逾時之後),但我們希望在它恢復服務後再次開始詢問。透過每次向下調整其他伺服器值,它們遲早會低於我們首選伺服器的平均 RTT。當這種情況發生時,我們將向他們的方向發出一個查詢,如果時間更好,那就太好了。回前面。我們的絕大多數查詢將發送到集合中最快的一個或多個伺服器,但會定期嘗試異常值,以確保如果條件發生變化,表會更新以反映這一點,並且平均而言仍然會選擇最佳伺服器。
答案3
13 個根網域伺服器其實不是 13 個伺服器。每台伺服器都是分佈在世界各地不同站點的分散式伺服器集群,它們可以透過標準 IP 路由進行訪問,就像任何其他伺服器一樣。
至於哪個ISP 的 DNS 伺服器選擇聯絡的根名稱伺服器,這可能取決於其 DNS 解析器的詳細資訊。也許它是完全隨機的,也許它是加權的,但我無法告訴你。
編輯:如果你的意思是,ISP 是如何做到的尋找13 個名稱伺服器中的任何一個,都有一個公開清單及其對應的 IP 位址,基本上每台電腦都有。從那裡開始,只需選擇一個,然後讓互聯網的路由器完成其餘的工作。