2.1 DNS 原理:遞迴查詢、TTL 與全球分散式資料庫#
本節目標#
- 理解 DNS 誕生的歷史動機:為什麼 1983 年的網際網路需要放棄單一 hosts.txt
- 掌握 DNS 的樹狀命名空間與委派(delegation)模型
- 能完整推演一次「遞迴 vs 迭代」查詢的封包流程
- 認識 TTL 的語意、常用記錄型別,以及 DNSSEC 為何存在
歷史:從 hosts.txt 到分散式資料庫#
在 DNS 出現之前,整個 ARPANET 的主機名稱對照表只有一份:史丹福研究院(SRI-NIC)維護的 HOSTS.TXT 檔案。每台主機定期從 SRI 下載整份檔案。1980 年代初,這個設計瀕臨崩潰:
| 問題 | 說明 |
|---|---|
| 單點故障 | SRI-NIC 當機,全網名稱解析失效 |
| 流量瓶頸 | 所有主機輪番下載,SRI 頻寬吃緊 |
| 一致性延遲 | 修改要等全網同步,可能有數天落差 |
| 命名衝突 | 沒有層級機制,名稱是全域扁平的 |
Paul Mockapetris 在 1983 年發表 RFC 882/883(後被 RFC 1034/1035 取代),提出 DNS:一個階層式、分散式、可快取的資料庫。它不是靠「一份大表」,而是靠「每個區域的管理者只負責自己那一層」。這個設計放到四十年後的今天依然成立——Cloudflare 的權威 DNS 服務,本質上就是當年設計的商業化實現。
樹狀命名空間#
DNS 名稱空間是一棵以空標籤(root)為根的樹:
(root, ".")
/ | \
com org tw ...
/ \ /
google cloudflare edu
| \
blog.example.com ntu
blog.example.com. 這個完整的 FQDN(Fully Qualified Domain Name)由右至左逐層變寬:
| 層級 | 節點 | 誰管理 |
|---|---|---|
| 根 | . | IANA / 根伺服器營運組織(13 個字母身份,數千台 anycast 節點) |
| TLD | com / tw | Verisign、TWNIC 等註冊管理機構 |
| 網域 | example.com | 你(透過 Registrar 註冊取得) |
| 子網域 | blog | 你自由定義,想幾層就幾層 |
關鍵洞察:每一層不是「知道全部答案」,而是「知道往哪裡問」。根不知道 blog.example.com 的 IP,但知道 .com 的伺服器在哪;.com 的伺服器知道 example.com 的權威 DNS 在哪——這就是委派(delegation)。
遞迴 vs 迭代:一次查詢的完整旅程#
DNS 查詢有兩種角色:
- 遞迴查詢(Recursive):客戶端把責任整包丟給 resolver(如 8.8.8.8、Cloudflare 1.1.1.1),resolver 必須「問到底」。
- 迭代查詢(Iterative):resolver 對每層權威伺服器只問一次,對方回「下一個該問誰」。
Resolver 內部其實是「接收遞迴、發出迭代」:
[瀏覽器] [本機 resolver / ISP] [權威 DNS 伺服器群]
| | |
| 1.遞迴查詢 | |
| blog.example.com | |
|------------------->| |
| | 2.問根: blog.example.com? |
| |-------------------------> (root)
| | 回答: 去問 .com (NS) |
| |<-------------------------|
| | 3.問 .com 權威 |
| |-------------------------> (gtld)
| | 回答: 去問 ns.example.com|
| |<-------------------------|
| | 4.問 example.com 權威 |
| |-------------------------> (權威)
| | 回答: A 203.0.113.7 |
| 5.回傳 IP + 快取 |<-------------------------|
|<-------------------| |
| 6.用 IP 建立 TCP 連線 |
步驟 5 之後,resolver 會把答案快取起來——這就是 DNS 能撐住全網流量的秘密:絕大多數查詢根本到不了權威伺服器。
TTL:快取的租約期限#
每筆 DNS 記錄都附帶 TTL(Time To Live),語意是「這個答案你最多可以信任 N 秒」:
| TTL 設定 | 效果 | 適合情境 |
|---|---|---|
| 300 秒(5 分鐘) | 變更快速生效,查詢負載高 | 遷移 IP 期間、DDNS |
| 3600 秒(1 小時) | 一般網站的平衡點 | 常態營運 |
| 86400 秒(1 天) | 權威負載最低,但改錯要等一天 | 超穩定的 IP |
工程上重要的一課:TTL 是租約,不是指令。把 TTL 從 86400 改成 300 後,舊 TTL 仍會在快取裡停留最多 24 小時——所以任何 IP 遷移都要「先降 TTL、等一個舊 TTL 週期、再改 IP」。Cloudflare 代理(橘雲)開啟時,對外 TTL 固定為 300 秒且由 Cloudflare 控管,這是我們選 Cloudflare 託管 DNS 的便利之一。
常用記錄型別#
| 型別 | 語意 | 範例 |
|---|---|---|
A | 名稱 → IPv4 位址 | example.com → 203.0.113.7 |
AAAA | 名稱 → IPv6 位址 | example.com → 2001:db8::7 |
CNAME | 別名,指向另一個名稱(解析時再追查) | www.example.com → example.com |
TXT | 自由文字,用於 SPF 驗證、憑證簽發證明等 | "v=spf1 include:_spf.google.com ~all" |
NS | 指定該區域的權威 DNS 伺服器(委派的錨點) | example.com. NS ns1.cloudflare.com. |
MX | 收該網域信件的郵件伺服器優先序 | 10 mail.example.com. |
兩個容易踩的規則:
- CNAME 不能與其他記錄共存:
example.com若被 CNAME 指走,就不能再有 MX。這也是為什麼根網域(apex)通常用 A/AAAA 而不是 CNAME——DNS RFC 的歷史限制。Cloudflare 的 CNAME Flattening 技術在回應時把 CNAME 攤平成 A 記錄,繞過了這個限制。 - 查 CNAME 是一次新的解析流程:alias 不是答案,是「下一個問題」。
用 dig 實際觀察#
$ dig +noall +answer +authority blog.example.com
blog.example.com. 300 IN A 203.0.113.7
example.com. 3600 IN NS ns1.cloudflare.com.
# ^ TTL ^ IN 是 class "Internet" ^ 答案
300 就是快取租約——你自己架伺服器時看到的所有 DNS 行為,都可以用 dig 驗證,不用猜。
DNSSEC:替 DNS 加上簽章#
DNS 誕生時沒有任何認證機制:任何攔截到查詢的人都可以回一個假 IP(DNS cache poisoning / 劫持)。DNSSEC(RFC 4033-4035)的解法是公鑰簽章鏈:根的 KSK 簽 .com 的 key,.com 簽 example.com 的 key,層層簽下去,resolver 用 DS 記錄逐級驗簽。它不加密內容,只保證「記錄沒被竄改」。
Cloudflare 在 DNS 面板可一鍵啟用 DNSSEC,再把產生的 DS 記錄提交給你的 Registrar 即完成鏈結——這一步在 2.2 節會實作。
小結與練習#
本章建立的心智模型:DNS 是層層委派 + 結果快取(TTL 租約)的全球分散式資料庫;遞迴與迭代只是責任劃分的角色差異;TTL 決定變更生效速度;記錄型別決定「名稱指向什麼」。
練習:
- 在本機用
dig +trace www.wikipedia.org觀察逐級委派過程,數一數總共向幾台伺服器發了查詢。 - 解釋為什麼根伺服器只有 13 個 IP,卻能服務全世界的首跳查詢?(提示:anycast)
- 你的網站要從 A 伺服器遷移到 B 伺服器,停機期間想盡量縮短。請規劃完整的 TTL 操作時程表。
- 為什麼
example.com的根網域不能直接設 CNAME 指到blog.example.com?Cloudflare 用什麼技術解決?