06-1. DNS 域名解析

深入理解網際網路的電話簿:DNS 如何將域名轉換為 IP 位址

🌐 DNS 域名解析

🎯 什麼是 DNS?

💡 比喻:網際網路的電話簿

你記得朋友的名字(www.google.com)
但不記得他的電話號碼(142.250.185.46)

DNS 就是幫你查電話簿的服務
名字 → 電話號碼
域名 → IP 位址

DNS(Domain Name System) 是一個分散式的命名系統,負責將人類易讀的域名(如 www.example.com)轉換為機器可識別的 IP 位址(如 93.184.216.34)。

為什麼需要 DNS?

沒有 DNS 的世界:

# 訪問 Google 需要記住 IP
curl http://142.250.185.46

# 訪問 Facebook 需要記住 IP
curl http://157.240.3.35

# 訪問 YouTube 需要記住 IP
curl http://172.217.160.110

問題:
1. 難以記憶
2. IP 可能改變(網站搬家)
3. 一個網站可能有多個 IP(負載平衡)

有 DNS:

# 使用易記的域名
curl https://www.google.com
curl https://www.facebook.com
curl https://www.youtube.com

DNS 自動幫你找到對應的 IP!

🏗️ DNS 在網路模型中的位置

OSI 7 層模型

┌──────────────────────────────┬─────────────────┐
│ 7. Application Layer (應用層) │  DNS            │ ← DNS 在這裡
├──────────────────────────────┼─────────────────┤
│ 6. Presentation Layer (表示層)│  加密、壓縮      │
├──────────────────────────────┼─────────────────┤
│ 5. Session Layer (會話層)     │  建立、維護會話  │
├──────────────────────────────┼─────────────────┤
│ 4. Transport Layer (傳輸層)   │  UDP (主要), TCP│
├──────────────────────────────┼─────────────────┤
│ 3. Network Layer (網路層)     │  IP             │
├──────────────────────────────┼─────────────────┤
│ 2. Data Link Layer (資料鏈結層)│  Ethernet       │
├──────────────────────────────┼─────────────────┤
│ 1. Physical Layer (實體層)    │  網路線、光纖    │
└──────────────────────────────┴─────────────────┘

DNS 位於第 7 層(應用層)

  • DNS 是應用層協定
  • 提供域名解析服務
  • 將人類可讀的域名轉換為 IP 位址

TCP/IP 4 層模型

┌─────────────────────────────┬─────────────────┐
│ 4. Application Layer (應用層) │  DNS            │ ← DNS 在這裡
├─────────────────────────────┼─────────────────┤
│ 3. Transport Layer (傳輸層)  │  UDP (主要), TCP│
├─────────────────────────────┼─────────────────┤
│ 2. Internet Layer (網際網路層)│  IP             │
├─────────────────────────────┼─────────────────┤
│ 1. Network Access (網路存取層)│  Ethernet       │
└─────────────────────────────┴─────────────────┘

DNS 位於第 4 層(應用層)

  • 在 TCP/IP 模型中,DNS 是應用層協定
  • 主要使用 UDP(Port 53),查詢快速
  • 當回應超過 512 bytes 時,使用 TCP(Port 53)

對比表:

協定OSI 層級TCP/IP 層級傳輸層協定Port用途
DNSLayer 7Layer 4UDP (主要), TCP53域名解析
DHCPLayer 7Layer 4UDP67/68動態 IP 分配
NTPLayer 7Layer 4UDP123時間同步

重點:

  • DNS 是應用層協定(兩種模型都是)
  • 主要使用 UDP(快速、低開銷)
    • 查詢/回應通常 < 512 bytes → UDP
    • 回應 > 512 bytes → 切換到 TCP
    • Zone Transfer(區域傳輸)→ TCP
  • DoH (DNS over HTTPS) → 使用 TCP Port 443
  • DoT (DNS over TLS) → 使用 TCP Port 853

DNS 使用 UDP 的原因:

為什麼 DNS 主要用 UDP?

1. 速度快 ⚡
   UDP 無需三次握手
   查詢 → 回應(只需 2 個封包)

2. 開銷低 💰
   DNS 查詢量極大(全球每秒數億次)
   UDP 沒有連線狀態,節省資源

3. 失敗重試 🔄
   DNS client 可以自己處理逾時重試
   不需要 TCP 的可靠性保證

何時用 TCP?
✅ Zone Transfer(DNS 伺服器間同步)
✅ 回應超過 512 bytes(DNSSEC 簽章)
✅ DoH/DoT 加密查詢

🏗️ DNS 架構

階層式結構

💡 比喻:郵遞區號系統
台灣 → 台北市 → 大安區 → 忠孝東路 → 123號

DNS:
. (根) → com. → google.com. → www.google.com.
                     . (Root)
                    /    |    \
                  /      |      \
               com.     org.    tw.
              /   \       |      |
            /       \     |      |
        google.  amazon. wikipedia.  edu.tw.
          |         |       |          |
        www.      www.    www.       ntu.

完整域名(FQDN):

www.google.com.
│   │      │   └─ 根域名(通常省略)
│   │      └───── 頂級域名(TLD: Top-Level Domain)
│   └────────── 二級域名
└──────────── 主機名稱

DNS 伺服器類型

1. 根 DNS 伺服器(Root DNS Server):

💡 比喻:郵局總部
知道每個國家的郵局在哪裡

全球只有 13 個邏輯根伺服器(A-M)
實際上透過 Anycast 部署了數百個實體伺服器
根伺服器列表:
a.root-servers.net (198.41.0.4)
b.root-servers.net (199.9.14.201)
c.root-servers.net (192.33.4.12)
...
m.root-servers.net (202.12.27.33)

2. 頂級域名伺服器(TLD DNS Server):

💡 比喻:國家郵局
負責 .com, .org, .net, .tw 等頂級域名

.com → Verisign
.org → Public Interest Registry
.tw  → TWNIC(台灣網路資訊中心)

3. 權威 DNS 伺服器(Authoritative DNS Server):

💡 比喻:公司總機
公司的電話總機知道所有員工的分機號碼

google.com 的權威伺服器知道:
- www.google.com → 142.250.185.46
- mail.google.com → 172.217.160.37
- drive.google.com → 142.250.185.110

4. 遞迴 DNS 伺服器(Recursive DNS Server):

💡 比喻:你的秘書
幫你查電話簿,找到號碼後告訴你

通常是 ISP 提供:
- Hinet: 168.95.1.1
- Google Public DNS: 8.8.8.8
- Cloudflare DNS: 1.1.1.1

🔍 DNS 查詢流程

遞迴查詢(Recursive Query)

💡 比喻:問秘書「Google 的電話是多少?」
秘書幫你查好,直接告訴你答案

完整流程:

使用者                                         DNS 解析過程
  │
  ├─ 1. 查詢 www.google.com ──────────────────────────────────────┐
  │                                                                │
  │                                    ┌──────────────────────────▼────┐
  │                                    │ 遞迴 DNS (8.8.8.8)            │
  │                                    │ ┌──────────────────────────┐  │
  │                                    │ │ 1. 檢查快取(未命中)     │  │
  │                                    │ └──────────────────────────┘  │
  │                                    └───────────┬───────────────────┘
  │                                                │
  │                                    ┌───────────▼───────────────────┐
  │                                    │ 2. 查詢根 DNS (a.root-servers)│
  │                                    │    → 回應:查 .com TLD        │
  │                                    └───────────┬───────────────────┘
  │                                                │
  │                                    ┌───────────▼───────────────────┐
  │                                    │ 3. 查詢 .com TLD              │
  │                                    │    → 回應:查 google.com NS   │
  │                                    └───────────┬───────────────────┘
  │                                                │
  │                                    ┌───────────▼───────────────────┐
  │                                    │ 4. 查詢 google.com 權威 DNS   │
  │                                    │    → 回應:142.250.185.46     │
  │                                    └───────────┬───────────────────┘
  │                                                │
  │<─ 2. 回應:142.250.185.46 ─────────────────────┘
  │
  ├─ 3. 連線到 142.250.185.46 ────────────────────> Google 伺服器

詳細步驟:

Step 1: 瀏覽器查詢 www.google.com

Step 2: 遞迴 DNS (8.8.8.8) 查詢根伺服器
查詢:www.google.com 的 IP 是?
根伺服器回應:我不知道,但你可以問 .com TLD (192.5.6.30)

Step 3: 查詢 .com TLD
查詢:www.google.com 的 IP 是?
TLD 回應:我不知道,但你可以問 google.com 的權威 DNS (ns1.google.com)

Step 4: 查詢 google.com 權威 DNS
查詢:www.google.com 的 IP 是?
權威 DNS 回應:142.250.185.46

Step 5: 遞迴 DNS 回應給使用者
142.250.185.46

Step 6: 瀏覽器連線到 142.250.185.46

迭代查詢(Iterative Query)

💡 比喻:自己查電話簿
秘書不幫你查,只告訴你「去哪裡查」
使用者 → 遞迴 DNS:www.google.com 在哪?
遞迴 DNS → 根 DNS:www.google.com 在哪?
根 DNS → 遞迴 DNS:我不知道,問 .com TLD (192.5.6.30)

遞迴 DNS → .com TLD:www.google.com 在哪?
.com TLD → 遞迴 DNS:我不知道,問 ns1.google.com (216.239.32.10)

遞迴 DNS → ns1.google.com:www.google.com 在哪?
ns1.google.com → 遞迴 DNS:142.250.185.46

遞迴 DNS → 使用者:142.250.185.46

📝 DNS 記錄類型

常見記錄類型

1. A 記錄(Address Record):

💡 功能:域名 → IPv4 位址
www.example.com.  IN  A  93.184.216.34
│                 │   │  │
│                 │   │  └─ IPv4 位址
│                 │   └──── 記錄類型
│                 └──────── IN (Internet)
└────────────────────────── 域名

範例:

# 查詢 A 記錄
dig www.google.com A

# 回應
www.google.com.  300  IN  A  142.250.185.46

2. AAAA 記錄(IPv6 Address):

💡 功能:域名 → IPv6 位址
www.example.com.  IN  AAAA  2606:2800:220:1:248:1893:25c8:1946

3. CNAME 記錄(Canonical Name):

💡 功能:別名 → 正式名稱
比喻:暱稱 → 本名
blog.example.com.  IN  CNAME  example.github.io.
│                              │
│                              └─ 真正的域名
└────────────────────────────── 別名

範例:

www.example.com.  IN  CNAME  example.com.
example.com.      IN  A      93.184.216.34

查詢流程:
1. 查 www.example.com → CNAME → example.com
2. 查 example.com → A → 93.184.216.34

注意:CNAME 限制

❌ 錯誤:根域名不能是 CNAME
example.com.  IN  CNAME  other.com.  # 不允許!

✅ 正確:子域名可以是 CNAME
www.example.com.  IN  CNAME  other.com.  # 允許

4. MX 記錄(Mail Exchange):

💡 功能:指定郵件伺服器
example.com.  IN  MX  10 mail1.example.com.
example.com.  IN  MX  20 mail2.example.com.
                  │   │
                  │   └─ 郵件伺服器域名
                  └───── 優先級(數字越小優先級越高)

範例:

dig example.com MX

# 回應
example.com.  3600  IN  MX  10 aspmx.l.google.com.
example.com.  3600  IN  MX  20 alt1.aspmx.l.google.com.

# 發送郵件時:
# 先嘗試 aspmx.l.google.com (優先級 10)
# 如果失敗,嘗試 alt1.aspmx.l.google.com (優先級 20)

5. NS 記錄(Name Server):

💡 功能:指定權威 DNS 伺服器
example.com.  IN  NS  ns1.example.com.
example.com.  IN  NS  ns2.example.com.

範例:

dig example.com NS

# 回應
example.com.  3600  IN  NS  a.iana-servers.net.
example.com.  3600  IN  NS  b.iana-servers.net.

6. TXT 記錄(Text):

💡 功能:儲存文字資訊
用途:SPF、DKIM、網站驗證

範例:

# SPF(防止郵件偽造)
example.com.  IN  TXT  "v=spf1 include:_spf.google.com ~all"

# 網站驗證(Google Search Console)
example.com.  IN  TXT  "google-site-verification=abcd1234..."

# DKIM(郵件簽章)
default._domainkey.example.com.  IN  TXT  "v=DKIM1; k=rsa; p=MIGfMA0..."

7. PTR 記錄(Pointer):

💡 功能:反向查詢(IP → 域名)
46.185.250.142.in-addr.arpa.  IN  PTR  www.google.com.
│
└─ 反轉的 IP (142.250.185.46)

範例:

# 反向查詢
dig -x 8.8.8.8

# 回應
8.8.8.8.in-addr.arpa.  21599  IN  PTR  dns.google.

⚡ DNS 快取機制

💡 比喻:電話簿的便利貼
常打的號碼寫在便利貼上,下次不用翻電話簿

TTL(Time To Live)

www.google.com.  300  IN  A  142.250.185.46
                 │
                 └─ TTL = 300 秒(5 分鐘)

意思:這筆記錄可以快取 5 分鐘
5 分鐘後需要重新查詢

快取層級:

1. 瀏覽器快取(1 分鐘)
   chrome://net-internals/#dns

2. 作業系統快取
   Windows: ipconfig /displaydns
   Linux: systemd-resolved --statistics

3. 遞迴 DNS 快取(依 TTL)

4. 權威 DNS(不快取,直接回應)

清除快取:

# Windows
ipconfig /flushdns

# macOS
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

# Linux
sudo systemd-resolve --flush-caches

🛠️ DNS 實戰工具

1. dig 命令

# 基本查詢
dig www.google.com

# 指定記錄類型
dig www.google.com A
dig example.com MX
dig example.com NS

# 簡化輸出(只顯示答案)
dig www.google.com +short

# 追蹤完整查詢過程
dig www.google.com +trace

# 指定 DNS 伺服器
dig @8.8.8.8 www.google.com

# 反向查詢
dig -x 8.8.8.8

dig +trace 範例:

$ dig www.google.com +trace

.               518400  IN  NS  a.root-servers.net.
# → 查詢根伺服器

com.            172800  IN  NS  a.gtld-servers.net.
# → 查詢 .com TLD

google.com.     172800  IN  NS  ns1.google.com.
# → 查詢 google.com 權威 DNS

www.google.com. 300     IN  A   142.250.185.46
# → 最終答案

2. nslookup 命令

# 基本查詢
nslookup www.google.com

# 指定 DNS 伺服器
nslookup www.google.com 8.8.8.8

# 互動式模式
nslookup
> set type=MX
> example.com
> set type=NS
> google.com
> exit

3. Python 實作 DNS 查詢

import socket

# 查詢 A 記錄(最簡單)
ip = socket.gethostbyname('www.google.com')
print(f"IP: {ip}")

# 使用 dnspython 庫(功能完整)
import dns.resolver

# 查詢 A 記錄
answers = dns.resolver.resolve('www.google.com', 'A')
for rdata in answers:
    print(f"A: {rdata.address}")

# 查詢 MX 記錄
answers = dns.resolver.resolve('gmail.com', 'MX')
for rdata in answers:
    print(f"MX: {rdata.preference} {rdata.exchange}")

# 查詢 TXT 記錄
answers = dns.resolver.resolve('google.com', 'TXT')
for rdata in answers:
    print(f"TXT: {rdata.strings}")

# 指定 DNS 伺服器
resolver = dns.resolver.Resolver()
resolver.nameservers = ['8.8.8.8', '1.1.1.1']
answers = resolver.resolve('www.example.com', 'A')

🔐 DNS 安全性

1. DNS 欺騙(DNS Spoofing)

💡 攻擊:偽造 DNS 回應
正常流程:
使用者 → DNS:facebook.com 在哪?
DNS → 使用者:157.240.3.35

攻擊流程:
使用者 → DNS:facebook.com 在哪?
攻擊者 → 使用者:(搶先回應)123.45.67.89(釣魚網站)
DNS → 使用者:(晚一步)157.240.3.35

防禦:DNSSEC


2. DNS 快取投毒(Cache Poisoning)

💡 攻擊:污染 DNS 快取
攻擊者偽造回應:
example.com → 惡意 IP

如果遞迴 DNS 相信並快取這筆記錄:
所有使用者都會被導向惡意 IP(在 TTL 期間)

防禦:

  • 來源 Port 隨機化
  • Transaction ID 隨機化
  • DNSSEC

3. DNSSEC(DNS Security Extensions)

💡 功能:數位簽章驗證 DNS 回應
就像郵件的簽名,確保來源可信

運作原理:

1. 權威 DNS 用私鑰簽署記錄
2. 發布公鑰(DNSKEY 記錄)
3. 遞迴 DNS 用公鑰驗證簽章
4. 如果簽章不符 → 拒絕回應

查詢 DNSSEC:

# 查詢 DNSKEY
dig google.com DNSKEY +dnssec

# 查詢 RRSIG(簽章)
dig www.google.com A +dnssec

4. DoH / DoT(加密 DNS)

DoH(DNS over HTTPS):

傳統 DNS:明文 UDP Port 53
DoH:HTTPS 加密(Port 443)

好處:
- ISP 無法竊聽你查詢什麼網站
- 防止 DNS 竄改

設定 DoH(瀏覽器):

Firefox:
設定 → 隱私權與安全性 → 啟用「透過 HTTPS 的 DNS」
伺服器:https://mozilla.cloudflare-dns.com/dns-query

Chrome:
設定 → 安全性 → 使用安全 DNS
選擇:Cloudflare (1.1.1.1) 或 Google (8.8.8.8)

DoT(DNS over TLS):

加密 DNS,使用 TLS(Port 853)

設定(Linux):
/etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1
DNSOverTLS=yes

🎓 常見面試題

Q1:DNS 查詢過程有哪些步驟?

答案:

完整 8 步驟:

  1. 瀏覽器檢查快取

    • 已訪問過?直接使用快取
  2. 檢查作業系統快取

    • 檢查 hosts 檔案和系統 DNS 快取
  3. 查詢遞迴 DNS

    • 向 ISP 或公共 DNS(8.8.8.8)查詢
  4. 遞迴 DNS 檢查快取

    • 有快取?直接回應
  5. 查詢根 DNS

    • 詢問 .com TLD 的位置
  6. 查詢 TLD DNS

    • 詢問 google.com 權威 DNS 的位置
  7. 查詢權威 DNS

    • 獲得最終 IP 位址
  8. 回應給使用者

    • 遞迴 DNS 快取結果並回應

記憶口訣:「瀏系遞緩根頂權回」


Q2:A 記錄和 CNAME 有什麼不同?

答案:

特性A 記錄CNAME
指向IP 位址另一個域名
用途直接解析別名
根域名✅ 可用❌ 不可用
多個值✅ 可以❌ 只能一個
範例example.com IN A 1.2.3.4www IN CNAME example.com

使用場景:

A 記錄:
example.com.      IN  A  93.184.216.34
# 直接指向 IP

CNAME:
www.example.com.  IN  CNAME  example.com.
blog.example.com. IN  CNAME  example.github.io.
# 指向另一個域名(別名)

為什麼根域名不能用 CNAME?

RFC 1034 規定:
如果一個域名有 CNAME 記錄,就不能有其他記錄

但根域名必須有 NS 和 SOA 記錄:
example.com.  IN  NS  ns1.example.com.
example.com.  IN  SOA ns1.example.com. admin.example.com. (...)

所以根域名不能用 CNAME

Q3:DNS 負載平衡如何實現?

答案:

方法 1:多個 A 記錄(Round Robin):

www.example.com.  IN  A  1.2.3.4
www.example.com.  IN  A  5.6.7.8
www.example.com.  IN  A  9.10.11.12

DNS 輪流回應不同 IP:
第 1 次查詢 → 1.2.3.4
第 2 次查詢 → 5.6.7.8
第 3 次查詢 → 9.10.11.12
第 4 次查詢 → 1.2.3.4(循環)

方法 2:GeoDNS(地理位置):

def resolve_dns(domain, client_ip):
    location = get_location(client_ip)

    if location == 'Asia':
        return '1.2.3.4'  # 亞洲伺服器
    elif location == 'Europe':
        return '5.6.7.8'  # 歐洲伺服器
    elif location == 'US':
        return '9.10.11.12'  # 美國伺服器

方法 3:智慧 DNS(健康檢查):

servers = [
    {'ip': '1.2.3.4', 'healthy': True},
    {'ip': '5.6.7.8', 'healthy': False},  # 故障
    {'ip': '9.10.11.12', 'healthy': True}
]

def resolve_dns(domain):
    # 只回應健康的伺服器
    healthy_servers = [s for s in servers if s['healthy']]
    return random.choice(healthy_servers)['ip']

Q4:DNS TTL 如何設定?

答案:

TTL 設定建議:

場景TTL原因
穩定服務3600-86400 (1小時-1天)減少查詢次數
準備遷移300-600 (5-10分鐘)快速切換
CDN60-300 (1-5分鐘)動態調整
測試環境60 (1分鐘)快速測試

範例:

# 穩定的服務(低 TTL 開銷)
www.example.com.  86400  IN  A  93.184.216.34
# 1 天內不會改變,減少 DNS 查詢

# 準備遷移(方便快速切換)
www.example.com.  300    IN  A  93.184.216.34
# 5 分鐘後可以切換到新 IP

# CDN(動態調整)
cdn.example.com.  60     IN  A  151.101.1.69
# 1 分鐘內可以更新

遷移步驟:

Step 1: 提前降低 TTL(24 小時前)
www.example.com.  86400  IN  A  1.2.3.4
→
www.example.com.  300    IN  A  1.2.3.4

Step 2: 等待舊 TTL 過期(等 1 天)

Step 3: 更新 A 記錄指向新 IP
www.example.com.  300    IN  A  5.6.7.8

Step 4: 驗證新 IP 運作正常

Step 5: 恢復高 TTL
www.example.com.  86400  IN  A  5.6.7.8

Q5:如何診斷 DNS 問題?

答案:

常見問題與診斷:

1. 域名無法解析:

# 測試是否是 DNS 問題
ping www.example.com
# 如果顯示「找不到主機」→ DNS 問題

# 使用不同 DNS 伺服器測試
nslookup www.example.com 8.8.8.8
nslookup www.example.com 1.1.1.1

# 如果公共 DNS 可以解析,ISP DNS 不行
# → ISP DNS 快取問題或設定問題

2. DNS 傳播延遲:

# 檢查全球 DNS 傳播狀態
# 使用線上工具:whatsmydns.net

# 或手動查詢不同地區的 DNS
dig @8.8.8.8 www.example.com
dig @1.1.1.1 www.example.com
dig @208.67.222.222 www.example.com  # OpenDNS

# 如果結果不同 → 正在傳播中

3. CNAME 循環:

# 錯誤設定
a.example.com.  IN  CNAME  b.example.com.
b.example.com.  IN  CNAME  a.example.com.
# CNAME 指向彼此 → 無限循環

# 診斷
dig a.example.com
# 錯誤:CNAME loop detected

4. 快取問題:

# 清除本地快取
ipconfig /flushdns  # Windows
sudo systemd-resolve --flush-caches  # Linux

# 檢查快取的 TTL
dig www.google.com
# 回應中的 TTL 會遞減
# 300 → 250 → 200 ... → 0(需要重新查詢)

5. DNSSEC 驗證失敗:

# 檢查 DNSSEC
dig example.com +dnssec

# 如果回應包含 SERVFAIL
# → DNSSEC 驗證失敗

# 可能原因:
# 1. 簽章過期
# 2. 時鐘不同步
# 3. 設定錯誤

📝 總結

DNS 關鍵要點:

  • 分散式架構:根 → TLD → 權威 DNS 🏗️
  • 快取機制:TTL 控制快取時間 ⏱️
  • 記錄類型:A、AAAA、CNAME、MX、NS、TXT 📋
  • 安全性:DNSSEC、DoH、DoT 🔐

記憶口訣:「分(分散)、快(快取)、錄(記錄)、安(安全)」

DNS 查詢流程:

瀏覽器快取 → 系統快取 → 遞迴 DNS → 根 DNS → TLD → 權威 DNS

優化建議:

  • 使用公共 DNS(8.8.8.8, 1.1.1.1)提升速度
  • 適當設定 TTL 平衡快取與靈活性
  • 啟用 DNSSEC 提升安全性
  • 使用 GeoDNS 實現全球負載平衡

🔗 延伸閱讀

0%