
1. DNS 是什么?
DNS (Domain Name System 的縮寫)的作用非常簡單,就是根據域名查出IP地址。你可以把它想象成一本巨大的電話本。
舉例來說,如果你要訪問域名math.stackexchange.com,首先要通過DNS查出它的IP地址是151.101.129.69。
2. 域名的層級
由於后面我會講到 DNS 的解析過程,因此需要你對域名的層級有一些了解
- 根域名 :
.root或者.,通常是省略的 - 頂級域名,如
.com,.cn等 - 次級域名,如
baidu.com里的baidu,這個用戶是可以注冊購買的 - 主機域名,比如
baike.baidu.com里的baike,這個用戶是可分配的
主機名.次級域名.頂級域名.根域名
baike.baidu.com.root
3. DNS 解析過程
咱們以訪問 www.163.com 這個域名為例,來看一看當你訪問 www.163.com 時,會發生哪些事:
- 先查找本地 DNS 緩存(自己的電腦上),有則返回,沒有則進入下一步
- 查看本地 hosts 文件有沒有相應的映射記錄,有則返回,沒有則進入下一步
- 向本地 DNS 服務器(一般都是你的網絡接入服務器商提供,比如中國電信,中國移動)發送請求進行查詢,本地DNS服務器收到請求后,會先查下自己的緩存記錄,如果查到了直接返回就結束了,如果沒有查到,本地DNS服務器就會向DNS的根域名服務器發起查詢請求:請問老大,
www.163.com的ip是啥? - 根域名服務器收到請求后,看到這是個
.com的域名,就回信說:這個域名是由.com老弟管理的,你去問他好了,這是.com老弟的聯系方式(ip1)。 - 本地 DNS 服務器接收到回信后,照着老大哥給的聯系方式(ip1),馬上給
.com這個頂級域名服務器發起請求:請問.com大大,www.163.com的ip 是啥? .com頂級域名服務器接收到請求后,看到這是163.com的域名,就回信說:這個域名是.163.com老弟管理的,你就去問他就行了,這是他的聯系方式(ip2)- 本地 DNS 服務器接收到回信后,按照前輩的指引(ip2),又向
.163.com這個權威域名服務器發起請求:請問163.com大大,請問www.163.com的ip是啥? 163.com權威域名服務器接收到請求后,確認了是自己管理的域名,馬上查了下自己的小本本,把www.163.com的ip告訴了 本地DNS服務器。- 本地DNS服務器接收到回信后,非常地開心,這下總算拿到了
www.163.com的ip了,馬上把這個消息告訴了要求查詢的客戶(就是你的電腦)。由於這個過程比較漫長,本地DNS服務器為了節省時間,也為了盡量不去打擾各位老大哥,就把這個查詢結果偷偷地記在了自己的小本本上,方便下次有人來查詢時,可以快速回應。
總結起來就是三句話
- 從"根域名服務器"查到"頂級域名服務器"的NS記錄和A記錄(IP地址)
- 從"頂級域名服務器"查到"次級域名服務器"的NS記錄和A記錄(IP地址)
- 從"次級域名服務器"查出"主機名"的IP地址

4. DNS的緩存時間
上面的幾個步驟里,可以看到有兩個地方會緩存 DNS 的查詢記錄,有了緩存,在一定程度上會提高查詢效率,但同時在准確率上會有所損失。
因此我們在配置 DNS 解析的時候,會有一個 TTL 參數(Time To Live),意思就是這個緩存可以存活多長時間,過了這個時間,本地 DNS 就會刪除這條記錄,刪除了緩存后,你再訪問,就要重新走一遍上面的流程,獲取最新的地址。

5. DNS 的記錄類型
當我們在阿里雲買了一個域名后,可以配置我們主機域名解析規則,也就是 記錄。

常見的 DNS 記錄類型如下
-
A:地址記錄(Address),返回域名指向的IP地址。 -
NS:域名服務器記錄(Name Server),返回保存下一級域名信息的服務器地址。該記錄只能設置為域名,不能設置為IP地址。 -
MX:郵件記錄(Mail eXchange),返回接收電子郵件的服務器地址。 -
CNAME:規范名稱記錄(Canonical Name),返回另一個域名,即當前查詢的域名是另一個域名的跳轉,詳見下文。 -
PTR:逆向查詢記錄(Pointer Record),只用於從IP地址查詢域名,詳見下文。
6. DNS 報文結構
后面我將使用 wireshark 抓取 DNS 的數據包,但是在開始之前 ,得先了解一下 DNS 的報文結構

- 事務 ID:DNS 報文的 ID 標識。對於請求報文和其對應的應答報文,該字段的值是相同的。通過它可以區分 DNS 應答報文是對哪個請求進行響應的。
- 標志:DNS 報文中的標志字段。
- 問題計數:DNS 查詢請求的數目。
- 回答資源記錄數:DNS 響應的數目。
- 權威名稱服務器計數:權威名稱服務器的數目。
- 附加資源記錄數:額外的記錄數目(權威名稱服務器對應 IP 地址的數目)。
7. Wireshark抓包實戰
打開 Wireshark 后,使用 ping 163.com 來發起 DNS 解析請求,使用 DNS 關鍵字在Wireshark 過濾。
從抓取的報文整體來看,我們可以粗略獲取幾個信息
- DNS 是應用層協議,傳輸層協議使用的是 UDP
- DNS 默認端口是 53

請求和應答的報文的截圖我放在了下面,接下來我將逐個分析。
請求

應答

Transaction ID
請求和應答的事務ID應當是一個:0xd0d7
Flags
標志字段里的內容比較多,每個字段的含義如下
- QR(Response):查詢請求/響應的標志信息。查詢請求時,值為 0;響應時,值為 1。
- Opcode:操作碼。其中,0 表示標准查詢;1 表示反向查詢;2 表示服務器狀態請求。
- AA(Authoritative):授權應答,該字段在響應報文中有效。值為 1 時,表示名稱服務器是權威服務器;值為 0 時,表示不是權威服務器。
- TC(Truncated):表示是否被截斷。值為 1 時,表示響應已超過 512 字節並已被截斷,只返回前 512 個字節。
- RD(Recursion Desired):期望遞歸。該字段能在一個查詢中設置,並在響應中返回。該標志告訴名稱服務器必須處理這個查詢,這種方式被稱為一個遞歸查詢。如果該位為 0,且被請求的名稱服務器沒有一個授權回答,它將返回一個能解答該查詢的其他名稱服務器列表。這種方式被稱為迭代查詢。
- RA(Recursion Available):可用遞歸。該字段只出現在響應報文中。當值為 1 時,表示服務器支持遞歸查詢。
- Z:保留字段,在所有的請求和應答報文中,它的值必須為 0。
- rcode(Reply code):返回碼字段,表示響應的差錯狀態。當值為 0 時,表示沒有錯誤;當值為 1 時,表示報文格式錯誤(Format error),服務器不能理解請求的報文;當值為 2 時,表示域名服務器失敗(Server failure),因為服務器的原因導致沒辦法處理這個請求;當值為 3 時,表示名字錯誤(Name Error),只有對授權域名解析服務器有意義,指出解析的域名不存在;當值為 4 時,表示查詢類型不支持(Not Implemented),即域名服務器不支持查詢類型;當值為 5 時,表示拒絕(Refused),一般是服務器由於設置的策略拒絕給出應答,如服務器不希望對某些請求者給出應答。
Answer RRs
回答資源記錄數,在應答包里為 2,說明返回了兩條查詢結果,你可以在 Answer 字段里看到。
Authority RRs
權威名稱服務器計數
Additionnal RRs
附加資源記錄數
Answers
應答的主要內容,這里返回兩條結果,每條結果里的字段有
Name: 查詢的域名
Type: A表示IPv4,AAAA 表示IPv6
Class: 表示Internet,幾乎總是它
Time to live: 生存時間
Data length: 數據長度
Address: 查詢到的 IP 地址
8. DNS 劫持 與 HTTP 劫持
通過上面的講解,我們都知道了,DNS 完成了一次域名到 IP 的映射查詢,當你在訪問 www.baidu.com 時,能正確返回給你 百度首頁的 ip。
但如果此時 DNS 解析出現了一些問題,當你想要訪問 www.baidu.com 時,卻返回給你 www.google.com 的ip,這就是我們常說的 DNS 劫持。
與之容易混淆的有 HTTP 劫持。
那什么是 HTTP 劫持呢?
你一定見過當你在訪問 某個網站時,右下角也突然彈出了一個扎眼的廣告彈窗。這就是 HTTP 劫持。
借助別人文章里的例子,它們倆的區別就好比是
-
DNS劫持是你想去機場的時候,把你給丟到火車站。
-
HTTP劫持是你去機場途中,有人給你塞小廣告。
那么 DNS劫持 是如何產生的呢?
下面大概說幾種DNS劫持方法:
1.本機DNS劫持
攻擊者通過某些手段使用戶的計算機感染上木馬病毒,或者惡意軟件之后,惡意修改本地DNS配置,比如修改本地hosts文件,緩存等
2. 路由DNS劫持
很多用戶默認路由器的默認密碼,攻擊者可以侵入到路由管理員賬號中,修改路由器的默認配置
3.攻擊DNS服務器
直接攻擊DNS服務器,例如對DNS服務器進行DDOS攻擊,可以是DNS服務器宕機,出現異常請求,還可以利用某些手段感染dns服務器的緩存,使給用戶返回來的是惡意的ip地址
9. 工具的使用
dig 命令
dig是一個在類Unix命令行模式下查詢DNS包括NS記錄,A記錄,MX記錄等相關信息的工具。
通過 dig (參數:+trace)命令,我們可以看到上面描述的 DNS 解析的詳細過程

從返回的結果,我們可以看得出幾點信息
- 我們的本地 DNS 服務器 ip 為 192.168.1.1,端口為53,你可以在 /etc/resolv.conf 里看到這個配置
- 根域名服務器目前全球一共只有十三台,從a.root-servers.net.
到m.root-servers.net. ,它們對應的ip地址,已經內置在本地DNS服務器中。
如果你只想看到結果,可以使用 +short 參數,可以直接返回 www.163.com 對應着哪幾個ip

你也可以加個 @ 參數 ,指定從某個 DNS 服務器進行查詢

如果你只想查看指定的記錄類型

host 命令
host 命令 可以看作dig命令的簡化版本,返回當前請求域名的各種記錄。

whois命令
whois命令用來查看域名的注冊情況。

nslookup命令
nslookup也是常用的一個查詢 DNS 解析結果的工具
$ nslookup [查詢的域名] [指定DNS服務器]

你也可以指定公網的域名服務器進行查詢,比如常見的 114.114.114.114

10. 手動清理本地緩存
MacOS
$ sudo dscacheutil -flushcache
$ sudo killall -HUP mDNSResponder
Windows
$ ipconfig /flushdns
Linux
# 使用NSCD的DNS緩存
$ sudo /etc/init.d/nscd restart
# 服務器或者路由器使用DNSMASQ
$ sudo dnsmasq restart

