# Computer Networking — 2.4 DNS — The Internet’s Directory Service contributed by <[`kaeteyaruyo`](https://github.com/kaeteyaruyo)> ###### tags: `Computer Networking` 我們人類可以用很多種方式來辨別每個人,例如:出生證明上的名字、身份證字號,或是駕照上面的編號。雖然這些方法都可以用來辨識身份,但是在不同的情境下,或許某一種方法會比別的方法還要更恰當。例如:美國國稅局的電腦要查驗身份時,就會覺得身份證字號比出生證明上的名字還要好用。但另一方面,一般人在交談時就比較偏好使用好記憶的名字而不是身份證字號(確實,你能想像有人跟你說:「嗨,我是 S282866026,這是我老公 E132643678。」嗎?) 就跟人類可以用很多種方式辨別不同的人一樣,電腦主機也可以用很多種方式來識別身份。其中一個識別主機的方式就是**主機名稱 (hostname)**,像是 `www.facebook.com`、`www.google.com`,或是`gaia.cs.umass.edu` 之類的。主機名稱很容易記憶,因此人類比較習慣用這種方式來識別不同的主機。但是主機名稱並沒有辦法提供太多關於這個主機到底在網際網路的哪裡的資訊(例如:`www.eurecom.fr` 這個主機名稱,因為結尾是 `.fr`,所以我們只能知道他大概是在法國,但除此之外也沒辦法知道更多了)。除此之外,由於主機是由不等長的英數字元所組成的,所以對路由器來說會比較難處理。因為這些原因,我們還有另一種識別主機的方式,叫作 **IP 位址 (IP address)**。 我們會在第四章詳細介紹 IP 位址,但是現在稍微提一下它的概念會很有幫助。IP 位址是由四個位元組組成的,而且有固定的、階層式的結構。一個 IP 位址會長得像 `121.7.106.83`,每一個由 `.` 區分開的數字都是代表一個位元組的十進制數字(值從 0 到 255)。之所以說 IP 位址是一個階層式的結構,是因為當我們從左邊讀到右邊時,我們就愈能夠知道這台主機到底是在網際網路的哪裡(也就是這台主機到底在這個網路上的哪一個網路的哪一個部份裏面)。就像我們在閱讀地址的時候,我們愈往右邊讀,就愈能知道一間建築物具體來說到底在哪個地方。 ## 2.4.1 Services Provided by DNS 我們剛剛已經知道有兩種辨識主機的方式,一種是主機名稱、一種是 IP 位址。人類比較喜歡用好記憶的主機名稱來辨識主機,但路由器比較喜歡固定長度、有階層架構的 IP 位址。為了銜接這個差異,我們需要一個類似查號台的服務,來查詢主機名稱所對應的 IP 位址。這就是**網域名稱系統 (Domain Name System, DNS)** 的主要功能。DNS 是 (1) 一個由 DNS 伺服器以階層式架構所組成的分散式資料庫,(2) 一個讓所有主機都能夠查詢上述分散式資料庫的應用層協定。 DNS 伺服器通常都是 UNIX 系統的機器,並且會執行 BIND (Berkeley Internet Name Domain) 軟體 [BIND 2016]。 DNS 協定跑在 UDP 之上,使用的埠號是 53。 DNS 通常會配合其他的應用層協定一起使用,包含 HTTP 和 SMTP,他們都會用 DNS 來把使用者提供的主機名稱轉換成 IP 位址。舉個例子:假設有一個瀏覽器(HTTP 的客戶端)執行在某使用者的主機上,請求了 `www.someschool.edu/index.html` 這個 URL。為了讓這個使用者的主機有辦法向 `www.someschool.edu` 這台 Web 主機送出 HTTP 請求訊息,該使用者的主機必須要先取得 `www.someschool.edu` 的 IP 位址。因此會發生接下來的事: 1. 該使用者的機器要有執行 DNS 應用程式的客戶端。 2. 瀏覽器會從 URL 當中取出主機名稱的部份 `www.someschool.edu`,然後將這個主機名稱傳給 DNS 的客戶端。 3. DNS 客戶端會傳一個包含該主機名稱的詢問給 DNS 主機。 4. DNS 客戶端最後會收到一個回應,回應中會包含著該主機名稱對應到的 IP 位址。 5. 一旦瀏覽器收到了 DNS 主機傳來的 IP 位址,他就可以跟位於該位址的 HTTP 主機建立一個通往埠號 80 的 TCP 連線。 從這個例子中我們會看到,DNS 會對網際網路應用程式增加(有時是必要的)延遲。還好,等等我們就會看到,這些所需的 IP 通常會被快取在附近的 DNS 伺服器,這不但能減少 DNS 網路的流量,也可以降低平均的 DNS 延遲。 除了把主機名稱轉換成 IP 位址之外,DNS 也額外提供了幾個重要的服務: * **主機別名 (Host aliasing)**:如果有一個主機名稱很長很複雜,那麼我們可以另外幫他取一到多個別名。例如:`relay1.west-coast.enterprise.com` 這個主機就可以有像是 `enterprise.com` 和 `www.enterprise.com` 這兩個別名。在這個例子中,`relay1.west-coast.enterprise.com` 這個主機名稱就被叫作**正規主機名稱 (canonical hostname)**。如果一個主機有別名的話,通常他的別名會比正規主機名稱還要簡單好記。應用程式可以透過別名來向 DNS 主機詢問該別名對應到的正規主機名稱,還有該主機的 IP 位址。 * **信件伺服器別名 (Mail server aliasing)**:很顯然地,email 地址應該要有一個好記的名字。例如:如果 Bob 有一個 Yahoo 的信箱帳號,那他的 email 地址就應該要像是 `bob@yahoo.mail` 這樣很簡單。但是 Yahoo 的信件伺服器的主機名稱一定不是像 yahoo.com 這樣簡單好記,而是會更複雜許多(比如說:該主機的正規名稱可能會長得像 `relay1.west-coast.yahoo.com` 這樣)。 Email 服務可以透過別名來向 DNS 主機詢問該別名對應到的正規主機名稱,還有該主機的 IP 位址。事實上,MX record(稍後討論)允許一個企業給他們的信件伺服器和網頁伺服器都取同一個別名。例如:某企業的信件伺服器和網頁伺服器可以同時叫作 `enterprise.com`。 * **負載分散 (Load distribution)**:DNS 也可以用來在多個副本伺服器 (replicated servers) 之間進行負載分散,像是 replicated Web servers 等等。流量大的主機,像是 cnn.com,通常會在多台伺服器之間放置資料副本,這些伺服器會跑在不同的終端機器上,因此也有不同的 IP 位址。在這種使用了副本伺服器的情況下,一個正規主機名稱對應到的是一群 IP 位址的*集合*。DNS 資料庫當中就包含了這個 IP 位址的集合。當一個客戶端向 DNS 詢問的主機名稱對應到的是一個位址集合時,DNS 伺服器會回傳整個集合,但每回傳一次,DNS 都會把集合中的 IP 位址順序輪轉一格。因為客戶端通常都會發送 HTTP 請求給回傳位址列表中的第一個主機,所以每次都輪轉一格,就可以達到在不同伺服器之間分散流量的效果。DNS 輪轉也被用在 email 伺服器上,如此一來多個信件伺服器就可以有一樣的別名。還有,內容傳遞公司如 Akamai,以更複雜的方式 [Dilley 2002] 使用了 DNS 來提供網路內容傳遞的服務(詳見 2.6.3)。 DNS 的規格被記載在 RFC 1034 和 RFC 中,並在之後的多個 RFC 當中有更新。他是一個很複雜的系統,在這裡我們只會提到他的操作原理的核心概念而已。有興趣的讀者可以去詳讀上述的那些 RFC,還有 Albitz 和 Liu 所著的書 [Albitz 1993];另外,[Mockapetris 1988] 這篇回顧性的論文也很好的描述了什麼是 DNS 以及為何我們需要它,而 [Mockapetris 2005] 這篇也很值得一讀。 :::info :memo: **DNS: Critical Network Functions via the Client-Server Paradigm** 就像 HTTP, FTP 還有 SMTP 一樣,DNS 協定是一個應用層協定,因為它 (1) 運作在兩個互相溝通的終端裝置之上,並且使用的是主從式架構,(2) 依賴於底下的端到端傳輸層協定在終端裝置之間傳遞 DNS 訊息。然而從另一個角度來說,DNS 所扮演的角色卻又跟網頁服務、檔案傳輸服務或是 email 服務很不一樣。不像上述的這些應用程式,DNS 並不是以「讓使用者直接互動」的方式提供服務的。反之,DNS 提供的是網際網路核心的服務 —— 也就是為網際網路裡的其他應用程式和軟體提供把主機名稱轉換成 IP 位址的服務。我們在 1.2 節當中有提到,網際網路最複雜的部份大多都坐落在網路的邊緣。DNS,這個利用了網路邊緣中的主機與客戶端實作了關鍵性的主機名稱轉位址的服務,又是另一個展現了這個設計宗旨的好例子。 ::: ## 2.4.2 Overview of How DNS Works 接著我們來概念性地看過 DNS 服務是怎麼運作的。我們的討論會聚焦在主機名稱轉 IP 位址的這個轉譯服務上。 假設有某個運作在使用者主機中的應用程式(例如網頁瀏覽器或是 email 閱讀器),需要把某個主機名稱轉換成 IP 位址。該應用程式會呼叫 DNS 的客戶端,然後給它需要被轉換的主機名稱(在許多 Unix-based 的機器上,應用程式是透過呼叫 `gethostbyname()` 這個函式來進行轉譯的)。在使用者主機裡的 DNS 服務接著接手,將詢問的請求發送到網路裏面。所有的 DNS 請求和回應訊息都是放在 UDP 資料塊當中,通過埠號 53 進行傳送的。在一段延遲(長度可能從幾毫秒到幾秒)之後,使用者主機中的 DNS 就會收到包含所求的 IP 位址的回應。這個 IP 位址接著就會被送回剛剛呼叫 DNS 的應用程式。所以對於呼叫 DNS 的應用程式來說,DNS 就像是一個黑盒子一樣,提供了一個簡單、直觀的轉譯服務。但實際上,實作了這個轉譯服務的黑盒子內部的構造是很複雜的,這個系統是由散落在世界各地的非常多的 DNS 伺服器,以及一套規範了 DNS 伺服器如何和請求的主機溝通的通訊協定所組成的。 DNS 最簡單的設計就是單純只放一台 DNS 伺服器,在該伺服器中存放世界上所有的主機名稱-位址對應表。在這個中心化的設記下,客戶端們就只需要把所有的請求都送往這個單一的 DNS 主機就好了,該主機也可以直接回應給所有來詢問的客戶端。儘管這個設計的簡單俐落很吸引人,但是這對於現今的網際網路來說是不切實際的,因為現在網路中的主機數量增長得非常快又廣。中心化設計的問題包含: * **單點故障問題**。如果這台 DNS 主機壞掉了,整個網際網路也就跟著掛了! * **流量問題**。這一台 DNS 主機必須獨自處理所有的 DNS 請求(包含了由上億台的主機所產生的 HTTP 請求和 email 訊息等)。 * **遙遠的中心化資料庫**。一台 DNS 主機不可能「靠近」所有要詢問的主機。如果我們把這台主機放在紐約市,那麼所有從澳洲出發的請求都要橫跨半個地球才有辦法送達這台主機,或許中途還得要經過很擠又很慢的傳輸鍊結,這一定會造成很嚴重的延遲。 * **維護問題**。這一台主機必須獨自包存所有網際網路主機的資料。這台中心化的資料庫不僅可能會很大一包,他還可能會需要非常頻繁地更新,才能確保新出現的主機資料也都在裡面。 總結來說,在單一一台 DNS 主機中放一個中心化的資料庫*並不能規模化 (dosen't scale)*。順理成章地,DNS 就被設計成了一個分散式的系統。事實上,DNS 是一個完美展示分散式資料庫如何被實作在網際網路當中的一個好例子。 ### A Distributed, Hierarchical Database ![](https://hackmd.io/_uploads/B1JUN1IJ6.png) > Figure 2.17 DNS 伺服器架構的一部份 為了解決上述規模化的問題,DNS 系統使用了大量的伺服器,這些伺服器以階層化的架構排列,並且分佈在世界各處。並沒有哪一台單一的 DNS 系統持有世界上所有主機的 IP 對應表。相反地,這些對應表是分散地放在各個 DNS 伺服器當中。大致上來說,DNS 伺服器可以分成三類:根域名 DNS 伺服器 (root DNS servers)、頂級域名 DNS 伺服器 (top-level domain (TLD) DNS servers),還有權威域名 DNS 伺服器 (authoritative DNS servers),這三類伺服器以 Figure 2.17 的架構組織在一起。為了了解這三個階層的伺服器是如何互相溝通的,想像有一個 DNS 的客戶端想要詢問 `www.amazon.com` 這個網域名稱的 IP 位址。大致上來說,會發生以下幾件事。首先,客戶端會先聯絡上其中一個根域名伺服器,根伺服器會回傳好幾個負責頂級域名 `com` 的 TLD 伺服器的 IP 位址。接著客戶端就必須對這當中的其中一個 TLD 伺服器做查詢,該伺服器就會回傳好幾個負責權威域名 `amazon.com` 的權威域名伺服器的 IP 位址。最後,客戶端再對這幾個伺服器的其中一個做詢問,得到網域名稱 `www.amazon.com` 的 IP 位址。我們稍後就會詳細介紹這個 DNS 查詢過程。但在這之前,我們先來分別介紹這三種伺服器等級: ![](https://hackmd.io/_uploads/r1Kg61U1p.png) > Figure 2.18 2016 年的 DNS 根伺服器分佈 * **根域名 DNS 伺服器 (root DNS servers)**:(截至 2016 年,)世界上總共有超過 400 台 DNS 根伺服器散落各處。Figure 2.18 展示了世界上所有擁有 DNS 根伺服器的國家分佈,擁有愈多台的國家顏色愈深。這些根域名伺服器總共被分成 13 組進行管理,各組有哪些伺服器、分別由哪些組織進行管理,以及他們的 IP 位址,都可以在 [Root Servers 2016] 當中查詢得到。根域名伺服器負責用來提供 TLD 伺服器們的 IP 位址。 * **頂級域名 DNS 伺服器 (top-level domain (TLD) DNS servers)**:對於所有的頂級域名(像是 `com`, `org`, `net`, `edu` 以及 `gov`,或是國家域名如 `uk`, `fr`, `ca` 和 `jp` 等),它們都有一個對應的 TLD 伺服器(或是多個伺服器的叢集)。威瑞信環球註冊服務 (Verisign Global Registry Services) 這間公司負責維護負責 `com` 這個頂級域名的那些 TLD 伺服器,而 Educause 這間公司則負責維護負責 `edu` 這個頂級域名的那些 TLD 伺服器。支援 TLD 伺服器的那些網路基礎設施可能會很大型很複雜,[Osterweil 2012] 提供了有關威瑞信網路的非常不錯的概述。而在 [TLD list 2016] 當中則可以查詢到所有頂級域名的列表。TLD 伺服器負責提供權威域名伺服器們的 IP 位址。 * **權威域名 DNS 伺服器 (authoritative DNS servers)**:所有打算在網際網路上提供可公開存取的主機(像是網頁伺服器、信件伺服器等)的組織,都必須要提供一個可以公開存取的 DNS 條目,上頭要記載他們的網域名稱所對應到的 IP 位址。每個組織的權威域名 DNS 伺服器就是用來儲存這些 DNS 條目用的。組織們可以選擇自行實作他們自己的權威域名伺服器,也可以選擇付錢給其他服務商讓他們負責提供自己的 DNS 條目。大多數的學校和企業都是選擇自己實作與維護他們自己的主要和次要(備份用)的權威域名 DNS 伺服器。 根域名、頂級域名,以及權威域名 DNS 伺服器都屬於 Figure 2.17 的架構當中。但還有另一種也很重要的 DNS 伺服器類型,那就是**本地 DNS 伺服器 (local DNS server)**。本地 DNS 伺服器並不嚴格地屬於上述架構中的任何一層,但對於整個 DNS 架構來說卻是相當重要。每一個 ISP(像是家用網路的 ISP 或是企業的 ISP)都有一個自己的本地 DNS 伺服器(也稱作預設域名伺服器)。每當一個主機連上 ISP 時,ISP 都會提供給這台主機一到多個它的本地 DNS 伺服器的 IP 位址(通常是透過 DHCP 傳送的,關於這點我們在第四章會詳談)。你可以很簡單的透過打開你作業系統的網際網路狀態視窗來查詢到你的本地 DNS 伺服器的 IP 位址,通常這些伺服器都會離我們的主機很近。如果是企業的 ISP 的話,通常他們的本地 DNS 伺服器都會坐落在同一個區域網路裏面;而如果是家用網路 ISP 的話,這些本地 DNS 伺服器通常只會距離使用者沒幾個路由器的距離而已。每當一台主機想要送出 DNS 查詢時,這些請求都會先送到本地 DNS 伺服器,再由這台伺服器作為代理,將請求轉發到上述階層式架構中的那些伺服器去,我們接下來會詳談這個過程的細節。 ![](https://hackmd.io/_uploads/Bk3Zi-LJa.png) > Figure 2.19 各個 DNS 伺服器之間的互動流程 我們來看一個簡單的範例。假設 `cse.nyu.edu` 這台主機想要查詢 `gaia.cs.umass.edu` 這台主機的 IP 位址,再假設 NYU 裡面負責轉譯 `cse.nyu.edu` 這個域名的的本地 DNS 伺服器的主機名稱叫作 `dns.nyu.edu`,而負責 `gaia.cs.umass.edu` 這個域名的權威域名 DNS 伺服器其主機名稱則是 `dns.umass.edu`。就如同 Figure 2.19 所示,`cse.nyu.edu` 這台主機首先會往他的本地 DNS 伺服器 `dns.nyu.edu` 送出一個請求,該請求中包含了需要被轉譯的主機名稱,也就是 `gaia.cs.umass.edu`。接著這個本地 DNS 伺服器會把請求轉發給根域名 DNS 伺服器,根域名記下了主機名稱中 `edu` 這個部份,然後回傳給本地 DNS 伺服器一串負責 `edu` 這個頂級域名的 TLD 伺服器的 IP 位址列表。本地 DNS 伺服器接著就會隨便挑一個 TLD 伺服器,重新把剛剛的請求再發送過去,TLD 伺服器記下了 `umass.edu` 這個部份,然後回傳給本地 DNS 伺服器麻薩諸塞大學 (UMASS) 的權威域名伺服器的 IP 位址,也就是 `dns.umass.edu` 的位址。最後,本地 DNS 伺服器再把剛剛的請求直接發送到 `dns.umass.edu` 去,這次該伺服器就會回傳 `gaia.cs.umass.edu` 的 IP 位址了。你可以注意到在這個例子當中,為了要取得正確的 IP 位址,總共有 8 條 DNS 訊息被發送了,其中 4 條是請求訊息、4 條是回應訊息!接著我們就會看到 DNS 快取是如何降低這些請求的流量的。 在上述的例子中,我們假設 TLD 伺服器知道所求的主機名稱對應到的權威域名伺服器是哪一台。但實際上很常並不是這麼一回事。相反地,該 TLD 伺服器可能只認識另一個中介的伺服器,而該中介伺服器才知道負責該主機名稱的權威域名伺服器是誰。再把我們剛剛那個例子拿回來看,假設 UMASS 有自己的 DNS 伺服器,而 UMASS 裡面的每一個系所也都有自己的 DNS 伺服器,負責回答他們系所自己的主機名稱。在這個狀況下,當 `dns.umass.edu` 這個中介 DNS 伺服器收到想要轉譯在 `cs.umass.edu` (也就是資訊系)底下的主機的請求時,他就會把 `dns.cs.umass.edu` 的 IP 位址回傳給 `dns.nyu.edu`,因為該伺服器才真的有在負責那些 `cs.umass.edu` 結尾的主機名稱的轉譯。接著 `dns.nyu.edu` 再把訊息傳給資訊系的權威域名 DNS 伺服器,才能拿到該系所的本地 DNS 伺服器的位址,最後再向這台本地 DNS 伺服器查詢,才能拿到所求的主機名稱的 IP 位址。這一來一往總共就需要傳送 10 條 DNS 訊息了! 在 Figure 2.19 當中所展示的例子同時用上了**遞迴查詢 (recursive queries)** 和**迭代查詢 (iterative queries)**。從 `cse.nyu.edu` 送往 `dns.nyu.edu` 的查詢是一個遞迴查詢,因為該請求要求 `dns.nyu.edu` 這台伺服器代替最一開始送出請求的主機去找到所求的 IP 位址。但接下來的 3 個請求就都是迭代查詢,因為所有的回應都是直接回傳給 `dns.nyu.edu`。理論上,任何的 DNS 查詢都可以是迭代查詢或是遞迴查詢。舉個例子:Figure 2.20 展示了一個都是遞迴查詢的連鎖 DNS 查詢。但實際上,大多數的查詢過程都還是比較像 Figure 2.19 展示的那樣,只有一開始發出請求的主機到本地 DNS 伺服器這一個詢問是遞迴查詢,剩下的都是迭代查詢。 ![](https://hackmd.io/_uploads/BJXPEXIyp.png) > Figure 2.20 DNS 中的多個遞迴查詢 ### DNS Caching 到目前為止我們的討論都無視了 **DNS 快取**這個對 DNS 系統來說至關重要的機制。事實上,DNS 系統非常廣泛地運用了 DNS 快取機制來降低延遲以及減少在網際網路上飛來飛去的 DNS 訊息的數量。DNS 快取的想法非常簡單:在一連串連鎖的請求當中,每當一個 DNS 伺服器收到了一則 DNS 回應(當中可能包含了某個主機名稱對應到的 IP 位址),那他就可以把這個對應表存在自己本地的記憶體當中。舉例:每當 `dns.nyu.edu` 這台本地 DNS 伺服器收到任何回傳的訊息時,他都可以把裡頭的任何訊息快取下來。一旦某個主機名稱 / IP 位址的對應表已經被快取在某台 DNS 伺服器裡了,下一次有人要再來問一樣的主機名稱的 IP 位址時,他就可以直接回答,就算這台伺服器並不真的負責該主機的網域也沒關係。因為世界上有哪些主機,以及每一台主機對應到的 IP 位址為何並不是永久不變的,所以 DNS 伺服器會在固定一段時間之後就把快取下來的紀錄給清除(通常是兩天)。 舉個例子:假設 `apricot.nyu.edu` 這台主機向 `dns.nyu.edu` 這台 DNS 伺服器詢問了 `cnn.com` 的 IP 位址,而在幾個小時過後,另一台也在 NYU 裡面的主機 `kiwi.nyu.edu` 也問了同一台 DNS 伺服器一樣的問題。因為有快取的關係,本地 DNS 伺服器可以直接回傳 `cnn.com` 的 IP 位址回去給第二個詢問的主機,而不需要再詢問任何額外的 DNS 伺服器。本地 DNS 伺服器同樣也可以快取 TLD 伺服器的 IP 位址,從而跳過對根域名伺服器那一次的請求。事實上,由於這個快取機制,幾乎所有的 DNS 請求都可以跳過根域名伺服器,只有一小小部份才需要真的做詢問。 ## 2.4.3 DNS Records and Messages 由 DNS 伺服器們所組合而成的 DNS 分散式資料庫當中,儲存了**資源紀錄 (resource records, RRs)**,包含那些提供了主機名稱與 IP 位址對應表的資源紀錄。每一個 DNS 回應訊息當中,都帶著一到多個資源紀錄。在這裡以及接下來的幾個小節,我們會簡單的介紹 DNS 資源紀錄以及 DNS 訊息。更多的細節可以在 [Albitz 1993] 或是 DNS 的 RFCs [RFC 1034, RFC 1035] 當中找到。 一個資源紀錄是由包含以下四個欄位的四元組 (four-tuple) 所組成的: ``` (Name, Value, Type, TTL) ``` `TTL` 是指該資源紀錄的存活時間,用來決定該比紀錄什麼時候應該要被從快取中移除。在以下的範例當中,我們會忽略 `TTL` 欄位。而 `Name` 和 `Value` 的欄位意義則取決於 `Type` 欄位: * 如果 `Type=A` ,則 `Name` 是主機名稱,而 `Value` 是該主機所對應到的 IP 位址。因此,Type A 的紀錄提供了標準的主機名稱-IP 位址對應功能。例如: `(relay1.bar.foo.com, 145.37.93.126)` 就是一種 Type A 紀錄。 * 如果 `Type=NS` ,則 `Name` 是網域名稱(例如 `foo.com`),而 `Value` 是某個知道怎麼取得該網域底下的主機 IP 位址的另一台權威域名 DNS 的主機名稱。這類紀錄用來在 DNS 的連鎖請求中將 DNS 請求轉發到適當的地方去。例如: `(foo.com, dns.foo.com, NS)` 就是一種 Type NS 紀錄。 * 如果 `Type=CNAME` ,則 `Name` 某個主機的別名,而 `Value` 是這台主機的正規主機名稱。這類紀錄用來給那些使用別名進行查詢的主機提供查詢對象的正規主機名稱。例如: `(foo.com, relay1.bar.foo.com, CNAME)` 就是一種 Type CNAME 紀錄。 * 如果 `Type=MX` ,則 `Name` 某個信件伺服器的別名,而 `Value` 是這台信件伺服器的正規主機名稱。例如: `(foo.com, mail.bar.foo.com, MX)` 就是一種 Type MX 紀錄。MX 紀錄允許信件伺服器的主機名稱可以有簡單的別名。值得注意的是,藉由使用 MX 紀錄,一間公司就可以讓一台信件伺服器跟另外一種類型的伺服器(例如網頁伺服器)同時具有同樣的別名。要取得信件伺服器的正規主機名稱,DNS 客戶端就要請求 MX 紀錄;但如果是要取得其他種類的伺服器的正規主機名稱,那麼 DNS 客戶端得請求 CNAME 紀錄。 (註:資源紀錄的類型並不是只有這四種,詳見 [DNS 紀錄類型列表](https://zh.wikipedia.org/zh-tw/DNS%E8%AE%B0%E5%BD%95%E7%B1%BB%E5%9E%8B%E5%88%97%E8%A1%A8)) 如果一台 DNS 伺服器管轄了某一個特定的主機名稱,那麼該 DNS 伺服器就會擁有一個該主機名稱的 Type A 紀錄。(就算某個 DNS 伺服器並不專門管轄該主機,它也有可能會在快取當中存放該主機的 Type A 紀錄)但如果一台 DNS 伺服器並不負責管轄某主機,那麼他就會擁有一個 Type NS 紀錄,記載著涵蓋該主機的網域名稱,還有一個 Type A 紀錄,用來提供上述 NS 紀錄的 `Value` 欄位中所對應的 DNS 伺服器的 IP 位址。舉個例子:假設有一台 TLD 伺服器並沒有管轄到 `gaia.cs.umass.edu` 這台主機,那麼這台伺服器就會包含一個記載著有涵蓋到 `gaia.cs.umass.edu` 這個主機名稱的網域名稱的 Type NS 紀錄,例如:`(umass.edu, dns,umass,edu, NS)`。這台 edu TLD 伺服器也會同時擁有一個提供 `dns.umass.edu` 的 IP 位址用的 Type A 紀錄,例如:`(dns.umass.edu, 128.119.40.111, A)`。 ### DNS Messages ![](https://hackmd.io/_uploads/HyHaSFllT.png) > Figure 2.21 DNS 訊息格式 在本節的前段,我們有提到 DNS 有詢問訊息和回應訊息,DNS 系統中就只有這兩種訊息而已,而且他們的格式還長得一模一樣,如 Figure 2.21 所示。DNS 訊息中各個欄位的意義如下: * 前 12 個位元組是*標頭區段 (header section)*,裡頭有好幾個欄位: * 第一個欄位是一個 16-bit 的數字,用來辨識該詢問。這個辨識符會被複製到該詢問的回應訊息當中,好讓客戶端可以正確辨別收到的回應是對應到哪一個詢問 * 在旗標欄位 (flags) 中有數個旗標: * 1-bit 的 query/reply 旗標,用來標示該訊息是屬於詢問訊息 (0) 還是回應訊息 (1) * 1-bit 的 authoritative 旗標,當回應的 DNS 伺服器是負責管轄所查詢主機的權威域名伺服器時,這個旗標就會被設定為 1 * 1-bit 的 recursion-desired 旗標,當收到請求的 DNS 伺服器並無持有所查詢的主機紀錄時,如果客戶端(無論是主機或是 DNS 伺服器)希望此時該伺服器執行遞迴查詢,這個旗標就會被設定為 1 * 1-bit 的 recursion-available 旗標,當收到請求的 DNS 主機支援遞迴查詢時,在回應訊息中這個旗標就會被設定為 1 * 還有其他四個欄位,分別用來紀錄標頭底下的四個欄位出現的數量 * *問題區段 (question section)* 包含了跟詢問有關的一些資訊,包含: * 一個 name 欄位,代表所詢問的主機名稱 * 一個 type 欄位,代表現在要查詢的紀錄是哪一種類型的紀錄,例如:是要問某個主機的位址(Type A)還是要問某個主機名稱對應到的信件伺服器 (Type MX) * 在 DNS 主機所發出的回應訊息中,*回答區段 (answer section)* 包含了原本所查詢的名字的資源紀錄。剛剛有提過每一個資源紀錄中都有 `Type`(像是 A, NS, CNAME 和 MX)、`Value`,和 `TTL` 欄位。一個回應訊息中可以同時包含很多個 RR 在回答內,因為一個主機名稱可能會對應到多個 IP 位址(例如在前幾個小節中所提到的副本 Web 伺服器的情況)。 * *權威區段 (Authority section)* 包含了其他權威域名伺服器的紀錄。 * *備註區段 (additional section)* 包含了其他許多有用的紀錄。例如:MX 類型詢問的回應訊息中的回答區段內,會包含一個用來提供某信件伺服器的正規主機名稱的資源紀錄。而在同一個回應的備註區段內,就會包含一個 Type A 紀錄,用來提供該正規名稱的信件伺服器的 IP 位址。 你想不想直接從你的電腦上送出一個 DNS 詢問訊息到某台 DNS 主機上呢?這用 **nslookup 程式** 可以很容易地做到,這個程式在幾乎所有的 Windows 和 UNIX 平台上都有。舉個例子:在 Windows 主機上,打開終端機並簡單地輸入 "nslookup" 就可以執行該程式了。執行 nslookup 後,你就可以送出一個 DNS 詢問到任何的 DNS 伺服器去(包含根域名伺服器、TLD 伺服器或權威域名伺服器)。在收到 DNS 伺服器的回應訊息後,nslookup 會顯示所有包含在該回應當中的資源紀錄(會轉換成人類看得懂的格式)。除了在自己的電腦上執行 nslookup 之外,你也可以在網路上找到許多可以讓你在遠端的電腦上執行 nsloopup 的網站(就在 Google 上搜尋 "nslookup" 就可以了)。在本章最後的 DNS Wireshark lab 會讓你更深入探索 DNS 的更多細節。 ### Inserting Records into the DNS Database 上方的討論都專注在我們是怎麼從 DNS 資料庫當中獲取紀錄的,但你可能會好奇:那這些紀錄一開始到底是怎麼被放進這些資料庫裡的?讓我們透過一個特定的範例來了解 DNS 紀錄是怎麼被存進資料庫的。假設你剛成立了一間新創公司叫作 Network Utopia,你第一個想到的一定就是要先把 `networkutopia.com` 這個網域名稱給註冊下來。而**域名註冊商 (registrar)** 就是一個負責驗證域名的獨一性、把域名輸入進 DNS 資料庫(稍後詳談),以及跟你收一些小費用以維持域名服務的商業實體。在 1999 年之前,就只有一間叫作 Network Solutions 的域名註冊商,它壟斷了包含 `com`, `net`, `org` 等域名的註冊服務。但現在已經多了很多間公司彼此競爭,而這些公司都是由網際網路名稱與數位位址分配機構 (Internet Corporation for Assigned Names and Numbers, ICANN) 所授權的。已被授權的域名註冊商完整名單可以在 http://www.internic.net. 上找到。 當你要向某個域名註冊商註冊 `networkutopia.com` 這個網域名稱時,你同時也需要向該註冊商報備你的主要和次要權威域名伺服器的主機名稱與 IP 位址。假設這兩台 DNS 伺服器的主機名稱和 IP 位址是 `dns1.networkutopia.com` 和 `dns2.networkutopia.com`、`212.212.212.1` <span style="color: #AAA">(課本此處寫 `212.2.212.1`,應是筆誤)</span> 和 `212.212.212.2`。對於這兩台權威域名伺服器,註冊商都會保證他們對應到的 Type NS 和 Type A 紀錄都會被輸入進 `com` 域名的 TLD 伺服器當中。更明確來說,對於管轄 `networkutopia.com` 的主要權威域名伺服器,註冊商會插入以下兩筆紀錄到 DNS 系統中: ``` (networkutopia.com, dns1.networkutopia.com, NS) (dns1.networkutopia.com, 212.212.212.1 A) ``` 你同時也需要確保你的網頁伺服器 `www.networkutopia.com` 的 Type A 資源紀錄以及你的信件伺服器 `mail.networkutopia.com` 的 Type MX 資源紀錄也有被輸入進你的權威域名伺服器裏面。(在不久的以前,每一台 DNS 伺服器的內容物都是靜態設定的,舉例來說,我們可能會使用由系統管理員所創建的設定檔來進行設定。但最近(註:大約 1997 年),UPDATE 選項被加入到了 DNS 協定中,使得 DNS 資料庫中的內容物可以透過 DNS 訊息被動態地新增或刪除。[RFC 2136] 和 [RFC 3007] 當中註明了 DNS 動態更新的細節。) 一旦上述這些步驟通通都完成了,一般大眾就可以開始造訪你的網站,以及寄送 email 給你公司的員工。作為本節介紹 DNS 系統的總結,我們來驗證看看上述說法是否為真,這個驗證過程也會加強我們對 DNS 系統的認識。假設人在澳洲的 Alice 想要拜訪 `www.networkutopia.com` 這個網站。就如同我們上面討論的,他的主機會先送出一個 DNS 詢問到他的本地 DNS 伺服器,而本地 DNS 伺服器會再去詢問 `com` 域名的 TLD 伺服器(如果這個 `com` 域名的 TLD 伺服器的 IP 位址並不在該本地 DNS 伺服器的快取當中,那麼它就也必須先去詢問根域名伺服器才行)。這個 TLD 伺服器會持有上述的 Type NS 和 Type A 資源紀錄,因為域名註冊商已經確保了這些資源紀錄有被輸入進所有 `com` 域名的 TLD 伺服器當中。`com` 域名的 TLD 伺服器接著會把回應回傳給 Alice 的本地 DNS 伺服器,回應當中就會包含上述兩個資源紀錄。本地 DNS 伺服器再接著送出一個 DNS 請求到 `212.212.212.1` 這台主機,去向他請求 `www.networkutopia.com` 的 Type A 紀錄。這個紀錄就會提供上述網址所指向的主機的 IP 位址,例如 `212.212.71.4`,而本地 DNS 伺服器就會把這個 IP 位址回傳給 Alice 的主機。此時 Alice 的網頁瀏覽器就可以建立一個通往 `212.212.71.4` 的 TCP 連線,並透過該連線傳送 HTTP 請求到該網頁伺服器了。累死人了!在我們上網時,在眼睛看得到的東西之外,底下還有好多複雜的事情正在運作呢! :::info :memo: **DNS Vulnerabilities** 現在我們已經知道 DNS 是網際網路基礎建設中的一個至關重要的元件,沒有了它,有許多的服務(包含網頁服務和電子郵件服務)就完全無法運作了。於是我們很自然的就會想到一個問題:DNS 系統如果被攻擊了怎麼辦?難道 DNS 系統就要坐以待斃,等著被打到停止服務並且拖一卡車的網際網路應用程式一起下水嗎? 最容易想到的第一種攻擊方式就是針對 DNS 伺服器的 DDoS 洪水流量攻擊(參見 [1.6](https://hackmd.io/@kaeteyaruyo/computer-networking-1-6) 節)。舉例來說:攻擊者會試著對每一個根域名伺服器送出海量的封包,數量多到大部份合法的 DNS 詢問都無法正常收到回應。如此大規模的針對根域名伺服器的 DDoS 攻擊確實在 2002 的 10 月 21 日發生過。在該次攻擊中,攻擊者利用了僵屍網路 (botnet) 送出了非常大量的 ICMP ping 訊息到所有 13 台的根域名伺服器的 IP 位址去(關於 ICMP 訊息我們會在 5.6 節談到,當前你只需要知道 ICMP 封包就是一種特別的 IP 資料塊就可以了)。幸好,該次的大規模攻擊只有造成很小的損害,幾乎沒有影響到一般使用者上網的體驗。攻擊者是成功把海量的 ICMP 封包導向到了根域名伺服器沒錯,但是許多的根域名伺服器都被封包過濾器給保護的好好的,這些過濾器都被設定成會把直接往根域名伺服器送來的 ICMP ping 訊息給封鎖掉。這些根域名伺服器因此倖免於難,並且得以繼續正常運作。更好的是,大部分的本地 DNS 伺服器都有把多數 TLD 伺服器的 IP 位址給快取下來,所以大部份的詢問也根本不會跑到根域名伺服器那裡去。 潛在來說,針對 DNS 系統更有效的 DDoS 攻擊應該是要把海量的 DNS 請求送到 TLD 伺服器去,例如:攻擊所有負責 `com` 域名的 TLD 伺服器。要把送往 DNS 伺服器的 DNS 詢問給過濾掉是比較困難的,而且 TLD 伺服器也不像根域名伺服器那麼容易跳過不問。但這類攻擊的影響有一部份可以利用本地 DNS 伺服器的快取機制來緩解。 DNS 系統也有可能被其他類型的攻擊給影響。在中間人攻擊當中,攻擊者會攔截從主機送出的訊問並回傳有害的回應給詢問的主機;在 DNS 毒化攻擊當中,攻擊者會送出有害的回應給 DNS 伺服器,騙該伺服器把有害的紀錄存到快取當中。這兩種方法都可以用來誘騙一個毫無戒心的網頁使用者,把他從原本想去的網站導去攻擊者的有害網站。但這兩種攻擊是很難實作的,因為這需要攻擊者有辦法攔截封包或是挾持一台伺服器 [Skoudis 2006]。 總結來說,DNS 已經證實了自己面對攻擊時是相當可靠的 (robust)。至今還沒有任何一場攻擊有成功阻斷過 DNS 的服務。 ::: ---- [<< 2.3 Electronic Mail in the Internet](https://hackmd.io/@kaeteyaruyo/computer-networking-2-3) | [目錄](https://hackmd.io/@kaeteyaruyo/computer-networking-index) | [2.5 Peer-to-Peer File Distribution >>](https://hackmd.io/@kaeteyaruyo/computer-networking-2-5)