為什麼 DNS 仍然難以學習?
我經常寫關於我發現難以學習的技術的文章。不久前,我的朋友 Sumana 向我提出了一個有趣的問題 - 為什麼這些東西學起來那麼難?為什麼它們看起來如此神秘?
以 DNS 為例。我們從 80 年代 開始使用 DNS(已經超過 35 年了!)。它在互聯網上的每個網站中都使用。而且它相當穩定 - 在很多方面,它的工作方式與 30 年前完全相同。
但是我花了好幾年的時間才弄清楚如何自信地調試 DNS 問題,我也見過很多其他程序員在調試 DNS 問題上苦苦掙扎。那麼到底發生了什麼呢?
以下是關於為什麼學習排除 DNS 問題很困難的幾點思考。
(我不會在這篇文章中詳細解釋 DNS,更多關於 DNS 如何工作的信息,請參閱 《用一個周末實現一個 DNS》 或 我的 DNS 方面的博文)
並不是因為 DNS 非常難
當我最終學會如何排除 DNS 問題時,我的反應是「什麼,就這樣嗎???這並不難!」我感覺有點被騙了!我可以在 幾個小時 內向你解釋關於 DNS 令我感到困惑的一切事情。
那麼 - 如果 DNS 並不是那麼複雜,為什麼我花了這麼多年的時間才弄清楚如何排除相當基本的 DNS 問題(比如「即使我已經正確設置了,我的域名仍無法解析」或者「dig
命令和我的瀏覽器的 DNS 結果不一致,為什麼?」)?
而且,在發現 DNS 學習困難方面,我並不孤單!我與許多經驗豐富的程序員朋友討論過多年來的 DNS 問題,其中很多人要麼:
- 不敢輕易對其網站進行簡單的 DNS 更改
- 或對 DNS 工作原理的基本事實感到困惑(比如記錄是 拉取的而非推送的)
- 或對 DNS 基礎知識了解得很好,但卻和我一樣存在一些知識盲點(負緩存和
dig
命令及瀏覽器如何以不同方式進行 DNS 查詢的細節)
因此,如果我們都面臨著 DNS 的相同困擾,到底發生了什麼?為什麼對許多人來說學習 DNS 如此困難?
以下是我的一些看法。
很多系統是隱藏的
當你在計算機上發起 DNS 請求時,基本的過程如下:
- 你的計算機向一個名為「解析器」的伺服器發起請求。
- 解析器檢查其緩存,並向一些稱為「權威名稱伺服器」的其它伺服器發起請求。
以下是你看不到的一些內容:
- 解析器的緩存。裡面有什麼內容?
- 在你的計算機上進行 DNS 請求的庫代碼是哪個(是否是 libc 的
getaddrinfo
函數?如果是,它是來自 glibc、musl 還是蘋果?是你的瀏覽器的 DNS 代碼嗎?還是其他自定義的 DNS 實現?)所有這些選項的行為略有不同,並且有不同的配置、緩存方法、可用功能等等。例如,musl DNS 直到 2023 年初 才支持 TCP。 - 解析器與權威名稱伺服器之間的對話。如果你能夠神奇地獲得一個準確記錄你的請求期間向下游查詢的每個權威名稱伺服器以及它們的響應的追蹤,我認為很多 DNS 問題將變得非常簡單。(比如,如果你能運行
dig +debug google.com
並獲得一些額外的調試信息會怎麼樣?)
如何和隱藏系統打交道
以下是幾個處理隱藏系統的方法:
- 向人們傳授隱藏系統的知識會產生重大影響。很長一段時間裡,我不知道我的計算機有多個不同的 DNS 庫,它們在不同情況下使用,我對此感到困惑了好幾年。這是我的重要排錯方法。
- 通過 Mess With DNS,我們嘗試了一種「魚缸」的方法,展示了通常隱藏的系統(與解析器和權威名稱伺服器的對話)的一些部分。
- 我覺得將 DNS 擴展以包括一個「調試信息」部分會非常酷。(註:似乎這已經有了!它被稱為「擴展 DNS 錯誤」,即 EDE,各種工具正在逐漸添加對它的支持。)
擴展 DNS 錯誤看起來不錯
擴展 DNS 錯誤是 DNS 伺服器提供額外調試信息的一種新方式。以下是一個示例:
$ dig @8.8.8.8 xjwudh.com
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 39830
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; EDE: 12 (NSEC Missing): (Invalid denial of existence of xjwudh.com/a)
;; QUESTION SECTION:
;xjwudh.com. IN A
;; AUTHORITY SECTION:
com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1690634120 1800 900 604800 86400
;; Query time: 92 msec
;; SERVER: 8.8.8.8#53(8.8.8.8) (UDP)
;; WHEN: Sat Jul 29 08:35:45 EDT 2023
;; MSG SIZE rcvd: 161
這裡我請求了一個不存在的域名,並收到了擴展錯誤信息 EDE: 12 (NSEC Missing): (Invalid denial of existence of xjwudh.com/a)
。我不太確定這是什麼意思(它與 DNSSEC 有關),但能看到這樣額外的調試信息真的很酷。
為了能看到上述內容,我確實需要安裝更新版本的 dig
。
令人困惑的工具
儘管很多 DNS 的細節被隱藏起來,但你可以通過使用 dig
工具來找出發生了什麼事情。
例如,你可以使用 dig +norecurse
來確定給定的 DNS 解析器是否在其緩存中具有特定的記錄。如果響應沒有被緩存,8.8.8.8
看起來會返回 SERVFAIL
響應。
以下是對 google.com
進行該操作的示例:
$ dig +norecurse @8.8.8.8 google.com
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11653
;; flags: qr ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 21 IN A 172.217.4.206
;; Query time: 57 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Jul 28 10:50:45 EDT 2023
;; MSG SIZE rcvd: 55
這是對 homestarrunner.com
的示例:
$ dig +norecurse @8.8.8.8 homestarrunner.com
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 55777
;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;homestarrunner.com. IN A
;; Query time: 52 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Jul 28 10:51:01 EDT 2023
;; MSG SIZE rcvd: 47
在這裡,你可以看到我們對於 google.com
得到了一個正常的 NOERROR
響應(8.8.8.8
的緩存中有該記錄),但對於 homestarrunner.com
得到了 SERVFAIL
響應(沒有緩存)。這並不意味著 homestarrunner.com
沒有 DNS 記錄(實際上有!),它只是沒有被緩存。
但如果你不熟悉這樣的輸出,它確實很難閱讀!以下是我認為其中一些奇怪的地方:
- 標題很奇怪(有
->>HEADER<<-
、flags:
、OPT PSEUDOSECTION:
、QUESTION SECTION:
、ANSWER SECTION:
)。 - 空格排版很奇怪(
OPT PSEUDOSECTION
和QUESTION SECTION
之間為什麼沒有換行符?)。 MSG SIZE rcvd: 47
很奇怪(MSG SIZE
中是否還有其他欄位,而不僅僅是rcvd
?它們是什麼?)。- 它說有 1 個記錄在
ADDITIONAL
部分,但沒有顯示它,你必須以某種方式神奇地知道OPT PSEUDOSECTION
記錄實際上在ADDITIONAL
部分。
總的來說,dig
的輸出給人的感覺是一個以臨時方式編寫並隨著時間的推移逐漸發展起來的腳本,而不是經過有意設計的東西。
處理令人困惑的工具的一些想法:
- 解釋輸出結果。例如,我寫了一篇 如何使用 dig 的文章,解釋了
dig
的輸出結果以及如何配置它以默認給出更簡短的輸出。 - 創建新的、更友好的工具。例如,在 DNS 方面,有 dog、doggo 和 我的 DNS 查詢工具。我認為這些工具非常酷,但我個人不使用它們,因為有時我想做一些稍微高級一點的操作(比如使用
+norecurse
),據我所知,無論是dog
還是doggo
都不支持+norecurse
。我更願意使用一個工具來完成所有任務,所以我堅持使用dig
。要替換dig
,其功能廣度是一項龐大的工作。 - 使 dig 的輸出更加友好。如果我在 C 編程方面更好一些,我可能會嘗試編寫一個
dig
的拉取請求,添加一個+human
標誌以以更結構化和易讀的方式格式化長格式的輸出,可能類似於以下形式:
$ dig +human +norecurse @8.8.8.8 google.com
HEADER:
opcode: QUERY
status: NOERROR
id: 11653
flags: qr ra
records: QUESTION: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
QUESTION SECTION:
google.com. IN A
ANSWER SECTION:
google.com. 21 IN A 172.217.4.206
ADDITIONAL SECTION:
EDNS: version: 0, flags:; udp: 512
EXTRA INFO:
Time: Fri Jul 28 10:51:01 EDT 2023
Elapsed: 52 msec
Server: 8.8.8.8:53
Protocol: UDP
Response size: 47 bytes
這樣可以更清晰地呈現 DNS 響應的結構-包括標題、問題、答案和附加部分。
而且它並不是「簡化」了什麼!它是完全相同的信息,只是以更結構化的方式進行了格式化。我對替代的 DNS 工具最大的不滿是它們經常為了清晰起見而刪除信息。雖然這些工具肯定有其用武之地,但我想要看到所有的信息!我只是希望它能夠以清晰明了的方式呈現。
在過去的 40 年中,我們已經學到了很多關於如何設計更用戶友好的命令行工具的知識,我認為將其中一些知識應用到我們那些有些陳舊的工具中將會很棒。
dig +yaml
關於 dig
的一個簡單備註:較新版本的 dig
支持 +yaml
輸出格式,對我來說更加清晰,但有些冗長(一個相當簡單的 DNS 響應都無法在屏幕上完整顯示)。
一些奇怪的陷阱
DNS 存在一些相對常見但很難通過自學了解到的奇怪問題。以下是一些例子(有更多可在 導致 DNS 中斷的一些方式 中找到):
- 負緩存:我在 這篇演講 中提到過,我大約花了 5 年時間才意識到不應該訪問沒有 DNS 記錄的域名,因為該記錄的 不存在 信息將被緩存,並且該緩存在幾個小時內不會被更新,這真的很煩人。
getaddrinfo
實現的差異:直到 2023 年初,musl
不支持 TCP DNS。- 忽略 TTL 的解析器:如果你在 DNS 記錄上設置了 TTL(比如「5 分鐘」),一些解析器完全會忽略這些 TTL 設置,並將記錄緩存更長時間,比如可能是 24 小時。
- 如果你錯誤地配置了 Nginx(像這樣),它將永久緩存 DNS 記錄。
- ndots 如何導致 Kubernetes DNS 緩慢。
如何應對奇怪的陷阱
對此,我沒有像我希望的那樣完美的答案。對奇怪陷阱的了解非常難以獲得(再次強調,我花了多年的時間才弄清楚負緩存!),對我而言,人們不得不一次又一次地自己重新發現它們感覺很愚蠢。
以下是一些想法:
- 當有人在解釋一個主題時提到了一些棘手的問題,這是非常有幫助的。例如(離開 DNS 一下),Josh Comeau 的 Flexbox 入門解釋了這個 最小尺寸的陷阱,在找到解釋之前,我多年來遇到過很多次這個問題。
- 我希望看到更多的社區整理的常見陷阱。比如說,對於 Bash,shellcheck 是一個非常不錯的常見陷阱集合。
關於記錄 DNS 陷阱的一個棘手問題是,不同的人會遇到不同的陷阱。如果你只是每三年為個人域名配置一次 DNS,你可能會遇到不同的問題,而那些管理高流量域名的人則可能會遇到其他問題。
還有一些更簡單的原因:
不經常接觸
很多人非常少接觸 DNS。如果你只在每三年才處理一次 DNS,學習起來就會更加困難!
我認為備忘單(比如「這是更改你的名稱伺服器的步驟」)可以在這方面起到很大的幫助。
難以進行實驗
DNS 在進行實驗時可能會讓人感到害怕,因為你不想搞砸自己的域名。我們建立了 Mess With DNS 來使這個過程變得更容易一些。
目前就這些
我很想聽聽其他關於什麼讓 DNS(或你最喜歡的神秘技術)難以學習的想法。
(題圖:MJ/96c5d8fb-f4a5-4710-8f91-c71617120675)
via: https://jvns.ca/blog/2023/07/28/why-is-dns-still-hard-to-learn/
作者:Julia Evans 選題:lujun9972 譯者:ChatGPT 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive