Linux中國

為什麼有時候域名的末尾有個點?

大家好!今年早些時候,我在寫《DNS 是如何工作的》 時,有人問我——為什麼人們有時在域名的末尾加一個點?例如,如果你通過運行 dig example.com 查詢 example.com 的 IP,你會看到一下內容:

$ dig example.com
example.com.        5678    IN  A   93.184.216.34

執行完 dig 命令後,example.com 有一個 . ——變成了 example.com.!發生了什麼?

有些 DNS 工具也要求傳給它的域名後加一個 .:如果你在使用 miekg/dns 時傳給它 example.com,它會報錯:

// trying to send this message will return an error
m := new(dns.Msg)
m.SetQuestion("example.com", dns.TypeA)

最初我以為我知道這個問題的答案(「呃,末尾的點意味著域名是完全限定的?」)。這是對的 —— 一個 完全限定域名 fully qualified domain name (FQDN)是一個末尾有 . 的域名!

但是為什麼末尾的點是有用且重要的呢?

DNS 的請求/響應中,域名的末尾並沒有 「.」

我曾經(錯誤地)認為 「為什麼末尾有一個點?」的答案可能是 「在 DNS 請求/響應中,域名末尾有一個 .,所以我們把它放進去,以匹配你的計算機實際發送/接收的內容」。但事實並不是這樣!

當計算機發送 DNS 請求/響應時,域名的末尾並沒有點。實際上,域名中沒有點。

域名會被編碼成一系列的長度/字元串對。例如,域名 example.com 被編碼為這 13 個位元組。

7example3com0

編碼後的內容一個點也沒有。一個 ASCII 域名(如 example.com)被轉成了各種 DNS 軟體的 DNS 請求/響應中使用的格式。

今天我們來討論域名被轉成 DNS 響應的一個地方:區域文件。

區域文件中域名末尾的 「.」

一些人管理域名的 DNS 記錄的方法是創建一個被稱為 「區域文件」 的文本文件,然後配置一些 DNS 伺服器軟體(如 nsdbind)來為該區域文件中指定的 DNS 記錄提供服務。

下面是一個對應 example.com 的示例區域文件:

orange  300   IN    A     1.2.3.4
fruit   300   IN    CNAME orange
grape   3000  IN    CNAME example.com.

在這個文件中,任何不以 . 結尾的域名(比如 orange)後都會自動加上 .example.com。所以 orange 成了 orange.example.com 的簡稱。DNS 伺服器從它的配置中得知這是一個 example.com 的區域文件,所以它知道在所有不以點結尾的名字後面自動添加 example.com

我想這裡的想法只是為了少打幾個字元——如果要打出全稱,區域文件會是這樣:

    orange.example.com.  300   IN    A     1.2.3.4
    fruit.example.com.   300   IN    CNAME orange.example.com.
    grape.example.com.   3000  IN    CNAME example.com.

確實多了很多字元。

你也可以不通過區域文件來使用 DNS

儘管官方的 DNS RFC(RFC 1035)中定義了區域文件格式,但你也可以不通過區域文件來使用 DNS。例如,AWS Route 53 就不用區域文件來存儲 DNS 記錄!你可以通過 Web 界面或 API 來創建記錄,我猜他們是用某種資料庫而不是一堆文本文件來存儲記錄。

不過,Route 53(像許多其他 DNS 工具一樣)確實支持導入和導出區域文件,這個功能或許在你更換 DNS 提供商時很有用。

dig 命令輸出中末尾的 「.」

現在我們來討論下 dig 命令的輸出:

$ dig example.com
; <<>> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> +all example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10712
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;example.com.           IN  A

;; ANSWER SECTION:
example.com.        81239   IN  A   93.184.216.34

有一件奇怪的事是,幾乎每一行都以 ;; 開頭,這是怎麼回事?; 是區域文件中的注釋字元!

我想 dig 以這種奇怪的方式輸出的原因可能是為了方便你粘貼這些內容到區域文件時,不用修改就可以直接用。

這也是 example.com 末尾有個 . 的原因 —— 區域文件要求域名末尾必須有點(否則它們會被解釋為是相對於該區域的)。因此 dig 也這麼處理了。

我真的希望 dig 有一個 +human 選項,以更人性化的方式列印出這些信息,但現在我太懶了,懶得花工夫去實際貢獻代碼來做這件事(而且我並不擅長 C),所以我只能在我的博客上抱怨一下 :smiley:

curl 命令輸出中末尾的 「.」

我們來看下另一個末尾有 . 的例子:curl

我家裡有台計算機名為 grapefruit,其上運行著 Web 伺服器。當我執行 curl grapefruit 時,會輸出:

$ curl grapefruit
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
......

這樣運行沒問題!但是如果我在域名後加一個 . 會怎樣呢?它報錯了:

$ curl grapefruit.
curl: (6) Could not resolve host: grapefruit.

發生了什麼?為了搞清楚,我們需要先來學習下搜索域:

初識搜索域

當我執行 curl grapefrult 時,它是怎麼被轉成一個 DNS 請求的?你可能會認為我的計算機會向域名 grapefruit 發送一個請求,對嗎?但事實並不是這樣。

讓我們用 tcpdump 來看看到底是什麼域名在被查詢。

$ sudo tcpdump -i any port 53
[...] A? grapefruit.lan. (32)

實際上是向 grapefruit.lan. 發送的請求。為什麼呢?

解釋一下:

  1. curl 調用函數 getaddrinfo 來查詢 grapefruit
  2. getaddrinfo 查詢了我計算機上的文件 /etc/resolv.conf
  3. /etc/resolv.conf 包含兩行內容:
nameserver 127.0.0.53
search lan
  1. 因為有 search lan 這行內容,所以 getaddrinfograpefruit 的末尾添加了一個 lan,去查詢 grapefruit.lan

什麼時候搜索域被使用?

現在我們知道了一些奇怪的事情:當我們查詢一個域名時,有時會有一個額外的東西(如 lan)被加到最後。但是什麼時候會發生這種情況呢?

  1. 如果我們在域名末尾添加一個 .,那麼這時不會用到搜索域
  2. 如果域名中間包含一個 .(如 example.com),那麼默認也不會用到搜索域。但是可以通過修改配置來改變處理邏輯(在 ndots 里有更詳細的說明)

我們現在知道了 curl grapefruit.curl grapefruit 結果不一樣的原因——因為一個查詢的是 grapefruit.,而另一個查詢的是 grapefruit.lan.

我的計算機怎麼知道使用哪個搜索域呢?

當我連接路由時,它會通過 DHCP 告訴我它的搜索域是 lan —— 它也是通過這個方式給我的計算機分配 IP。

所以為什麼要在域名末尾加一個點呢?

現在我們已經了解了區域文件和搜索域,下面是我認為的人們要在域名末尾加點的原因:

有兩種情況下,域名會被修改,並在末尾添加其他東西。

  • example.com 的區域文件中,grapefruit 會被轉為 grapefruit.example.com
  • 在我的本地網路(我的計算機已經配置了使用搜索域 lan),grapefruit 被轉為 grapefruit.lan

因此,由於域名在某些情況下實際上可能被轉成其他名字,人們就在結尾處加一個 .,以此來表示 「這是域名,末尾不需要添加任何東西,這就是全部內容」。否則會引起混亂。

「這就是全部內容」的技術術語是「完全限定域名」,簡稱為「FQDN」。所以 google.com. 是一個完全限定域名,而 google.com 不是。

我總是要提醒自己這樣做的原因,因為我很少使用區域文件和搜索域,所以我經常覺得——「我當然是指 google.com 而不是 google.com.something.else! 我為什麼要指其他東西?那太傻了!」

但是有些人確實在使用區域文件和搜索域(例如 Kubernetes 中使用了搜索域!),所以結尾的 . 很有用,可以讓人確切的知道,不應該再添加其他東西。

什麼時候在末尾添加 「.」?

以下是關於何時在域名末尾加 ". " 的幾個簡單說明:

需要添加:配置 DNS 時

在配置 DNS 時,使用完全限定域名從來都不是壞事。你不一定要這樣做:非完全限定域名通常也能正常工作,但我從來沒有遇到過不接受完全限定域名的 DNS 軟體。

有些 DNS 軟體需要這樣做:現在我為 jvns.ca 使用的 DNS 伺服器讓我在域名的末尾加上 .(例如在 CNAME 記錄中),並提示如果我不添加,它將在我輸入的內容末尾加上 .jvns.ca。我不同意這個設計決定,但這不是什麼大問題,我只是在最後加一個 .

不需要加:在瀏覽器中

令人困惑的是,在瀏覽器中,在域名結尾處加一個 . 不能正常運行。例如,如果我在瀏覽器中輸入 https://twitter.com.,它就會報錯。它會返回 404。

我認為這裡發生的事情是,它將 HTTP Host 標頭設置為 Host:twitter.com.,而對端的 Web 伺服器則期望 Host:twitter.com

同樣地,https://jvns.ca. 由於某種原因,返回了一個 SSL 錯誤。

我認為相對域名在過去是比較常見的

最後一件事:我認為「相對」域名(比如我用 grapefruit 來指代我家的另一台計算機 grapefruit.lan)在過去更常用,因為 DNS 是在大學或其他有大型內部網路的大機構中開發的。

在今天的互聯網上,使用「絕對」域名(如 example.com)似乎更為普遍。

via: https://jvns.ca/blog/2022/09/12/why-do-domain-names-end-with-a-dot-/

作者:Julia Evans 選題:lujun9972 譯者:lxbwolf 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國