關於DNS,你應該知道這些

有價值炮灰發表於2017-01-08

在網際網路時代中,如果要問哪個應用層協議最重要的話,我想答案無疑是DNS.雖然我們每天都享受著DNS服務帶來的便利,
卻對它往往知之甚少.因此本文就來介紹一下DNS協議的工作流程,真正認識一下這個支撐著龐大網際網路絡的基礎服務.

前言

DNS協議,全稱為Domain Name System,即域名服務, 其功能描述起來很簡單,就是將域名(網址)轉換為IP地址.
可以想象為一個儲存了全世界域名到IP的對映的伺服器, 通過DNS請求查詢獲得IP地址. 然而事實上域名的
數量繁多,如果全部存放在一臺伺服器之上顯然不合適. 因此對不同層級的域名往往需要在不同的域名伺服器上查詢,
直至找到最終的IP地址或者下一層級的域名伺服器,是一個多次查詢的過程.

域名的分級

我們日常上網所輸入的網址,格式例子為http://www.pppan.net,其中www.pppan.net就可以看作是域名.
實際上,域名是從右到左分級的,格式如下所示:

主機名.次級域名.頂級域名.根域名
即:
host.sld.tld.root

www.pppan.net為例,其完整的域名應該是‵www.pppan.net.root‵,由於全球的根域名都是root,因此根域名
部分常常忽略,因此可以寫成www.pppan.net.(注意最後的點),

根域名

根域名通過根伺服器進行解析, 根伺服器對於每個請求告知頂級域名伺服器的地址. 目前全世界一共有十三臺根伺服器,
由於不同國家或機構管理維護,分別坐落在如下的地方:

root-servers

可以看到其中沒有一臺是在中國境內的,不知道這是好事還是壞事呢? 呵呵.

頂級域名

頂級域名, 英文名為TLD(Top-Level Domains). 根據用途不同被分為兩部分. 一部分稱為通用頂級域名gTLD(generic TLD),
.com, .net, .org, .biz, .info等都是常見的通用頂級域名; 另一部分稱為國別頂級域名ccTLD(country side TLD),
ccTLD對應的國家擁有對應域名進行任何限制的權力,有的國家只允許本國公民註冊ccTLD域名,不過其他國家的機構可以通過"租"
的方式來獲得對應國家的ccTLD域名, 常見的ccTLD型別域名有.cn, .us, .ru等,還有些國家國別頂級域名因為有特殊的含義
而被批量租用的,如.tv, .ws, .tk等.

次級域名

次級域名, 英文名為SLD(Sub-Level Domains), 通常又被稱為二級域名. 這一級別的域名是使用者可以向域名代理商進行註冊的,
我們通常說的購買域名,就是買的次級域名.

主機名

主機名(hostname), 為使用者在自己的域中為伺服器所分配的不同的名稱. 常見的www就是一個主機名.

域名查詢

當我們知道一個用名稱表示的資源時,為了訪問這個資源,我們就需要知道其地址, 這個地址通常也稱為記錄(records).
這個根據資源名稱(域名)來查詢地址的過程, 就稱為DNS, DNS查詢通常會經過下面四步:

  • 詢問Resolver
  • 詢問根伺服器
  • 詢問頂級域名伺服器
  • 詢問次級域名伺服器

Resolver

resolver就是我們常說的DNS伺服器, 其作用是為我們提供域名伺服器的地址. resolver的地址一般在我們接入網路的時候,
通過DHCP獲得, 也可以手動指定resolver地址. 在Linux系統中可以檢視/etc/resolv.conf檔案檢視resolver地址,
Windows則可以通過控制皮膚檢視.

resolver通常有個root-hints檔案, 其中硬編碼了十三個根域名伺服器的地址. 當我們向resolver發起DNS請求時,
resolver會同時向所有根域名伺服器發出查詢請求,並以最快返回的響應為結果執行下一步的操作. 實際上,
resolver會根據響應速度獲得一個優先查詢的根伺服器,並將隨後的查詢都只向此根伺服器進行請求. 當然,
優先伺服器也有自己的更新機制,不過這是題外話了.

resolver獲得根伺服器的地址之後,通常還需要進行下一步的查詢. 如果我們要查詢的域名為www.example.com,
則還需要向根伺服器查詢com的頂級域名伺服器,然後再查詢次級域名伺服器和主機名等.

詢問根伺服器

上面也說了,全球一共是三個根域名伺服器,其中每一個都知道可以處理此次DNS請求的次級域名伺服器的地址,
或者至少知道可以處理請求的下級的域名伺服器地址.

一般來說,根伺服器處理DNS請求,並且告訴resolver下一步應該去詢問哪個頂級伺服器. 不過如果根伺服器識別出了
次級伺服器的地址,就會把這個地址返回給resolver的.

詢問頂級域名伺服器

如果上一步根伺服器沒有識別出次級域名伺服器的地址,那麼就會給resolver返回頂級伺服器的地址,從而resolver
需要再次向頂級域名伺服器發起查詢.

頂級域名伺服器收到查詢請求後,會將可以真正解析此請求的次級域名伺服器地址返回給resolver.

詢問次級域名伺服器

上一步resolver請求頂級域名伺服器後,會收到返回,內容是下一步要查詢的域名伺服器的地址,
也就是次級域名伺服器的地址. 於是resolver向次級域名伺服器發起DNS查詢請求, 次級域名
伺服器接收到請求後即返回對應次級域名的IP地址.

值得一提的是,次級域名還有如下的別名:

  • 使用者DNS名稱伺服器(User DNS name server)
  • 權威名稱伺服器(Authoritative name server)

其中後者更廣為人知一些,因為SLD是查詢到對應域名IP地址的最後一步(如果有的話), 而且這個域名伺服器也負責
對應資源的DNS設定,如新增不同主機地址的記錄等.

resolver從次級域名伺服器獲得了域名的IP地址,並將其返回給使用者,只此便完成了一次DNS查詢.

域名查詢例項

紙上得來終覺淺,絕知此事要躬行. 上面介紹了域名查詢的一般流程之後, 我們就可以通過一次真實的DNS查詢來
驗證上述的過程. 在Linux環境下,有預設的dig命令可以進行DNS的查詢和除錯, 這裡以域名test.pppan.net為例.
輸入命令dig +trace test.pppan.net可以看到詳細的查詢過程.

Step 1

首先, 向使用者的DNS伺服器(resolver,這裡是10.0.20.166)查詢根域名伺服器的地址(std query A a-m.root-servers.net),
其中A表示查詢ipv4地址記錄,AAAA表示查詢ipv6地址, 在下一節詳細介紹. 返回結果如下:

.           318381  IN  NS  j.root-servers.net.
.           318381  IN  NS  k.root-servers.net.
.           318381  IN  NS  l.root-servers.net.
.           318381  IN  NS  m.root-servers.net.
.           318381  IN  NS  a.root-servers.net.
.           318381  IN  NS  b.root-servers.net.
.           318381  IN  NS  c.root-servers.net.
.           318381  IN  NS  d.root-servers.net.
.           318381  IN  NS  e.root-servers.net.
.           318381  IN  NS  f.root-servers.net.
.           318381  IN  NS  g.root-servers.net.
.           318381  IN  NS  h.root-servers.net.
.           318381  IN  NS  i.root-servers.net.
;; Received 811 bytes from 10.0.20.166#53(10.0.20.166) in 247 ms

可以看到,一共有13個根域名伺服器,地址分別是a-m.root-servers.net., 其中響應最快的根域名伺服器是
j.root-servers.net.

Step 2

然後, 向j-root-servers.net(192.58.128.30)發起查詢請求(standard query A test.pppan.net),
得到的返回如下:

net.            172800  IN  NS  a.gtld-servers.net.
net.            172800  IN  NS  b.gtld-servers.net.
net.            172800  IN  NS  c.gtld-servers.net.
net.            172800  IN  NS  d.gtld-servers.net.
net.            172800  IN  NS  e.gtld-servers.net.
net.            172800  IN  NS  f.gtld-servers.net.
net.            172800  IN  NS  g.gtld-servers.net.
net.            172800  IN  NS  h.gtld-servers.net.
net.            172800  IN  NS  i.gtld-servers.net.
net.            172800  IN  NS  j.gtld-servers.net.
net.            172800  IN  NS  k.gtld-servers.net.
net.            172800  IN  NS  l.gtld-servers.net.
net.            172800  IN  NS  m.gtld-servers.net.
net.            86400   IN  DS  35886 8 2 7862B27F5F516EBE19680444D4CE5E762981931842C465F00236401D 8BD973EE
net.            86400   IN  RRSIG   DS 8 1 86400 20170121050000 20170108040000 61045 . Y6+Td6BUfPw5RgC2aWX/pvC6OgEl8rVd3SCPtg+/qdwHxRa4TM8ppZWU +nTSRNTwgXX1VWxJ8D7MNu4q8gLZZWxO1U+3Viw8WNSRdIou+s2fVwon IQVF9y0GGpLaKt8mwlOaeHO3O1HiGGpR50GTlNhxyx6eGYHu5581ugFm NTjogYmrcTy5Es70WH6NhQ1z7+rO8rcuo5ES7fJoZWr4Bekd7YntSxXx +WCwOcpf3muLGPC9yshNprA/c9Fam3WDpJLYPjmCp2l96GyrJcv4o9z9 gov5IV69HWQnCD9IGRIj/XG/JZerp6YIRGH8cnrVe3F87Hy95SkNWnYR lC5fIg==
;; Received 863 bytes from 192.58.128.30#53(j.root-servers.net) in 524 ms

並沒有返回IP,而是返回了可以解析該域名的頂級域名地址, 由於是.net因此屬於gTLD,
可以看到返回了多個頂級域名伺服器(a-m.gtld-servers.net.)的地址.

Step 3

接著, 我們應該向返回的地址再次發起查詢(standard query A test.pppan.net),
這次返回了次級域名伺服器的地址,如下:

pppan.net.      172800  IN  NS  ns01.freenom.com.
pppan.net.      172800  IN  NS  ns02.freenom.com.
pppan.net.      172800  IN  NS  ns03.freenom.com.
pppan.net.      172800  IN  NS  ns04.freenom.com.
A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20170113060849 20170106045849 43880 net. WTfL5/hHBUsV2D5vusIP5KNSoiyfG4sG0GZQuBUqppWEY/WgZJ2wnnpk jjjfN5BlIExTuDyHclY2bXbiIqebcd1aVGp1ELUI7E5t3z7iCZmajPsT TLuLohKJmLC7b/OVdxoAuFoaIqj+GDsp2yDkXsem1IrfSOCbQlvJE9Ya xbQ=
OKR8BNVHVTI8CTK5KIDNJN546MJM5M16.net. 86400 IN NSEC3 1 1 0 - OKSF929IG7A7E1KLTJD5CF495DR06C54 NS DS RRSIG
OKR8BNVHVTI8CTK5KIDNJN546MJM5M16.net. 86400 IN RRSIG NSEC3 8 2 86400 20170113060546 20170106045546 43880 net. BGw3/vY9GzViJNHllwJkC1WB5XBtV9jzjy3LSA9I0zovOpVFHivHE01S r3YUtqAUuJ0LOJ4wrxBPwDRB0wTgbQdIO7dol2nQWuYujbxEbJ6AOWtR 7MTRhiG8BDn9LP06UWpUcWlsyywivKR70xCnamq3ZKeeI48dluRkVy9f lig=
;; Received 679 bytes from 192.33.14.30#53(b.gtld-servers.net) in 1813 ms

這一步返回可以看到, pppan.net所屬的次級域名伺服器是ns01-ns04.freenom.com, 因為我配置的就是這個地址.
但實際上可以自己在公網搭建這樣一個次級域名伺服器,只要可以解析出對應的hostname即可.

Step 4

最後,向ns01.freenom.com發起查詢,便可以從響應中看到,已經找到了test.pppan.net的一條地址記錄:

test.pppan.net.     14440   IN  A   233.233.233.233
;; Received 59 bytes from 54.171.131.39#53(ns01.freenom.com) in 464 ms

因此便能得到本次DNS查詢的結果, 即test.pppan.net的ip地址為233.233.233.233.

注: 對於使用者而言,其實只進行一次DNS查詢,即向resolver的查詢,中間的過程由resolver進行按級查詢,
並將最後查詢到的結果返回給使用者(如果有的話). 上面的查詢由dig命令發起,因此和實際的查詢過程還是有點小差別的.

記錄型別

從上面的示例中我們可以看到, 我們查詢的記錄型別為A或者AAAA, 返回的結果型別有NS,DS或者A等.
這些記錄的型別在DNS協議中都有詳細介紹,這裡只解釋幾個常見的型別:

A

A記錄(Address Mapping records), 指示了對應名稱的IPv4地址, A記錄用來將域名轉換為ip地址.

AAAA

AAAA記錄類似於A記錄, 只不過指示的是IPv6的地址.

NS

NS記錄(Name Server records), 用來指定對應名稱的可信名稱伺服器(authoritative name server).

PTR

PTR記錄(Reverse-lookup Pointer records), 和正向DNS解析(A/AAAA記錄)相反, 主要用來根據IP地址查詢對應的域名.

CNAME

CNAME記錄即Canonical Name records, 用來指定一個新的域名用以完成本次查詢.
當resolver查詢過程中遇到一個CNAME記錄時, 則會重新開始本次查詢, 但是查詢的域名會改為CNAME指定的域名.
舉例來說,假如某次級域名伺服器上有如下記錄:

NAME                    TYPE   VALUE
--------------------------------------------------
bar.example.com.        CNAME  foo.example.com.
foo.example.com.        A      192.0.2.23

則查詢bar.example.com的時候, 會在resolver端轉而查詢foo.example.com,從而得到查詢的地址為192.0.2.23,
可以看到其實CNAME就是一個別名, 但是增加了查詢的步驟. 不過這在當我們想要把自己的某個域名當作某個外部
域名的別稱時還是很有用的. CNAME也有使用限制, 比如記錄值不可以是IP, 以及不可同時有其他同名的A記錄等,
具體可以參考這裡.

MX

MX記錄(Mail Exchanger records)為某個DNS域名指定了郵件交換的伺服器. 這個記錄資訊由SMTP協議使用來將
郵件傳送到正確的主機上. 通常對於一個域名有多個郵件交換伺服器,並且他們之間都有對應的優先順序.

TXT

TXT記錄(text records)可以包含任意非格式化的文字資訊, 通常這項記錄被SPF框架(Sender Policy Framework)
用來防止傳送給你的虛假郵件.

當然還有許多其他的記錄型別, 不過相對而言沒有那麼常見. 需要了解的可以再深入查閱DNS協議的白皮書即可.

後記

經過上面對於DNS服務的解釋, 我們應該就能解決大部分日常遇到的DNS問題. 比如為什麼電腦能上QQ卻打不開網頁啦,
為什麼我的網站突然解析不出來啦; 或者有獨立域名的還能實現一些好玩的功能, 比如建立惡作劇的查詢記錄,或者
搭建個人郵件伺服器等. 畢竟DNS協議是我們日常直接或者間接所接觸到的最多的協議, 花上幾個小時瞭解一下它的
工作機制,我想應該也是挺有趣的吧.

參考文章

部落格地址:

歡迎交流,文章轉載請註明出處.

相關文章