伺服器架設篇 - RockyLinux 9

第八章、領域名稱伺服器 DNS 服務

無論是 WAN 還是 LAN,主機名稱與 IP 位址的對應都是非常重要的!所以才需要 DNS 服務!

最近更新時間: 2023/11/30

以前提到 DNS 系統,大家都覺得似乎是在網際網路服務上面才需要這東西!不過,大家想一想,我們在企業內部, 每部主機應該也都需要提供主機名稱吧?如果透過自己的 /etc/hosts 檔案來處理,每次增加/修改伺服器 IP 位址與主機名稱時, 你不是會變得很麻煩~所以啊!即使是 LAN 內部,事實上,我們還是需要一部 DNS 系統的。簡單的處理方式有 dnsmasq 等軟體, 不過,我們這邊還是使用功能完整的 bind 軟體來的查!這一章比較難~大家要多花點腦袋喔!

8.1、Domain Name Service (DNS) 系統

雖然對於網際網路世界來說,我們主要是透過 TCP/IP 協定來連網,連網就得要有 IP 位址,IP 位址目前有 IPv4 與 IPv6 兩種版本, 無論如何,有 public IP 位址或透過 NAT 的 private IP 位址之後,就可以連網。問題是,對於人類來說,這種數值方式的主機位置記憶, 還是無法跟文字相比的,文字類型的主機名稱還是比較好記憶!為此,早期人們使用的是 /etc/hosts 來作為主機名稱與 IP 位址的對應! 讓我們來看一看 /etc/hosts 的內容:

[root@master ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
....
192.168.10.254     masterap.vbird    masterap
192.168.20.254     masterlan.vbird   masterlan

[root@master ~]# ping -c 2 masterap.vbird
PING masterap.vbird (192.168.10.254) 56(84) bytes of data.
64 bytes from masterap.vbird (192.168.10.254): icmp_seq=1 ttl=64 time=0.030 ms
....

如上,我們在 master 骨幹系統上面設定過 192.168.10.254 對應到 masterab.vbird 的主機名稱!這樣會比較好記憶!但是,這種方式也只能在 master 骨幹系統上生效!並無法對區域網路內的其他主機有效果~所以,在架設其他服務時,我們偶而會來複製 master:/etc/hosts 這個檔案!只是...這樣效率實在很糟糕!所以,後來才用 DNS 系統統一管理主機名稱與 IP 位址的對應!

要記得,連線到 localhost 時,我們的軟體可能會誤判是 IPv6 (::1) 還是 IPv4 (127.0.0.1) 的位址,因為這兩個 IP 位址對應, 都有寫到 localhost 上!如果單純要測試 127.0.0.1 的話,應該使用 localhost4 單獨對應會比較好!
  • DNS 系統的目的

DNS 原始最主要的目的是『透過主機名稱來找到該伺服器的 IP 位址』,如此一來,人們就可以不用記憶 IP 位址而只須記憶主機名稱即可。假設主機名稱是人名,IP 位址是身份證好了,想想看,你是記憶朋友的名字比較厲害, 還是記憶朋友的身份證比較厲害?戶政事務所要找的是身份證號碼,但是我們要找的是人名,兩者間的對應,對於伺服器來說,就是 DNS 系統了。所以說, DNS 系統就是網際網路的戶政事務所囉。相關的 DNS 目標為:

  • 每一部連上網路的電腦 (無論 server/client),應該都要有一個網路主機名稱 (公開或私有)
  • 上述主機名稱應該要『登錄在某一個 DNS 伺服器底下』
  • 上述伺服器若要讓全世界查詢的到,就需要『註冊在 DNS 系統的架構底下』
  • 最終,任何軟體只要透過詢問 DNS 系統,就會知道某網路電腦的主機名稱對應到的 IP 位址
  • 找到 IP 位址是最重要的目的 (正解)
  • DNS 架構下的主機名稱命名方式 - 了解 FQDN

主機名稱也不是隨便就能命名的!各個國家的名字命名方式都不一樣啊!在台灣,就像您的大名一樣,也不是可以隨便更改的! 至少,你的姓氏基本上就是不能變更對吧!一般來說,人名與地址相關的命名方式有點像這樣:

  • 先分區域,包括台北的、高雄的、台南的
  • 再分姓氏,姓蔡的、姓邱的、姓林的等等
  • 最後才是名字
  • 一般 DNS 的寫法與西方姓名編排比較像,重要的姓氏在後面,名字在前面,所以就會變成:
    • 鳥哥.蔡.台南 (住台南的蔡鳥哥)
    • 鳥哥.邱.台北 (住台北的邱鳥哥)
    • 名字都叫鳥哥,但是因為姓氏與住址不同,而可以找到正確的人名~我們姑且稱之為『完整的人名系統』

網路主機名稱跟上述的系統架構就很像了!你必須要去註冊一個領域名 (姓氏),你的主機名 (名字) 才能夠讓人家找到正確的地方。 就跟樹狀結構一樣,我們總是要找到『根 (root)』之後,才能夠往樹幹、樹枝、葉子等去搜尋到最終的資料!那麼那個『根』是什麼? 我們以台灣教育部的 www 伺服器來說明好了:

  • 所有主機名稱都是從一個『頂層』所延伸出來的,這個頂層也稱為 root,設計上是一個小數點 (.)
  • 台灣有跟頂層註冊一個姓氏,就是 .tw. 這個頂層姓氏
  • 然後透過 .tw. 自己分配台灣自己的下層領域,例如 .gov.tw., .edu.tw. 等等
  • 每個下層姓氏再自己成立所需要的主機名稱,例如 www.edu.tw. 這個教育部的 WWW 伺服器主機名!
  • 從主機名稱到最頂層 (www.edu.tw.) 這個完整的主機名稱,就被稱為 FQDN (Fully Qualified Domain Name)

以上面的例子來說,www.edu.tw. 這個 FQDN 可以拆成兩個部份,一個是主機名稱 (hostname),一個是領域名稱 (domain name)。 這個例子的主機名稱為 www 而領域名稱為 edu.tw.!這一個大架構其實可以視為分散式『資料庫』系統!因為所有的名字都在個別的 DNS 伺服器當中設定,再透過加入 DNS 系統,讓大家都能查詢的到!基本的 DNS 大架構是這樣的:

  • 最頂層 (類似根目錄) 基本上有 13 部系統在管理下層的資料連結
  • 每一個節點只負責自己所管理註冊的網域,其他網域則會去頂層 (類似根目錄) 尋找關聯點再去往下找。

所以最重要的就是『註冊』囉!就像你生出小孩,得要去戶政事務所報戶口一樣啦!只是有所謂的『授權』功能,讓你也能開小型戶政事務所而已。

用過 Linux 的應該都知道『目錄樹 (directory tree)』系統吧!你可以說,每一個目錄就是一個 DNS 伺服器管理的領域,每個檔名就代表一個主機名稱。 要查到某個獨一無二的檔名,要從根目錄 (/) 開始查詢 (絕對路徑檔名)。同理,要查到某個主機名稱,要從最頂層 (.) 開始查詢! 所以,對於 DNS 系統最簡單的認知,就是把它當成目錄樹結構的目錄(領域名稱)與檔名(主機名稱)!而絕對路徑檔名,就是 FQDN 啦!

8.1.1、DNS 的階層架構與 TLD

基本上,DNS 系統與目錄樹結構真的非常類似~DNS 紀錄的主機名稱是從 . 開始查詢領域與主機名稱,而目錄樹的檔名則是從根目錄 / 開始查詢到完整的絕對路徑主機名稱。根據維基百科 domain name space 的圖示重新繪製成為如下圖示,我們來了解一下整體 DNS 的階層架構:

圖 8.1.1、DNS 階層架構的 domain name space 示意圖
圖 8.1.1、DNS 階層架構的 domain name space 示意圖

每個虛線環都是一個區域 (zone),而且這個 zone 必須要跟上層註冊取得委任授權,才是合法的 zone,這個 zone 主要是由名稱伺服器 (name server) 所維護管理。所以,當我們崑山科大的計算機中心想要有自己的名稱伺服器時,就得要跟教育部 edu.tw. 這個 zone 註冊取得委任授權~ 如此,未來 edu.tw. 就不再紀錄 *.ksu.edu.tw. 的主機名稱,而是『導向委任的子區域 (subzone)』去向下查詢! 因為每個 zone 只能紀錄與自己有關的領域名稱,所以,崑山科大必要的 domain 一定含有上層領域名稱,所以就只能是申請 ksu.edu.tw.。

申請合法授權的意義是,當崑山科大自己的伺服器建立一個例如 www.ksu.edu.tw. 這樣的 FQDN 時,在左下角的 zone 由計算機中心自己設定好,無須通知任何人,任何在網際網路上面的電腦,透過從頂層 (.) 開始查詢,就可以找到 ksu.edu.tw. 所紀錄的 www 伺服器的 IP 位址了!

就跟 Linux 的根目錄底下所建立的第一層目錄 (例如 /etc, /home, /usr 等) 是有特殊意義的一樣,最古早的時候,由最源頭的根 (.) 記載的最頂層領域名稱 (Top Level Domain, TLD) 僅有 .com, .org, .edu, .gov, .net, .mil 等, 後來又加入國碼,後來又加入其他洲碼,後來又加入其他名稱等~不過,總的來說,原始定義為:

  • 一般最上層領域名稱 (Generic TLDs, gTLD):例如 .com, .org, .gov 等等
  • 國碼最上層領域名稱 (Country code TLDs, ccTLD):例如 .tw, .uk, .jp, .cn 等

至於最早 root 僅管理六大領域名稱,分別如下:

早期的 6 種 TLD 名稱與內容
領域名稱代表意義
com公司、行號、企業
org組織、機構
edu教育單位
gov 政府單位
net 網路、通訊
mil 軍事單位

台灣 (.tw) 管理的下一層領域名稱,大概也都維持相同的 gTLD 的分類~不過後來 TWNIC 有開放台灣底下的頂層領域名稱申請喔! 因此,鳥哥才有辦法申請到 vbird.tw. 這樣的領域名稱哩!從這個案例我們也可以知道:

  • 主機名稱或新申請的授權領域名稱,必定包含上層領域名稱 (所以 ksu 只能是 ksu.edu.tw.)
  • 申請到合法授權的領域之後,該領域下的主機名稱,一經設定,即可被整個 DNS 系統查詢到 (無須回報上層)

更多詳細的 TLD 領域名稱可以參考底下的網址,台灣除了有『.tw』之外,還有『.台灣』哩!台灣的 TLD 則是由 TWNIC (Taiwan Network Information Center) 所維護。

8.1.2、主機名稱解析流程與遞迴查詢方式(dns resolver, recursive query)

當你的電腦有連上某部主機的需求時,你的軟體 (例如瀏覽器) 會向 DNS 伺服器 (DNS resolver) 要求取得該主機名稱的 IP 位址, 例如我們需要知道 www.vbird.tw 這個主機名稱所代表的 IP 位址時,我們的 resolver 會去跟 DNS 伺服器要求這個主機名稱, 然後 DNS 伺服器會去查詢最頂層 root 的位置,而 root 只會告知下一層,也就是 tw. 的位置,然後再去找 vbird.tw.,如此層層查詢,就可以知道 www.vbird.tw. 是紀錄在 vbird.tw. 的領域下,透過該名稱伺服器紀錄的資訊,我們就可以查詢到 www.vbird.tw. 位址,接下來我們的軟體就可以連上該 IP 位址了!整體流程有點像底下這樣:

圖 8.1.2-1、透過 DNS 系統查詢主機名稱(FQDN)的整體流程示意圖
圖 8.1.2-1、透過 DNS 系統查詢主機名稱(FQDN)的整體流程示意圖

上面的圖示意思是:

  1. 我們的軟體有連網需求,需要連線到 www.vbird.tw,於是向 DNS 伺服器詢問該主機的 IP 位址。
  2. 我們的 DNS 沒有該筆紀錄,但是有 . 的紀錄,所以前去 . 查詢 www.vbird.tw.
  3. root (.) 僅有紀錄 tw. 的伺服器位址紀錄,所以叫 DNS 解析器去 tw. 詢問
  4. tw. 僅有 vbird.tw. 的伺服器位址紀錄,所以叫 DNS 解析器去 vbird.tw. 詢問
  5. vbird.tw. 確實有 www 的資料 (www.vbird.tw.),所以回答 DNS 解析器實際的 IP 位址。
  6. 最後,DNS 解析器會將 www.vbird.tw. 的 IP 位址資料記憶在記憶體中,並且該筆紀錄會有 TTL (time to live) 的存活時間,然後回報我們操作的軟體,軟體就可以開始連到 www.vbird.tw. 了!
  • TTL (time to live) 的意思

上面的流程應該不是很難理解~比較特別的只有 ttl 而已!ttl 主要是由 vbird.tw. 這部 DNS 伺服器所針對 www.vbird.tw. 所設定! 意思是『這筆紀錄建議放置到 DNS 解析器的記憶體存活的時間』,根據這個建議,DNS 解析器 (上圖左側的方塊) 會將這筆紀錄放置到記憶體當中一段時間, 在這段 ttl 存活時間內,如果有其他軟體也需要 www.vbird.tw. 的 IP 位址時,DNS 解析器將會直接把記憶體內的 IP 位址提供出去, 不會重新跑一次 root(.) 開始的流程!這樣可以降低很多的 DNS 查詢流量!

也就是說,當 www.vbird.tw. 這筆紀錄存活在記憶體當中時,查詢流程只需要『 0 --> 1 --> 5 』就可以取得正確的 IP 位址! 不需要 2, 3, 4 的步驟喔!但是對於較為頻繁變動的主機名稱對應的 IP 位址來說,ttl 不要設定太久...否則,剛改過 IP 位址時, 某些電腦會有一段時間無法連到正確的 IP 位址,這是因為他們使用的 DNS 解析器可能還在 ttl 的快取記憶中!所以提供的是舊的 IP 位址喔!

  • 用 whois 簡單檢查合法授權的領域名稱

我們這個章節的目的,主要就是想要架設如上圖的 vbird.tw. 這個領域名稱伺服器 (name server) 的角色!這部主機需要取得合法授權! 怎麼知道一個領域有沒有經過合法的授權呢?我們在指令列模式底下,可以透過 whois 來直接查得註冊的訊息:

[root@master ~]# yum install whois

[root@master ~]# whois [領域名稱]
[root@master ~]# whois vbird.tw
Domain Name: vbird.tw
   Domain Status: ok
   Registrant:
....
   Domain servers in listed order:
      dns.vbird.tw      140.116.44.179
      dns2.vbird.tw     140.116.44.180

Registration Service Provider: HINET
Registration Service URL: http://domain.hinet.net

[root@master ~]# whois www.vbird.tw
網域名稱不合規定

[root@master ~]# whois my.vbird
No whois server is known for this kind of object.

從上面我們可以清楚的知道,whois 指令後面要接的是領域名稱,而不是 FQDN!如果有顯示領域名稱的狀態,那就代表有相關註冊的資料! 那就是一個合法的授權領域名稱。上表後面兩個錯誤的示範,就代表不是領域名稱,或根本沒有該領域名稱的意思!所以,我們就可以在 vbird.tw. 這個領域底下隨便建立屬於鳥哥自己的主機名稱了!

  • 使用 dig 做 +trace 追蹤流程

上頭的示意圖,如果將要 2, 3, 4 當中的每個步驟都抓出來檢測看看,該如何處理?我們可以使用 dig 這個指令加上 +trace 參數來查詢即可! 我們來檢查一下全部的流程看看:

[root@master ~]# dig +trace www.vbird.tw
; <<>> DiG 9.16.23-RH <<>> +trace www.vbird.tw
;; global options: +cmd
.                       16299   IN      NS      f.root-servers.net.
.                       16299   IN      NS      l.root-servers.net.
.                       16299   IN      NS      e.root-servers.net.
......
;; Received 715 bytes from 120.114.100.1#53(120.114.100.1) in 0 ms
# 由 120.114.100.1 查詢到 . 共有多台 NS 的紀錄資料存在!隨機取一個來使用

tw.                     172800  IN      NS      a.dns.tw.
tw.                     172800  IN      NS      g.dns.tw.
......
;; Received 945 bytes from 192.203.230.10#53(e.root-servers.net) in 6 ms
# 由 e.root-servers.net 查詢到 tw. 共有多台 NS 的紀錄,隨機取一個來使用

vbird.tw.               3600    IN      NS      dns.vbird.tw.
vbird.tw.               3600    IN      NS      dns2.vbird.tw.
......
;; Received 623 bytes from 203.73.24.25#53(a.dns.tw) in 6 ms
# 由 a.dns.tw 查詢到 vbird.tw. 有兩部 NS 的紀錄,隨機取一台來使用

www.vbird.tw.           600     IN      CNAME   linux.vbird.tw.
linux.vbird.tw.         600     IN      A       140.116.44.180
vbird.tw.               600     IN      NS      dns2.vbird.tw.
vbird.tw.               600     IN      NS      dns.vbird.tw.
;; Received 174 bytes from 140.116.44.180#53(dns.vbird.tw) in 1 ms
# 由 dns.vbird.tw 找到正確的 IP 位址了!

上面的資料,若搭配我們圖示的步驟,那就可以清楚的看出來:

  1. 從 global 開始到第一個 Received 資料當中,那個 . 的 IP 位址對應是由 120.114.100.1 所提供的。 該 120.114.100.1 就是我們自己設定的 DNS 解析器!
  2. 由前一步驟所得知的 e.root-servers.net 伺服器當當中取得 tw. 的資料
  3. 由前一步驟所得知的 a.dns.tw 伺服器當中取得 vbird.tw. 的資料
  4. 由前一步驟所得知的 dns.vbird.tw 查詢到 www.vbird.tw 為別名,實際名稱為 linux.vbird.tw,並查得 IP 位址定位為 140.116.44.180
  • 查詢方式 query 與 recursive

一般來說,每部 DNS 伺服器,都會回報它自己紀錄的領域資料,亦即 zone 裡面的資訊如果是該 DNS 伺服器自己管的, 那就可以直接提供給用戶端軟體,這就是所謂的查詢 (query)。下圖在右邊的三部 DNS 伺服器提供的查詢方式, 就是 query 的查詢方式,每部伺服器僅提供自己擁有的紀錄值而已,這也是正常 DNS 伺服器應該要提供放行的功能。

而下圖中左側的 DNS 解析器,可以幫我們用戶端軟體去向外查詢,尤其是從 root (.) 開始查起~這個遞迴查詢的動作,就稱為 recursive 查詢。通常 DNS 伺服器不會開放 recursive 查詢!因為容易被亂用,導致 DNS 伺服器所在的頻寬被 DDoS 打到爆炸... 一般來說,DNS 伺服器只會開放內部用戶或者是特定用戶作為遞迴查詢的信任用戶!

圖 8.1.2-2、recursive 與 query 查詢示意圖
圖 8.1.2-2、recursive 與 query 查詢示意圖
  • DNS 伺服器的角色位置

還記得我們在網路參數設定的章節中,都會跟大家說,你的 DNS 伺服器 IP 位址可能需要填寫兩台嘛!為什麼要填寫兩台呢? 現在你知道,我們人類大概都用主機名稱來記憶,而網際網路主要是 TCP/IP,所以能夠將兩者在背景自動轉換的 DNS 系統, 就顯得相當重要!如果沒有 DNS 系統,我們大概所有的網路服務通通不能使用了吧!所以說,如下圖所示,所有的網路電腦都需要設定好名稱解析器的 DNS IP 位址才行!我們使用的是 Network Manager 管理機制,但其實 Linux 記憶名稱解析器的設定檔是在 /etc/resolv.conf 這個檔案內!

圖 8.1.2-3、DNS 角色示意圖
圖 8.1.2-3、DNS 角色示意圖
# 查詢系統內的 DNS 伺服器設定
[root@master ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search vbird
nameserver 120.114.100.1   <==第 1 台,主要的 DNS 遞迴伺服器
nameserver 168.95.1.1      <==第 2 台,次要的 DNS 遞迴伺服器

因為我們底下會設定 DNS 伺服器,所以這裡應該要正名為本機的名稱解析設定!從設定上面就可以看到,事實上我們目前設定兩部名稱解析器, 分別是 120.114.100.1 以及 168.95.1.1。為什麼要設定兩部呢?如圖 8.1.2-3 所示,如果主要的解析器掛掉 (本例當中是 120.114.100.1 那部), 那麼我們的電腦會主動找第二台次要的那部做查詢!所以在圖 8.1.2-3 當中才會有灰色字體的部份~在一切正常的情況下, 次要的 DNS server 是不會被使用的!那是預防第一部 DNS 出問題時的保險動作。要注意的是, 120.114.100.1 以及 168.95.1.1 雖然都是網際網路的 DNS 伺服器,其中 120.114.100.1 是崑山科大內部的 DNS 遞迴伺服器,校外不能使用喔!168.95.1.1 則是中華電信放行的遞迴伺服器。

一般來說,企業內部的 DNS 遞迴伺服器應該是不容易出問題~外部的 DNS 系統也通常防護的很好,所以, 在 /etc/resolv.conf 內的 nameserver 解析器不必設定超過 3 部以上!通常有備援想法所以設定 2 部即可! nameserver 設定太多也沒有意義~

8.1.3、DNS 資料庫類型 (hint/master/slave)

在圖 8.1.1 當中,我們知道每個虛線都是一個區域 (zone),每個 zone 都會代表一個領域 (domain),而這個 zone 的內容, 就是被 DNS 伺服器所維護!那這些紀錄的資料,在 Linux 的 DNS 慣用軟體中,都是使用文字檔作為主機名稱與 IP 位址對應的紀錄格式, 但無論如何,我們還是習慣以 DNS 資料庫來解釋這個 zone 的資料就是了。

  • Zone 的正解與反解

如上所述,DNS 資料庫內的紀錄,其實就是主機名稱與 IP 位址的對應表,但是到底是主機名稱對應到 IP 位址?還是 IP 位址對應到主機名稱呢? 在 DNS 系統當中,原本正常的情況當然是從主機名稱找到 IP 的對應,因此這個方向稱為正解。反過來說,如果資料庫紀錄的資訊是從 IP 位址去對應主機名稱的話,那就稱為這是一個反解的 zone 設定。

  • 在 DNS 伺服器的資料庫設定中,不管是正解還是反解,每個領域的記錄就是一個區域 (zone)
  • 從主機名稱查詢到 IP 的流程稱為:正解
  • 從 IP 反解析到主機名稱的流程稱為:反解

剛剛上面講到的是 zone 的紀錄領域是主機名稱或 IP 位址,如果 zone 要解析的 domain 是主機名稱,那麼得到的答案就是 IP 位址, 因此就是正解。如果 zone 要解析的 domain 是 IP 位址,那麼就會得到主機名稱,因此這時就會是反解。我們等等講反解的 zone 時, 再來詳細說明。

  • 資料庫 Zone 的類型

從圖 8.1.1 當中,我們知道 DNS 伺服器管理的都是一個個的 zone,每個 zone 可能都是一個正解或反解~不過, 當中有個比較特別的存在!我們知道每個 zone 應該都是需要向上層 zone 申請授權,但是...那個 root (.) 要不要申請授權? 此外,我們從前一個小節也知道 DNS 最好有備援,也就是說,同一個 zone 最好有兩部以上的 DNS 伺服器維護較佳! 因為同一個 zone 放在兩個不同的 DNS 上,那麼如果 DNS 內容設定錯誤 (例如手滑寫錯數字),不就非常糟糕! 所以,這時就有所謂的 hint, master, slave 的 zone 的格式。

  • hint: 記錄最頂層 (.) 的領域記錄方式,每部 DNS server 都應該要有這個記錄才對
  • master: 讓管理員手動或透過管理界面『主動』修改主機名稱與 IP 對應的資料庫內容,該資料庫類型就稱為 master。
  • slave: 與 master 同樣可以管理同一個 domain 的資料庫,但其資料庫的來源為直接從 master 的記錄中同步而取得的

基本上,從圖 8.1.2-2 的主機名稱查詢流程來說,你會發現到 DNS 伺服器預設應該都要知道最頂天的 root (.) 這個 zone, root (.) 的 zone 紀錄的資料庫類型,就被稱為 hint,這是每部 DNS 伺服器都應該要設定的才對!而 hint 資料庫類型可以從 internic 網站下載~這個 zone 的資料庫內容,基本上是不會隨意改變的!

除了 root zone 是使用 hint 類型之外,其他的 zone 無論正反解,基本上預設應該都是放置成為 master 的類型! 也就是資料庫檔案內容要建立/刪除/變更,我們管理員得要手動去更改資料才行!但是如前所述,那如果手滑了,導致資料輸入錯誤, 或者是像 root zone 一樣,共有 13 部主機要維護,那得要分別連進 13 部主機去維護資料才行,這怎麼合理?因此就有 slave 資料庫的類型了。

slave 資料庫類型,管理員並不需要手動去修改!只是必須要指定這個 slave 類型的 zone 要跟哪個 master 進行資料庫內容同步即可! 所以,master 維護好新的資料庫紀錄,slave 就會自動跑來更新啦!兩者就同步了!一般來說,當 master 維護過紀錄的資料, 重新啟動服務時,就會主動告知 slave 來更新。而 slave 在預設的設定中,也會定期來跟 master 要求資料庫的同步就是了!

  • Master/Slave 資料庫類型的查詢權重

master/slave 在 DNS 的資料庫類型中,只是定義出紀錄的資訊更新的方式,並不會影響到圖 8.1.2-2 的查詢流程! 在 DNS 的查詢中,獲得的資料總是先搶先贏。例如,root zone 共有 13 部,那你的 DNS 是使用 13 部當中的哪一個? 這當然是透過輪詢機制來的!也就是這 13 部 server 在 DNS 查詢的角度上,其重要性是一模一樣的!這是 DNS 的大架構! 至於 master/slave 則僅是定義出,你的資料維護該如何進行而已!並不是 master 的資料庫類型就比較偉大喔!不要跟圖 8.1.2-3 搞混了!

鳥哥初次接觸 DNS 系統時,就是以為 master DNS 查不到時,才會去查 slave 資料庫類型~所以先跟 ISP 註冊兩部 DNS server 的 IP 位址對應, 然後僅架設一部 DNS 伺服器而已。沒想到要連線到自己的網站時,有時候會卡住,有時候又很順!非常奇怪!使用 IP 位址輸入在網址列, 那就肯定非常順。後來才發現,原來 master / slave 資料庫類型的權重是一模一樣的!這就導致網際網路的電腦,有時候查去不存在的那部 DNS 系統, 就導致找不到 IP 位址紀錄 (因為鳥哥根本沒有架設另一部 DNS 伺服器)!所以這裡才加強說明喔!

8.1.4、資料庫記載的內容 (resource recode, RR)

當我們從 DNS 查詢到資料時,該筆紀錄其實提供非常多的資訊喔!包括該筆 FQDN 的維護者 DNS 伺服器、 實際回應的資料、回應的旗標資訊 (flags) 等等,接下來,我們就來談一談這些回應的訊息~

  • 旗標資訊 (flags)

DNS 回應訊息的旗標資訊,可以在使用 dig 查詢時,從前面幾行表頭資料查到。我們透過目前的環境來檢測一下 www.vibrd.tw 的查詢資訊好了:

# 以目前的 DNS server 查詢 www.vbird.tw 的資訊
[root@master ~]# dig www.vbird.tw
; <<>> DiG 9.16.23-RH <<>> www.vbird.tw
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37144
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 10, ADDITIONAL: 14
....

透過上面的資訊,我們可以知道這筆紀錄的旗標有 qr, rd, ra 三個項目,而底下的資訊分別有一個查詢 (QUERY)、 2 個答案 (ANSWER)、10 個授權 (AUTHORITY)以及 14 個額外資訊 (ADDITIONAL)。好了,那 flags 是什麼意思? 從 wiki 的資料查詢得到相關的旗標意義為:

DNS 查詢資料的 flags 旗標資訊
旗標代碼資訊內容
qr 此回應資訊為查詢 (query) 或回應 (reply)
rd Recursion Desired,用戶端需要進行遞迴查詢的功能
ra Recursion Available,此 DNS 解析器具有遞迴查詢的功能
aa Authoritative Answer,此紀錄為有經授權的回應資訊

大致上比較常看到且需要了解的就是這幾個!我們在上面 dig 查詢中,也可以查詢到 qr, rd, ra 等旗標資訊,問題不大! 但是,那個 aa 旗標怎麼來?最簡單的想法,就是透過檢查具有自己主機名稱紀錄的 DNS 伺服器即可!簡單的說, 你可以找 www.ksu.edu.tw 主機名稱在 120.114.100.1 這部 DNS 伺服器!處理方案如下:

# 120.114.100.1 具有 ksu.edu.tw. 這個 zone 的維護權,所以這樣做:
[root@master ~]# dig www.ksu.edu.tw @120.114.100.1
; <<>> DiG 9.16.23-RH <<>> www.ksu.edu.tw @120.114.100.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52431
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 3
....

因為鳥哥的測試環境是在崑山科大網路環境當中,所以上面的 flags 會出現 ra 的旗標,否則,一般只會出現 qr, aa 與 rd 而已。 因為這筆紀錄是 120.114.100.1 這部 DNS 伺服器本身在維護,所以就顯示出這是授權回應的資訊!

  • 紀錄資源 (Resource Record, RR)

現在,讓我們來看一下 dig 指令回覆的問題 (Question) 與回答 (anwser) 區段的展示訊息:

[root@master ~]# dig www.vbird.tw
...
;; QUESTION SECTION:
;www.vbird.tw.                  IN      A

;; ANSWER SECTION:
www.vbird.tw.           303     IN      CNAME   linux.vbird.tw.
linux.vbird.tw.         303     IN      A       140.116.44.180
...

基本上,紀錄的資訊欄位有點像這樣:

[domain]    [ttl]           IN  [[RR type]  [RR data]]
[待查資料]  [暫存時間(秒)]  IN  [[資源類型] [資源內容]]

以查詢 www.vbird.tw 的結果來說,最終回應的是『linux.vbird.tw. 的存活時間為 303 秒,我們需要的是 A (Address) 的資訊, 其資訊為 140.116.44.180』這樣的意思!所以重點其實是『 A 140.116.44.180 』這一段回應資訊!至於 CNAME 則是別名的意思! 那麼常見的 RR 有哪些呢?大致上有這些:

# 常見 DNS server 管理需要的紀錄資源,假設 zone 為 domain.
[domain]   IN  [[RR type]  [RR data]]
domain.    IN  SOA         管理這個 domain 的七個重要參數 (容後說明) 
domain.    IN  NS          管理 domain. 這個 zone 的 DNS 伺服器主機名稱

# 在 DNS 管理的 zone 規範的主機名稱內,主要的正解紀錄類型
[domain]   IN  [[RR type]  [RR data]]
hostname.  IN  A           hostname. 的 IPv4 的 IP 位址
hostname.  IN  AAAA        hostname. 的 IPv6 的 IP 位址
domain.    IN  MX 權重數   接收 domain. 郵件的伺服器主機名字
hostname.  IN  CNAME       hostname. 為別名,實際名稱為此主機名稱
hostname.  IN  TXT         一串代表 hostname. 的解釋資料,當前環境很常用於 mail server

# 在 DNS 管理的 zone 規範的主機名稱內,主要的反解紀錄類型
[domain]   IN  [[RR type]  [RR data]]
hostname.  IN  PTR         代表 hostname. 這個領域的指向主機名稱,通常 hostname. 是 IP 的領域!
  • SOA: 針對整體 zone 的紀錄需求 (master/slave)

正反解都需要的 RR 項目,主要有 SOA 與 NS 兩者~比較需要注意的是 SOA (start of authority) 的項目! 這個項目內的資訊比較多~而且主要是針對 master/slave 的 DNS 資料庫結構所必須要的設定!如果只有單台 DNS 的設計, 那麼這個項目就比較不要緊~但是...我們都建議要架設兩部以上的 DNS 啦!所以當然兩部 DNS 的同步就很重要!所以, SOA 就一定得要了解才行。我們先來看看 google.com 這個 domain 的設定值好了!

[root@master ~]# dig -t soa google.com
....
;; QUESTION SECTION:
;google.com.            IN  SOA

;; ANSWER SECTION:
google.com.         60  IN  SOA   ns1.google.com. dns-admin.google.com. 584847865 900 900 1800 60
....
# 上面這行後面的特殊字體意義說明,共有 7 大項
# 1. 主要的 (master) DNS 伺服器主機名稱:  ns1.google.com.
# 2. google 的 DNS 管理員 email:          dns-admin@gogle.com.
# 3. 目前資料庫的序號:                    584847865
# 4. slave 資料庫間隔多久會主動去更新:    900 秒
# 5. 若前一個更新失敗,多久重新更新:      900 秒
# 6. 如果持續更新失敗,多久之後就不再更新:1800 秒
# 7. 錯誤查詢紀錄的 TTL 時間:             60 秒

上面的資料我們可以用英文這樣呈現:

domain. ttl IN SOA servername. adm_email. serial refresh retry expire minimum

至於詳細相關資料,可以這樣看:

  • domain.
    SOA 主要是針對整體的 zone,所以待查項目就是這個 zone 的名稱!除了完整撰寫成為 FQDN 之外,也可以使用 @ 代表!你沒看錯, @ 這個符號在 zone file 裡面是有特殊意義的!所以不要隨便使用 @ 喔!
  • servername.
    這個 Domain 的主要 DNS 伺服器 (master server) 之主機名稱
  • adm_email.
    是 DNS 管理員的 email,一般 email 寫法為『 user@host.domain.name. 』這樣,但是因為 @ 代表了 zone 的名稱, 所以 @ 需要用小數點取代~所以整體寫成:『 user.host.domain.name. 』這樣!
  • serial (序號)
    這個 zone file 的版本,數字越大代表越新的版本!一般建議使用『YYYYMMDDXX』(年/月/日/兩位數字) 來取代! 除了好記憶之外,也不會超出最大序號值。這個數字很重要喔!slave 的 zone file 版本若比較舊,那在更新時間到的時候, 就會同步資料~如果 slave 資料庫比較新,那反而就不會同步了!
  • refresh (更新頻率)
    slave 主動向 master 資料庫檢查 zone file 版本的間隔時間。
  • retry (失敗重新嘗試)
    當 slave 更新失敗時,才會觸發 retry 時間!
  • expire (失效時間)
    如果一直持續失敗到這個 expire 的間隔時間,那就不再主動更新,直到 DNS 伺服器重新啟動為止。
  • minimum (錯誤紀錄時間)
    這個數值已經被調整了!目前的定義是,錯誤查詢的資料 (NXDOMAIN) 所快取 (TTL) 在 DNS resolver 上面的時間~你沒看錯~錯誤查詢的資料也會被快取!這真是相當有趣的設定!

在 Linux 的 bind 軟體上面,都有提供預設值給大家參考,可以直接引用預設值即可。不過,最後一個設定值已經修訂成為錯誤紀錄的 TTL 時間, 以前都習慣這個項目設定為 86400 啦!現在可以將這個 TTL 改成跟正常查詢資料的 TTL 即可!否則,錯誤資料 cache 在人家的 DNS 伺服器上太久, 我們自己的更新反而沒被查詢到,這也挺奇怪的!

  • @ 與小數點 (.) 及完整主機名稱 (FQDN) 的關係

首先你要注意的是,在 DNS 設定上,我們通常說的 FQDN 其實是『 hostname.domain. 』這樣的格式!最後那個小數點代表最頂層的 root zone! 然後,所謂的 domain name 通常就是 zone 的名稱!而我們說的資料庫,其實就是個別的 zone file (zone 設定檔)!

在所有 dig 的輸出中,你應該發現了,跟 domain 還是 hostname 有關的名稱,結尾幾乎都會加上小數點 (.), 那個小數點代表的是 root zone 的意思!如果主機名稱沒有加上小數點,那麼 DNS 資料庫就會以為該筆資料為 hostname 而已, 而不是 FQDN,因此會主動加上 domain name!例如,你設定寫上『 www.vbird.tw 』沒有加上小數點,而 zone 假設為 vbird.tw, 那麼該筆設定的 FQDN 會變成『 www.vbird.tw.vbird.tw. 』!所以小數點非常非常重要!

  • NS: 針對整體 zone 的紀錄需求,設定 DNS server

先來看看 google 公司紀錄自己 DNS 的 server 有幾台?

[root@master ~]# dig -t ns google.com
....
;; QUESTION SECTION:
;google.com.                    IN      NS

;; ANSWER SECTION:
google.com.             21600   IN      NS      ns3.google.com.
google.com.             21600   IN      NS      ns1.google.com.
google.com.             21600   IN      NS      ns2.google.com.
google.com.             21600   IN      NS      ns4.google.com.

;; ADDITIONAL SECTION:
ns4.google.com.         7220    IN      A       216.239.38.10
ns4.google.com.         7407    IN      AAAA    2001:4860:4802:38::a

我們跟 DNS 解析器說,需要 google.com 這個 domain 的 DNS 名稱伺服器是誰?答案回答 4 台,亦即有 4 部 google DNS 伺服器! 而其中 ns4.google.com. 的 IPv4 位址為 216.239.38.10 這樣的意思。要注意的是, NS 也是針對整體 zone 的設定! 所以你不能使用『 dig -t ns www.google.com 』這樣的方式去查!因為 www.google.com 只是一個 google.com 這個 zone 底下的一台主機名稱而已。

  • A, AAAA: 僅針對某主機名稱的 IP 位址對應

預設的正解資料就是使用 A 或 AAAA,分別代表 IPv4 與 IPv6 的 IP 位址。因為這是 DNS 最原本的設計需求, 所以不用『 dig -t a www.google.com 』,直接『 dig www.google.com 』即可!太簡單了!就查詢即可!不做說明了!

[root@master ~]# dig www.google.com
;; QUESTION SECTION:
;www.google.com.                        IN      A

;; ANSWER SECTION:
www.google.com.         205     IN      A       142.251.42.228

A 與 AAAA 都是針對單一主機名稱做 IP 位址的對照!但是,你也可以給整個網域的名稱一個 IP 位址喔! 所以,如果你『 dig google.com 』也可以取得一個 IP 位址喔!

  • MX: 針對收信主機名稱的設定 (Mail eXchanger)

MX 是 Mail eXchanger (郵件交換) 的意思,由於郵件主機所傳送的資料就有點像信件,然後你也知道廣告信可以塞在你家的信箱! 因此,有陣子在不受管制的情況下,很多郵件主機就被拿來架設廣告信發信站,造成很多的網路頻寬與垃圾信件的問題。 所以,後來『合法』的郵件主機,『該主機名稱一定會對應一個以上的 MX 紀錄』,否則,該郵件主機名稱所發出的信件, 就會被當成垃圾信件或被直接丟棄。當然 MX 不止這個功能,它還可以讓你的信件不容易遺失~設定多個 MX 並架設多台 mail server, 可以讓你的郵件比較不容易遺失!先來看看 google 的 gmail 設定:

[root@master ~]# dig -t mx gmail.com
;; QUESTION SECTION:
;gmail.com.              IN   MX

;; ANSWER SECTION:
gmail.com.         3284  IN   MX   40 alt4.gmail-smtp-in.l.google.com.
gmail.com.         3284  IN   MX   5 gmail-smtp-in.l.google.com.
gmail.com.         3284  IN   MX   10 alt1.gmail-smtp-in.l.google.com.
gmail.com.         3284  IN   MX   20 alt2.gmail-smtp-in.l.google.com.
gmail.com.         3284  IN   MX   30 alt3.gmail-smtp-in.l.google.com.

MX 後面會加上權重數字,數字越小代表越重要!所以,當有個郵件名稱為 user@gmail.com 寄出之後,這封郵件就會被送到 gmail-smtp-in.l.google.com. 這部郵件主機上~並由此郵件伺服器收下,因為這部主機的 MX 權重數字最小 (5)。 如果該部主機因為某些原因導致你的郵件無法送達,那這封郵件就會送到 alt1.gmail-smtp-in.l.google.com. 上!因為它是後續次小的權重值! 在 gmail 的例子中,我們就知道 gmail 至少架設 5 部郵件伺服器的意思,郵件就不容易不見!

如果你要收信的主機名稱不只是網域,而是有多個主機名稱時,所有要能收信的郵件主機都需要有 MX 喔!舉例來說, 以崑山科大為例,我們通常使用的 email 是: user@mail.ksu.edu.tw~那如果你想讓 user@ksu.edu.tw 也能收信, 這兩個主機名稱 (mail.ksu.edu.tw, ksu.edu.tw) 就都需要有 MX 的設定!當然你可以設定在同一部郵件主機來接收!

[root@master ~]# dig -t mx ksu.edu.tw
;; ANSWER SECTION:
ksu.edu.tw.             3600    IN      MX      8 mx01.ksu.edu.tw.

[root@master ~]# dig -t mx mail.ksu.edu.tw
;; ANSWER SECTION:
mail.ksu.edu.tw.        3600    IN      MX      8 mx01.ksu.edu.tw.

你會發現兩者都寄到同一台郵件主機上喔!不過需要注意的是,MX 後面接的主機名稱,需要有對應的 A 或 AAAA 的 IP 位址紀錄才行! 不可以是 CNAME 喔!另外,為了加強郵件伺服器的合法性,目前還多了很多的紀錄資訊喔!未來談到 mail server 時, 我們再來繼續聊聊~

  • CNAME: 作為別名指向正確的主機名稱

有時候你不想要針對某個主機名稱設定 A 的標誌,而是想透過另外一部主機名稱的 A 來規範這個新主機名稱時,可以使用別名 (CNAME) 的設定喔!舉例來說,在台灣,查看新聞的時候,還是很可能會前往 tw.yahoo.com 查看的!這部主機的 IP 位址為何呢?

[root@master ~]# dig tw.yahoo.com
;; QUESTION SECTION:
;tw.yahoo.com.                  IN      A

;; ANSWER SECTION:
tw.yahoo.com.           26      IN      CNAME   fp-ycpi.g03.yahoodns.net.
fp-ycpi.g03.yahoodns.net. 47    IN      A       180.222.106.12
fp-ycpi.g03.yahoodns.net. 47    IN      A       180.222.109.251
fp-ycpi.g03.yahoodns.net. 47    IN      A       180.222.109.252
fp-ycpi.g03.yahoodns.net. 47    IN      A       180.222.106.11

我們可以看到,查詢是 tw.yahoo.com. 的 A,但是回應則是顯示 CNAME 到 fp-ycpi.g03.yahoodns.net. 上頭, 然後該主機有 4 個 IP 位址~CNAME 有點像 Linux 的符號連結啦!未來只要改了 fp-ycpi.g03.yahoodns.net. 的設定即可, 不用理會 tw.yahoo.com.!因為實際上用的是 fp-ycpi.g03.yahoodns.net. 的 A 紀錄就是了。

  • PTR: 由 IP 位址找出主機名稱的反解指向 (Pointer)

由 IP 位址反向找出主機名稱,使用的就是 PTR 這個紀錄~但是要查反解時,我們使用的參數是 dig -x 喔! 讓我們來瞧一瞧,找到的第一個 google.com 的 IP 位址反向追蹤會變怎樣?

# 先由短輸出資訊來查詢 google.com 的 IP 位址
[root@master ~]# dig +short google.com
142.251.42.238

# 再來查一下上面的 IP 位址對應的主機名稱又是什麼?
[root@master ~]# dig -x 142.251.42.238
;; QUESTION SECTION:
;238.42.251.142.in-addr.arpa.   IN      PTR

;; ANSWER SECTION:
238.42.251.142.in-addr.arpa. 45321 IN   PTR     tsa01s11-in-f14.1e100.net.

我們可以發現,詢問的資訊從 142.251.42.238 變成了『 238.42.251.142.in-addr.arpa. 』,裡面有兩個重點, 第一個是 IP 位址反過來寫了 (238.42.251.142),第二個是最終的名稱會加上『 in-addr.arpa. 』 。我們知道 IP 位址的記載,是從左側到右側,所以 class A/B/C 是從左側第一組 10 進位去開始查詢的!但是 DNS 主機名稱則是西式名字的寫法,也就是右側才是代表家族名稱~所以 DNS 是從右側開始查詢。為了讓 IP 位址的查詢符合 DNS 右側開始查詢的方式,所以 IP 位址需要反過來寫~而且為了讓 DNS 知道這其實是 IP 位址的領域 (反解),所以需要加上特殊的『 in-addr.arpa. 』這樣的領域結尾!

8.2、DNS 系統規劃設定與安裝測試 bind 軟體

要開始來架設 DNS 伺服器之前,得要想想我們內部的系統該如何規劃!另外,這部 DNS 伺服器的硬體/作業系統/網路環境/軟體等等, 也應該要來好好的處理一下才行!在網際網路上,bind (Berkeley Internet Name Domain, BIND) 這套達成 DNS 功能的軟體是挺常使用的, 這也是我們預設的 DNS 軟體!所以,讓我們開始來學習學習。

8.2.1、DNS 系統規劃與設定

假設我們已經向上層領域註冊了兩台 DNS 伺服器,然後未來這兩部 DNS 伺服器還需要對外提供服務!所以,這兩部系統應該要放置到 DMZ 的網域中。基本上 DNS 伺服器不應該放置在同一個 IP 位址網域當中的,不過我們這邊只是做個模擬練習的環境, 所以暫時將這兩部系統放置在一起喔!這點要多多留意才好!

  • 處理硬體設定檔 (XML)、硬碟檔 (.img) 等資訊

由於複製硬碟資料時,來源檔案應該要在乾淨 (clean) 的狀態下較佳!因此,我們先將 server_raw 的虛擬機器先關閉起來再說。 關閉完成之後,再來處理 XML 的複製以及 .img 的複製即可。現在,先登入我們的母機器 (cloud.vbird) 系統, 然後進行整體流程大概如下所示:

# 1. 確認在 KVM 母機器上面,然後確認一下,如果 server_raw 虛擬機存在,就關閉它
[root@cloud ~]# hostname
cloud.vbird
# 請確定是在 KVM 母機器上頭!否則會找不到相關的映像檔與 XML 檔!

[root@cloud ~]# virsh list
 Id   Name         State
----------------------------
 1    master       running
 2    client_raw   running
 3    server_raw   running
# 看起來 server_raw 是存在的,所以,先來關閉它!

[root@cloud ~]# virsh shutdown server_raw
Domain 'server_raw' is being shutdown
# 需要靜待幾秒鐘,等待 server_raw 的關閉!

# 2. 複製兩個硬碟檔案,分別給 DNS master/slave 使用
[root@cloud ~]# cd /kvm/img
[root@cloud img]# cp server_raw.img server_dns_master.img
[root@cloud img]# cp server_raw.img server_dns_slave.img

# 3. 處理 XML 硬體設定檔
[root@cloud img]# cd /kvm/xml
[root@cloud xml]# cp server_raw.xml server_dns_master.xml
[root@cloud xml]# cp server_raw.xml server_dns_slave.xml

[root@cloud xml]# vim server_dns_master.xml
  <name>server_dns_master</name>
    <loader readonly="yes" type="pflash" secure="no">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
    <nvram>/kvm/xml/server_dns_master.uefi.fd</nvram>
      <source file="/kvm/img/server_dns_master.img"/>
      <mac address="52:54:00:00:30:c1"/>
    <graphics type="vnc" port="5931" listen="0.0.0.0" passwd="rocky9">

[root@cloud xml]# vim server_dns_slave.xml
  <name>server_dns_slave</name>
    <loader readonly="yes" type="pflash" secure="no">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
    <nvram>/kvm/xml/server_dns_slave.uefi.fd</nvram>
      <source file="/kvm/img/server_dns_slave.img"/>
      <mac address="52:54:00:00:30:c2"/>
    <graphics type="vnc" port="5932" listen="0.0.0.0" passwd="rocky9">

# 4. 之後就啟動它吧!
[root@cloud xml]# virsh create server_dns_master.xml
[root@cloud xml]# virsh create server_dns_slave.xml
[root@cloud xml]# virsh list
 Id   Name                State
-----------------------------------
 1    master              running
 2    client_raw          running
 13   server_dns_master   running
 15   server_dns_slave    running

[root@cloud xml]# netstat -tlunp | egrep '^Pro|qemu'
Proto Recv-Q Send-Q Local Address   Foreign Address  State   PID/Program name
tcp        0      0 0.0.0.0:5909    0.0.0.0:*        LISTEN  786802/qemu-kvm
tcp        0      0 0.0.0.0:5920    0.0.0.0:*        LISTEN  786920/qemu-kvm
tcp        0      0 0.0.0.0:5932    0.0.0.0:*        LISTEN  985321/qemu-kvm
tcp        0      0 0.0.0.0:5931    0.0.0.0:*        LISTEN  984148/qemu-kvm
  • 網路佈建規劃

如前所述,我們的兩部 DNS 系統未來可能會提供給 internet 使用,所以理論上應該要放置到可以被外部網路存取的 DMZ 環境中。 另外,為了區分網路來源是 AP、內部網路還是外部的 DMZ 網路,因此我們預計給予三個 zone,分別是 ap.vbird, lan.vbird 及 server.vbird 共三個。當然啦,每個正解的 zone 我們預計都給予一個反解的 zone!相關的圖示如下所示。

圖 8.2.1、DNS 系統的網路佈建示意圖
圖 8.2.1、DNS 系統的網路佈建示意圖

我們已經建立了 master DNS 與 slave DNS 的系統,現在,請使用 VNC 連線到這兩部系統上,分別使用如下的設定來處理各自的網路環境。 為什麼要使用 VNC 呢?我們同時啟動兩部複製來自 server_raw 的硬體系統,所以這兩部硬體預設的主機名稱都是 server001,而且網路也都設定為手動, 所以目前就會 IP 位址衝突啦~建議就是使用 VNC 連線到主系統來處理,比較可以忽略網路 IP 位址變化造成的問題!所以,底下的行為, 請通通在 VNC 的本機終端機環境下處理喔!

# 1. 在 Master DNS 上面處理底下的行為:
[root@server001 ~]# hostnamectl hostname dns1.server.vbird
[root@dns1 ~]# nmcli connection modify enp1s0 ipv4.method manual ipv4.addresses 192.168.30.211/24 \
> ipv4.gateway 192.168.30.254 ipv4.dns 120.114.100.1,168.95.1.1
[root@dns1 ~]# nmcli connection up enp1s0
[root@dns1 ~]# dig +short www.google.com
172.217.163.36
# 最終有回應資訊,應該就是達到網路正常了!

# 2. 在 Slave DNS 上面處理底下的行為:
[root@server001 ~]# hostnamectl hostname dns2.server.vbird
[root@dns2 ~]# nmcli connection modify enp1s0 ipv4.method manual ipv4.addresses 192.168.30.212/24 \
> ipv4.gateway 192.168.30.254 ipv4.dns 120.114.100.1,168.95.1.1
[root@dns2 ~]# nmcli connection up enp1s0
[root@dns2 ~]# dig +short www.vbird.tw
linux.vbird.tw.
140.116.44.180
# 這次我們來測試另一部主機~可以看到 www.vbird.tw 也有相關的 IP 位址!

將兩部 DNS 的網路搞定之後,再來就準備架設 DNS 伺服器了!

8.2.2、bind 軟體安裝

bind 是達成 DNS 服務的一個軟體,主要是由柏克萊大學所開發的套件 (Berkeley Internet Name Domain, BIND)。 這個軟體雖然功能相當完整,不過,過去有許多資安方面的問題,因此,運作時,建議將此軟體的功能鎖住於 /var/named/chroot/ 目錄下! 為了方便設定,bind 同時提供了 bind-chroot 的軟體,可以讓管理員快速的設定 chroot 的功能。

bind 提供了名為 named 的軟體,同時提供了 named.service 的服務。而 bind-chroot 則提供了 named-chroot.service 的服務。 基本上, named.service 及 named-chroot.service 並沒有什麼太大的差異,只是 named-chroot 主動將服務關在 /var/named/chroot 而已。 而由於 bind-chroot 軟體已經幫我們做好了目錄的對照,所以我們可以依據正常的 named 設定來處理設定檔,只要啟動的服務是 named-chroot 就好了!相當方便!

  • 在 dns1 及 dns2 安裝 bind, bind-chroot, bind-utils 軟體

直接安裝好我們需要的軟體,底下的動作請分別在兩部主機上面進行!

# 1. 先進行全系統的更新
[root@dns1 ~]# yum -y update

# 2. 開始安裝 DNS 所需要的軟體
[root@dns1 ~]# yum -y install bind bind-chroot bind-utils

# 3. 查看主要設定檔:
[root@dns1 ~]# ll -d /etc/named.conf /var/named/*
-rw-r-----. 1 root  named 1722 Nov 11 10:55 /etc/named.conf              <==主設定檔
drwxr-x---. 8 root  named   73 Nov 27 20:37 /var/named/chroot
drwxrwx---. 2 named named    6 Nov 11 10:55 /var/named/data
drwxrwx---. 2 named named    6 Nov 11 10:55 /var/named/dynamic
-rw-r-----. 1 root  named 2253 Nov 11 10:55 /var/named/named.ca          <==root zone file
-rw-r-----. 1 root  named  152 Nov 11 10:55 /var/named/named.empty
-rw-r-----. 1 root  named  152 Nov 11 10:55 /var/named/named.localhost   <==正解範例檔
-rw-r-----. 1 root  named  168 Nov 11 10:55 /var/named/named.loopback    <==反解範例檔
drwxrwx---. 2 named named    6 Nov 11 10:55 /var/named/slaves
# 上面的動作,請在 dns2 上面一樣做一次!

這樣就安裝妥當了!但是預設的 named-chroot 這個 DNS 服務,僅提供如下的功能:

  • 僅監聽 DNS 要求在 127.0.0.1 這個界面
  • 僅允許本機 (127.0.0.1) 的資料查詢要求 (query)
  • 針對整個 Internet 放行 DNS 代理查詢 (recursion) 的功能
  • 載入了 . 的 root zone file
  • 載入了文件上要求載入的 zone

所以,準備來修改修改主設定檔~

8.2.3、caching only DNS 伺服器建置/測試

因為 named 這個服務預設只給本機自己使用,亦即無法當成外部的遞迴 DNS 伺服器!同時也不給外部查詢 (query)! 只開放自己查詢而已。這樣根本無法作為內部 DNS Server 使用,因此我們需要來修改一下!雖然圖 8.2.1 已經規劃好了所有的 zone, 不過,我們這邊先想要了解的是,DNS 作為快取功能的情況下,只有 root zone file 時,該如何設計?預計這個內部 DNS server 需要達成的目的是:

  • 設定 mynet 的 ACL,加入 192.168.10.0/24, 192.168.20.0/24, 192.168.30.0/24 這三段 IP 位址
  • DNS 監聽在本機的所有網路界面
  • 允許全部 (any) 來源的查詢 (query)
  • 僅允許本機與 mynet 的來源幫忙做遞迴 (allow-recursion)
  • (option):使用上層 DNS 伺服器作為轉遞 (forwarders) 伺服器來源
  • 設定 /etc/named.conf 主設定檔,並啟動 named-chroot

要達成上述的功能,需要將主設定檔做個修訂~我們來測試看看:

[root@dns1 ~]# vim /etc/named.conf
// 這個是註解
/* 這個也是註解!但是需要前後包夾 */

acl mynet { 192.168.10.0/24; 192.168.20.0/24; 192.168.30.0/24; 127.0.0.0/8; }
// 列出一個別名 (acl) 為 mynet,代表的是上述的四個網段 ( 連同 localhost )
options {
        listen-on port 53 { any; };     // 監聽在所有網路界面
        listen-on-v6 port 53 { any; };  // 監聽在所有 IPv6 界面
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        secroots-file   "/var/named/data/named.secroots";
        recursing-file  "/var/named/data/named.recursing";
        allow-query     { any; };       // 允許所有來源的查詢

        // recursion yes;
        allow-recursion { mynet; };     // 刪除全部遞迴,只讓本地端主機遞迴

        dnssec-validation yes;
        managed-keys-directory "/var/named/dynamic";
        geoip-directory "/usr/share/GeoIP";
        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
        include "/etc/crypto-policies/back-ends/bind.config";
};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

// zone 的設定值!非常重要!需要搭配 8.1.3 的說明查閱
zone "." IN {               // 這個 zone 針對的是 root file (.)
        type hint;          // 類型是 hint 資料庫
        file "named.ca";    // zone file 檔名為 /var/named/named.ca
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

acl 是一個 access control list 的設計,可以將複雜的/重複出現的資料用簡單的文字代替!所以上述的資料中, 我們用 acl 取名一個 mynet 作為 4 段網域的代表名稱!any 代表的是所有的網域!allow-query 指的是可以查詢的來源, allow-recursion 則是能夠遞迴查詢的來源!相關的 query/recursion 查詢,請查閱 8.1.2 的說明。 基本上不用做什麼奇怪的設定,大部分沿用設定檔內容即可。接下來檢查一下設定檔,如果沒有問題,就直接啟動 named-chroot 服務!

# 使用 named-checkconf 檢查 /etc/named.conf 設定檔是否有問題
[root@dns1 ~]# named-checkconf
/etc/named.conf:10: missing ';' before 'options'
# 如上所示,設定檔第 10 行在 options 設定之前,似乎少了分號!鳥哥故意留了個錯誤在上面!
# 請自行修改成正確的資料喔!修改完成之後再次 named-checkconf,一直到沒出現問題為止!

# 啟動 named-chroot 服務,並且查閱一下服務狀態
[root@dns1 ~]# systemctl --now enable named-chroot.service
[root@dns1 ~]# systemctl status named-chroot
● named-chroot.service - Berkeley Internet Name Domain (DNS)
     Loaded: loaded (/usr/lib/systemd/system/named-chroot.service; enabled; preset: disabled)
     Active: active (running) since Mon 2023-11-27 21:25:08 CST; 41s ago
     ....

Nov 27 21:25:08 dns1.server.vbird named[4534]: all zones loaded
Nov 27 21:25:08 dns1.server.vbird named[4534]: running
Nov 27 21:25:08 dns1.server.vbird systemd[1]: Started Berkeley Internet Name Domain (DNS).
Nov 27 21:25:09 dns1.server.vbird named[4534]: resolver priming query complete
Nov 27 21:25:09 dns1.server.vbird named[4534]: managed-keys-zone: Initializing automatic ..

[root@dns1 ~]# tail /var/log/messages

基本上,這樣就設定好 caching only 的 DNS 伺服器!要注意的是,在預設的情況下,named 的登錄檔資訊是紀錄到 /var/log/messages 這個檔案內,所以,如果重新啟動了 named-chroot 後,請使用 tail 或 less 等指令去觀察一下 /var/log/messages 喔! 非常重要!不要忘記!上述的動作完成後,請在 dns2.server.vbird 系統上實做!

  • 放行防火牆的 dns 存取功能

這部系統僅能提供 ssh 以及 dns 而已,其他的服務先關掉~

[root@dns1 ~]# firewall-cmd --list-services
cockpit dhcpv6-client ftp http https ssh

[root@dns1 ~]# firewall-cmd --remove-service={cockpit,dhcpv6-client,ftp,http,https}
[root@dns1 ~]# firewall-cmd --add-service=dns
[root@dns1 ~]# firewall-cmd --list-services
dns ssh

[root@dns1 ~]# firewall-cmd --runtime-to-permanent

很快的使用 firewalld 將防火牆搞定~設計完畢,也請針對 dns2.server.vbird 進行完整的設定!

  • 開始測試 DNS

現在,請開始測試這部 DNS 是否正常運作了!要注意的是,因為我們還是往外查詢,所以,查詢時可能會比較慢! 而且查詢的資料實際上是會快取的!測試看看先:

# 1. 在骨幹系統上面測試一下:
[root@master ~]# dig www.vbird.tw @192.168.30.211
....
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;www.vbird.tw.                  IN      A

;; ANSWER SECTION:
www.vbird.tw.           600     IN      CNAME   linux.vbird.tw.
linux.vbird.tw.         600     IN      A       140.116.44.180

;; Query time: 1516 msec
;; SERVER: 192.168.30.211#53(192.168.30.211)
# 確定有回應資料!我們的 DNS 系統實際活起來了!

# 2. 自己的 dns1 系統,使用自己的服務來測試看看:
[root@dns1 ~]# nmcli connection modify enp1s0 ipv4.dns 127.0.0.1
[root@dns1 ~]# nmcli connection up enp1s0
[root@dns1 ~]# dig www.vbird.tw
...
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;www.vbird.tw.                  IN      A

;; ANSWER SECTION:
www.vbird.tw.           384     IN      CNAME   linux.vbird.tw.
linux.vbird.tw.         384     IN      A       140.116.44.180

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)

如果對於自己的 DNS server 有信心的話,那麼所有內部的系統通通用這部伺服器來作為 DNS 查詢! 此時可以直接修改網路設定值,這樣就能使用共同的 DNS 服務了!也請將 dns2 的 DNS 查詢改為 127.0.0.1 喔!

  • 使用 forwarders 設定

你可能會發現,怎麼我們的 DNS 伺服器查詢的速度有點慢?這是因為內部系統電腦數量不夠多,所以我們的 DNS 每次都要從 root (.) 去查詢! 連去國外查詢速度確實很慢啊!那,我們能不能借用上層 DNS 伺服器?因為 DNS 伺服器越多人用,使用到相同的主機名稱查詢越可能重複, 所有主機名稱就越可能快取在 DNS 系統上!所以,使用上層 DNS 作為代查手段,應該是比較合理的啦!在鳥哥的場域,我們上層 DNS 是 120.114.100.1 這一台,所以我可以這樣做:

# 1. 修改主設定檔
[root@dns1 ~]# vim /etc/named.conf
        // recursion yes;
        allow-recursion { mynet; };
        forwarders {
                120.114.100.1;
                120.114.150.1;
        };

[root@dns1 ~]# named-checkconf
[root@dns1 ~]# systemctl restart named-chroot

再次 dig 查詢相關資料之後,你會發現,我們的查詢速度會變快喔!請在 dns2 機器上面也這麼處理!

8.3、zone file 的設定

我們從上面的測試,可以知道 zone 的定義是在 /etc/named.conf 主設定檔內,同時主設定檔也會宣佈該 zone 的 zone file 完整檔名! 所以,整體來說,主要還是需要 /etc/named.conf 啦!而我們從前幾個小節也知道,zone 的類型有 hint (.)、master 與 slave。 hint 就是單純的 root zone 設定,資料可以使用套件提供的,也可以自行從 internic 網站取得~手動自己改資料的 zone file 稱為 master 格式! 自動更新的則是在 slave DNS server 上的設定!底下我們就分別來談一談!

8.3.1、正解檔的主設定與 zone file 設定方式 (type master)

我們從圖 8.2.1 了解正解檔共有 3 個 zone,底下鳥哥只進行 client*.lan.vbird 這個 zone 的實做, 其他三個 zone 的實做是相同的處理方式~所以我們就不浪費篇幅~只是大家真的要實際實做出來才行喔!

  • zone 的設定與 zone file 檔名設計

我們先做一個名為 lan.vbird 的 zone,假設 zone file 的名稱就設定為 /var/named/named.lan.vbird,一般來說, zone file 常以 named 做開頭,後續則接 zone 的名字即可!那麼這個 dns1 的設定中,要能允許 dns2 的整體 zone 傳輸需求, 因此, named.conf 的設定可以寫成這樣:

[root@dns1 ~]# vim /etc/named.conf
zone "." IN {
        type hint;
        file "named.ca";
};
zone "lan.vbird" IN {
        type master;
        file "named.lan.vbird";
        allow-transfer { 192.168.30.212; };
};

[root@dns1 ~]# named-checkconf
  • zone file 內容設定

確定沒問題之後,再來則是前往 /var/named 去建立一個 named.lan.vbird 的檔案,zone file 的內容格式需要注意的有:

zone file 內容格式
字元意義
一定從行首開始 所有設定資料一定要從行首開始,前面不可有空白字元。若有空白字元,代表延續前一個 domain 的意思~非常重要~
@ 如前所述,這個符號代表 zone 的意思!zone 的名稱則是設定於 named.conf 當中!若為反解領域, 則可能成為類似 20.168.192.in-addr.arpa. 這樣的名稱!
. 這個點 (.) 很重要!因為他代表一個完整主機名稱 (FQDN) 而不是僅有 hostname 而已。
; 代表註解符號~似乎 # 也是註解~兩個符號都能使用

接下來,就讓我們實際來設計一下相關的設定值:

# 1. 建立 named.lan.vbird 的方式,包括權限與內容
[root@dns1 ~]# cd /var/named
[root@dns1 named]# cp -a named.localhost named.lan.vbird
[root@dns1 named]# chown root.named named.lan.vbird
[root@dns1 named]# chmod 640 named.lan.vbird
[root@dns1 named]# vim named.lan.vbird
; 這個 zone file 的 zone 預設為 lan.vbird.  @ 就是 lan.vbird.
$TTL 600                                ; 統一建立全部紀錄的 TTL 時間
@       IN SOA  dns1.lan.vbird. adm.mail.server.vbird. (
                        2023112801      ; serial
                        3H              ; refresh
                        15M             ; retry
                        1D              ; expire
                        600 )           ; minimum
; 這個 zone 的 DNS server 指定
@       IN NS   dns1.lan.vbird.
@       IN NS   dns2.lan.vbird.
dns1    IN A    192.168.30.211
dns2    IN A    192.168.30.212
; 其他用戶端的設定!主要是分給內網用的,共計 100 台!可用 gogozone.sh 建立
masterlan       IN A    192.168.30.254
client001       IN A    192.168.20.1
client002       IN A    192.168.20.2
...

# 2. 可用底下的腳本,修改之後,即可大量的處理相似資料的輸出
[root@dns1 named]# vim gogozone.sh
#!/bin/bash
for i in $( seq -w 1 100)
do
        ip=$( echo $i | sed 's/^0*//g' )
        echo -e "client${i}\tIN A\t192.168.20.${ip}"
done

[root@dns1 named]# sh gogozone.sh >> named.lan.vbird

# 3. 記得要檢查看看這個 zone 的設定是否正確!
[root@dns1 named]# named-checkzone {zone} {zone filename}
[root@dns1 named]# named-checkzone lan.vbird named.lan.vbird
zone lan.vbird/IN: loaded serial 2023112801
OK
  • 重新啟動服務與測試

如果上面兩個測試指令 named-checkconf 與 named-checkzone 都執行過無誤,那麼你的 named-chroot 應該就能重新載入設定了!

[root@dns1 named]# systemctl restart named-chroot

如果一切順利,那麼我們就可以開始檢查設定是否正確!請注意,所有你加入 zone file 的設定,全部都要測試!因為資料量太多, 所以鳥哥底下使用 +short 的方法來檢測,注意輸出的資訊是否正確喔!我們設定的項目有 SOA, NS, A 等三個主項目!

[root@dns1 named]# dig +short -t soa lan.vbird
dns1.lan.vbird. adm.mail.server.vbird. 2023112801 10800 900 86400 600

[root@dns1 named]# dig +short -t ns lan.vbird
dns2.lan.vbird.
dns1.lan.vbird.

[root@dns1 named]# dig +short dns1.lan.vbird
192.168.30.211
[root@dns1 named]# dig +short dns2.lan.vbird
192.168.30.212
[root@dns1 named]# dig +short masterlan.lan.vbird
192.168.20.254
[root@dns1 named]# dig +short client001.lan.vbird
192.168.20.1
[root@dns1 named]# dig +short client100.lan.vbird
192.168.20.100

這樣看起來大致上都有出現正確的資料!也就完成一個正解的 zone 處理了!

  • 設定與測試 ap.vbird 正解

請依據前面的設定流程,完成 ap.vbird 這個 zone 的設定 (查閱圖示 8.2.1),假設 zone file 檔名為 /var/named/named.ap.vbird, 這邊我們不浪費篇幅,請大家由剛剛的 named.lan.vbird 以及 gogozone.sh 的運作,同樣建立 100 個主機的 A 對應。 最終檢測結果會是這樣:

[root@dns1 ~]# dig +short -t soa ap.vbird
dns1.ap.vbird. adm.mail.server.vbird. 2023112801 10800 900 86400 600

[root@dns1 ~]# dig +short -t ns ap.vbird
dns2.ap.vbird.
dns1.ap.vbird.

[root@dns1 ~]# dig +short dns1.ap.vbird
192.168.30.211
[root@dns1 ~]# dig +short dns2.ap.vbird
192.168.30.212
[root@dns1 ~]# dig +short masterap.ap.vbird
192.168.10.254
[root@dns1 ~]# dig +short ap001.ap.vbird
192.168.10.1
[root@dns1 ~]# dig +short ap100.ap.vbird
192.168.10.100

注意,一定要查詢正確喔!不可以有失敗或錯誤的情況發生!

  • 設定與測試 server.vbird 正解

請依據前面的設定流程,完成 server.vbird 這個 zone 的設定 (查閱圖示 8.2.1),假設 zone file 檔名為 /var/named/named.server.vbird, 因為這個地方的設定主要都是固定 IP 位址的方式,所以不需要有太多的預設主機名稱,所以只建立 10 個主機的 A 對應即可! 最終檢測結果會是這樣:

[root@dns1 ~]# dig +short -t soa server.vbird
dns1.server.vbird. adm.mail.server.vbird. 2023112801 10800 900 86400 600

[root@dns1 ~]# dig +short -t ns server.vbird
dns2.server.vbird.
dns1.server.vbird.

[root@dns1 ~]# dig +short dns1.server.vbird
192.168.30.211
[root@dns1 ~]# dig +short dns2.server.vbird
192.168.30.212
[root@dns1 ~]# dig +short masterdmz.server.vbird
192.168.30.254
[root@dns1 ~]# dig +short server01.server.vbird
192.168.30.1
[root@dns1 ~]# dig +short server10.server.vbird
192.168.30.10

注意,一定要查詢正確喔!不可以有失敗或錯誤的情況發生!

8.3.2、slave 向 master 要求資料庫同步的設定方式 (type slave)

Slave 的同步更新挺簡單的!比較需要注意的是,通常我們的 slave 向 master 要資料之後,會將資料自動複寫到 /var/named/slaves/ 目錄下! 所以我們不需要重新撰寫 zone file~只要將 /etc/named.conf 設定好即可!現在,請在 dns2 上面如此設定:

# 1. 在 slave DNS (dns2) 設定好 /etc/named.conf
[root@dns2 ~]# vim /etc/named.conf
zone "." IN {
        type hint;
        file "named.ca";
};
zone "lan.vbird" IN {
        type slave;
        file "slaves/named.lan.vbird";
        masters { 192.168.30.211; };
};
zone "ap.vbird" IN {
        type slave;
        file "slaves/named.ap.vbird";
        masters { 192.168.30.211; };
};
zone "server.vbird" IN {
        type slave;
        file "slaves/named.server.vbird";
        masters { 192.168.30.211; };
};

# 2. 重新啟動 named-chroot,並查看輸出訊息
[root@dns2 ~]# systemctl restart named-chroot
[root@dns2 ~]# tail -n 100 /var/log/messages| grep 'lan.vbird'
Nov 28 17:01:30 dns2 named[5842]: zone lan.vbird/IN: Transfer started.
Nov 28 17:01:30 dns2 named[5842]: transfer of 'lan.vbird/IN' from 192.168.30.211#53: 
                                  connected using 192.168.30.212#40163
Nov 28 17:01:30 dns2 named[5842]: zone lan.vbird/IN: transferred serial 2023112801
Nov 28 17:01:30 dns2 named[5842]: transfer of 'lan.vbird/IN' from 192.168.30.211#53: 
                                  Transfer status: success
Nov 28 17:01:30 dns2 named[5842]: transfer of 'lan.vbird/IN' from 192.168.30.211#53: 
                                  Transfer completed: 1 messages, 107 records, 2816 bytes, 
                                  0.001 secs (2816000 bytes/sec) (serial 2023112801)
Nov 28 17:01:30 dns2 named[5842]: zone lan.vbird/IN: sending notifies (serial 2023112801)

# 3. 看看 zone file 有沒有被自動的建立起來
[root@dns2 ~]# ll /var/named/slaves/
-rw-r--r--. 1 named named 4505 Nov 28 17:01 named.ap.vbird
-rw-r--r--. 1 named named 5014 Nov 28 17:01 named.lan.vbird
-rw-r--r--. 1 named named  828 Nov 28 17:01 named.server.vbird

只要 zone file 有自動被建立起來,那就應該是正常運作了!只是,這個 slave 的資料格式為 named 的資料庫格式, 並不是我們習慣的純文字模式喔!所以,如果想要以純文字模式來觀察時,就得要透過某些特別的指令來觀察了:

[root@dns2 ~]# named-compilezone -f raw -o - server.vbird /var/named/slaves/named.server.vbird
zone server.vbird/IN: loaded serial 2023112801
server.vbird.             600 IN SOA  dns1.server.vbird. adm.mail.server.vbird. 2023112801 10800 900 86400 600
server.vbird.             600 IN NS   dns1.server.vbird.
server.vbird.             600 IN NS   dns2.server.vbird.
dns1.server.vbird.        600 IN A    192.168.30.211
dns2.server.vbird.        600 IN A    192.168.30.212
masterdmz.server.vbird.   600 IN A    192.168.30.254
server01.server.vbird.    600 IN A    192.168.30.1
.....
OK

如果夠小心翼翼的話,那麼在 dns2 同樣使用 dig 的方式,一個一個主機名稱與設定去檢查!確認 OK 才好喔!

8.3.3、反解檔的設定方式

確定正解流程沒問題之後,同時也解決了 master/slave 的設定,那就可以開始來處理反解。如同圖 8.2.1 所示, 我們基本上會有 3 組反解的 zone,要記得反解的 zone 設定的方式是 (1)IP 位址反過來寫 (2)結尾需加上 .in-addr.arpa.。 所以,192.168.{10,20,30}.0/24 這三組網段,其 zone name 就會變成:

  • 10.168.192.in-addr.arpa.
  • 20.168.192.in-addr.arpa.
  • 30.168.192.in-addr.arpa.

依循正解檔的對應,反解資料除了實際應用的 IP 位址之外,也只使用 1~100 號而已!接下來就讓我們依序來處理:

  • 主設定檔 /etc/named.conf 的修改

先來處理 dns1 的 master DNS 設定:

[root@dns1 ~]# vim /etc/named.conf
zone "10.168.192.in-addr.arpa" IN {
        type master;
        file "named.192.168.10";
        allow-transfer { 192.168.30.212; };
};
zone "20.168.192.in-addr.arpa" IN {
        type master;
        file "named.192.168.20";
        allow-transfer { 192.168.30.212; };
};
zone "30.168.192.in-addr.arpa" IN {
        type master;
        file "named.192.168.30";
        allow-transfer { 192.168.30.212; };
};

[root@dns1 ~]# named-checkconf

確認上述設定並不會出問題才行!接下來繼續做 zone file 設定!

  • zone file 反解設定

反解幾乎只有 PTR 設計而已,你要注意的是,主機名稱務必使用 FQDN,不要用正解的自動加上 zone 的模式! 這是因為反解的 zone 是一組 IP 的 domain,不是主機名稱!

[root@dns1 ~]# cd /var/named
[root@dns1 named]# vim named.192.168.10
; 這個 zone file 的 zone (@) 預設為 10.168.192.in-addr.arpa.
$TTL 600
@       IN SOA  dns1.server.vbird. adm.mail.server.vbird. ( 2023112801 3H 15M 1D 600 )
; 這個 zone 的 DNS server 指定,反解要用 PTR
@       IN NS   dns1.server.vbird.
@       IN NS   dns2.server.vbird.
211     IN PTR  dns1.server.vbird.
212     IN PTR  dns2.server.vbird.
; 其他用戶端的設定!主要是分給內網用的,共計 100 台!
1       IN PTR  ap001.ap.vbird.
2       IN PTR  ap002.ap.vbird.
...

[root@dns1 named]# named-checkzone 10.168.192.in-addr.arpa named.192.168.10
zone 10.168.192.in-addr.arpa/IN: loaded serial 2023112801
OK

相同的設定資料,請輸入到 named.192.168.{20,30} 檔案內。事實上,NS 的設定除了 192.168.30.0/24 那一段是正確的之外, 其餘兩段的 NS 設定是錯誤的!不過畢竟我們是放置在內網,也直接指定這兩部 DNS 作為代查詢伺服器,所以都可以找到正確的反解資料, 這樣就可以了!

  • 重新啟動 named-chroot 與測試

接下來就是重新啟動服務,並且嘗試測試我們的設定值!

[root@dns1 named]# systemctl restart named-chroot
[root@dns1 named]# dig +short -t soa 10.168.192.in-addr.arpa
dns1.server.vbird. adm.mail.server.vbird. 2023112801 10800 900 86400 600

[root@dns1 named]# dig +short -t ns 10.168.192.in-addr.arpa
dns2.server.vbird.
dns1.server.vbird.

[root@dns1 named]# dig +short -x 192.168.10.1
ap001.ap.vbird.
[root@dns1 named]# dig +short -x 192.168.20.10
client010.lan.vbird.
[root@dns1 named]# dig +short -x 192.168.30.5
server05.server.vbird.

至少得要完成上述的動作才行喔!這樣,我們的正反解也就在 dns1 完成了!接下來,準備處理 slave DNS 吧!

  • 將反解 zone file 同步到 slave DNS 上

跟正解的 slave 設定相同,我們不用處理 zone file,只要讓 slave 向 master 要資料就好!

# 記得,底下的動作是在 dns2 上面完成的!
# 1. 處理主設定檔,並且測試設定是否正確
[root@dns2 ~]# vim /etc/named.conf
zone "10.168.192.in-addr.arpa" IN {
        type slave;
        file "slaves/named.192.168.10";
        masters { 192.168.30.211; };
};
zone "20.168.192.in-addr.arpa" IN {
        type slave;
        file "slaves/named.192.168.20";
        masters { 192.168.30.211; };
};
zone "30.168.192.in-addr.arpa" IN {
        type slave;
        file "slaves/named.192.168.30";
        masters { 192.168.30.211; };
};

[root@dns2 ~]# named-checkconf

# 2. 重新啟動服務並且測試
[root@dns2 ~]# systemctl restart named-chroot
[root@dns2 ~]# tail -n 100 /var/log/messages| grep '168.192.in-addr.arpa'
# 這時應該要看到類似底下的資訊:
transfer of '10.168.192.in-addr.arpa/IN' from 192.168.30.211#53: Transfer completed:

[root@dns2 ~]# dig +short -x 192.168.10.1
ap001.ap.vbird.

就這樣,連反解也完成啦!

8.4、區域網路內 client 的 DNS 設定 (/etc/resolv.conf, search)

現在,根據圖 8.2.1 的說明,我們已經建置好內部三個 IP 位址網段的正反解設計,master/slave 的 DNS 架構也進行完畢, 那麼該對於內部的系統修改 DNS 設定了!我們先以 master 骨幹系統來處理好了。現在,假設我們需要讓 master 骨幹伺服器使用這兩部 dns 系統, 同時,為了簡化主機名稱的應用,我們希望使用類似 /etc/hosts 裡面的簡易設定,例如當輸入 client001 時, DNS 系統就應該要知道去找到 client001.lan.vbird 這個主機名稱,並取得 192.168.20.1 的 IP 位址才好!也就是說:

  • 需要使用 dns1, dns2 這兩部 DNS 伺服器
  • 需要依序查詢 server.vbird, lan.vbird, ap.vbird 這三個 domain 的 IP 位址正解。
  • 使用 nmcli 做設定

如果仔細看 nmcli 的輸出,會發現有一個 ipv4.dns-search 的設定,該設定就是搜尋 domain name 的意思! 所以,要達成上述的功能,我們可以在 master 骨幹系統上面這樣做:

[root@master ~]# nmcli connection modify enp1s0 ipv4.dns 192.168.30.211,192.168.30.212 \
> ipv4.dns-search server.vbird,lan.vbird,ap.vbird
[root@master ~]# nmcli connection up enp1s0
[root@master ~]# cat /etc/resolv.conf
search server.vbird lan.vbird ap.vbird vbird
nameserver 192.168.30.211
nameserver 192.168.30.212

[root@master ~]# dig www.vbird.tw
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;www.vbird.tw.                  IN      A
;; ANSWER SECTION:
www.vbird.tw.           600     IN      CNAME   linux.vbird.tw.
linux.vbird.tw.         600     IN      A       140.116.44.180
;; SERVER: 192.168.30.211#53(192.168.30.211)
# 我們只擷取部份會觀察到的資訊!可以看到 master 向 dns1 要求資料了!
  • 刪除 /etc/hosts 不必要的資料

因為之前為了方便我們記憶,我們有將一些私有 IP 對應主機名稱放置到這邊來~這時就該整理整理:

[root@master ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.201.249    cloud.vbird       cloud
192.168.201.245    master.vbird      master

實際上,就是將我們本章設定的 192.168.{10,20,30}.0/24 的 IP 網段對應取消而已!其他還是要保留喔! 然後就可以開始來測試看看了:

[root@master ~]# ping -c 2 dns1
PING dns1.server.vbird (192.168.30.211) 56(84) bytes of data.
64 bytes from dns1.server.vbird (192.168.30.211): icmp_seq=1 ttl=64 time=0.171 ms
64 bytes from dns1.server.vbird (192.168.30.211): icmp_seq=2 ttl=64 time=0.343 ms

[root@master ~]# ping -c 2 client001
PING client001.lan.vbird (192.168.20.1) 56(84) bytes of data.
64 bytes from client001.lan.vbird (192.168.20.1): icmp_seq=1 ttl=64 time=0.207 ms
64 bytes from client001.lan.vbird (192.168.20.1): icmp_seq=2 ttl=64 time=0.423 ms

[root@master ~]# ping -c 2 ap010
PING ap010.ap.vbird (192.168.10.10) 56(84) bytes of data.
From master.vbird (192.168.10.254) icmp_seq=1 Destination Host Unreachable
From master.vbird (192.168.10.254) icmp_seq=2 Destination Host Unreachable

你可以發現,使用短主機名稱 (hostname) 時,我們的系統還是可以找到對應的 FQDN 主機名稱,這是因為 /etc/resolv.conf 裡頭 search 的設定!這真是個不錯用的功能啊!只是,dig 不能這樣用~dig 還是得要輸入完整的 FQDN 才行! 但是 ping, curl 等等的網路指令,都可以這樣應用喔!未來就可以『 ssh dns1 』之類的方式去連線了!

請修改 dns1, dns2 及 client001 的網路設定,讓我們整個網域的資料都用相同的 DNS 與 dns search 設定!

8.5、進階設定方式

上面的 DNS 設定是比較常見的使用方式,簡單的正反解設計完畢後,就可以實際應用了。不過,某些特殊的情境下, 可能還是會遇到一些需要了解的部份!包括子網域授權、網際網路/區域網路查詢方式的差異、動態 DNS 的設計等等, 這些都可以來玩一玩!

8.5.1、子網域授權方式

所有的孩子都有個父母親是吧?名字大部份都是承襲家長對吧?那麼,如果你的下屬單位跟你說,他們需要自己獨立的 DNS 設定! 這樣方便他們自己管理~這時,你就得要『將你的網域的部份查詢權,交給下屬單位的 DNS 系統管理』才行! 舉例來說,成大 (ncku.edu.tw) 的資工系 (csie) 跟成大說,我需要自己架設 DNS 服務,以方便自己處理未來各研究室的主機名稱管理! 這樣要修改比較方便~此時,成大可能就會將 csie.ncku.edu.tw 的查詢權交給資工系自己館,從此就不再幫資工系設定主機名稱的正解設定了! 資工系也能更快速的在自己系上就完成相關的設定,而不用提交到校的層級去處理!真是 win win 啊!

# 1. 查詢成大是否具有自己的 domain name server
[root@dns1 ~]# dig +short -t ns ncku.edu.tw
apple.ncku.edu.tw.
name.ncku.edu.tw.
# 結果是有的!所以 ncku.edu.tw 就是一個完整的 domain

# 2. 查詢成大資工系是否具有自己的 domain name server
[root@dns1 ~]# dig +short -t ns csie.ncku.edu.tw
dns.csie.ncku.edu.tw.
# 結果也是有的!所以 csie.ncku.edu.tw 也是個完整的 domain

# 3. 查詢成大環工系 (ev) 是否具有自己的 domain name server
[root@dns1 ~]# dig +short -t ns ev.ncku.edu.tw
# 空的!沒任何資訊!所以 ev.ncku.edu.tw 還是由成大計中校級單位所控制

如同圖 8.1.1 當中提到的,子網域的 zone 必須要包含父網域才行!所以上面的例子當中,成大資工系自己的 domain 必須要完整的包含成大整體的 domain, 所以就 csie.ncku.edu.tw 這樣的存在!而 dns.csie.ncku.edu.tw. 這部主機未來只能規劃 *.csie.ncku.edu.tw 的主機名稱喔!

  • 在總公司設定子網域授權 (NS) 的設定方式

舉例來說,管理部門需要管理自己的 manage.server.vbird 的網域,未來所有的 *.manage.server.vbird 他們都要自己管理! 不讓總公司的 IT 部門管理了!子單位要求的子網域為 manage.server.vbird,且提供該 DNS 服務的 IP 位址為 192.168.30.210 時, 你有主機名稱與 IP 位址了~那麼總公司的 IT 部門,只要修改 zone file 即可!修改的方式如下:

# 1. 在 master DNS 上面,修改 named.server.vbird 檔案,除了 NS 與 A,還要記得改序號!
[root@dns1 ~]# vim /var/named/named.server.vbird
@       IN SOA  dns1.server.vbird. adm.mail.server.vbird. ( 2023112902 3H 15M 1D 600 )
# 上面 SOA 的序號請加大!使用日期格式處理較佳!
manage  IN NS dns.manage.server.vbird.
dns.manage.server.vbird. IN A  192.168.30.210
# 主機名稱的部份,寫 FQDN 好像問題比較小!其他的部份則保留不變

# 2. 分別檢查兩個 domain 的設定情況
[root@dns1 ~]# named-checkzone server.vbird /var/named/named.server.vbird
zone server.vbird/IN: manage.server.vbird/NS 'dns.manage.server.vbird' (out of zone) 
                      has no addresses records (A or AAAA)
zone server.vbird/IN: loaded serial 2023112902
OK
# 因為子網域授權的關係,這裡會顯示 out of zone,不過不用理會沒關係

[root@dns1 ~]# named-checkzone manage.server.vbird /var/named/named.server.vbird
zone manage.server.vbird/IN: loaded serial 2023112902
OK
# 這裡就顯示 domain name 設定是正常的了!

# 3. 重新啟動 named-chroot 吧!
[root@dns1 ~]# tail -n 100 /var/log/messages | grep 'server.vbird'
Nov 29 10:14:03 dns1 named[11857]: zone server.vbird/IN: loaded serial 2023112902
Nov 29 10:14:03 dns1 named[11857]: zone server.vbird/IN: sending notifies (serial 2023112902)
Nov 29 10:14:04 dns1 named[11857]: client @0x7fc9300073d8 192.168.30.212#59263 (server.vbird): 
                                   transfer of 'server.vbird/IN': AXFR-style IXFR started (serial 2023112902)
Nov 29 10:14:04 dns1 named[11857]: client @0x7fc9300073d8 192.168.30.212#59263 (server.vbird): 
                                   transfer of 'server.vbird/IN': AXFR-style IXFR ended: 1 messages, 
                                   19 records, 510 bytes, 0.001 secs (510000 bytes/sec) (serial 2023112902)
# 在 master 重新啟動 named-chroot 時,會主動呼叫 slave 來更新喔!

這樣就一切順利處理完畢了!接下來,所有 *manage.server.vbird 的網域,就由 192.168.30.210 那部系統 (dns.manage.server.vbird) 自己去管理了!其他的設定,就請自己參考我們上面所談到的流程了,只是子網域只有一部 DNS,所以也就不用設定 slave DNS 囉! 另外,在目前,當 dns.manage.server.vbird 尚未架設,或架設錯誤時,我們能不能找到設定在總公司的 dns.manage.server.vbird 的 A 設定呢?來測試看看:

[root@dns1 ~]# dig dns.manage.server.vbird
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 13409
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 870e35ffa8d0f3430100000065669fae55ab6c36c8a323e1 (good)
;; QUESTION SECTION:
;dns.manage.server.vbird.       IN      A

;; Query time: 1 msec
;; SERVER: 192.168.30.211#53(192.168.30.211)

你會發現沒有 ANSWER 的結果!因為 DNS 的 NS 設定項目,會將子網域完整授權出去,所以當你找不到 dns.manage.server.vbird 這部主機的資料 (因為該主機根本沒有建置啊!),就會顯示錯誤!也就是說,未來任何的設計錯誤,都跟總公司無關了!哈哈哈! 從這裡也是要跟大家說,如果你的 DNS 設定錯誤,那麼所有的正確設定就無法被查詢到,那你的 server name 反而會產生相當大的問題! 因此,到底是要自幹 DNS 伺服器?還是請外頭 DNS 代管公司幫忙你處理?這個就有賴各位讀者們的思考了!總之, 目前練功一下總是不錯的!

8.5.2、以 nftables 負載平衡進行兩部 DNS 的輪詢

現在,假設你的 DNS 服務準備要提供給 internet 作為查詢,主要是作為 query 的查詢而不是 recursion 喔! 那麼就得要開放防火牆的轉遞才行!然後,我們希望從外部來的 IP 位址找到的是 master 骨幹的對外 public IP 位址, 而內部來的 IP 位址找到的則是我們內部的 private IP 位址~該如何進行這部 DNS 向外放行的功能?

  • nftables 的負載平衡功能

既然我們的 DNS 伺服器是擺在 master 骨幹系統內部,那麼如果要對外提供服務的話,就勢必要放行 port 53 的 DNAT 功能才行! 但是,我們有架設兩部 DNS 伺服器耶!要提供那一部?主要是提供 master DNS 嘛?那麼 slave 未來幾乎都不會被用到喔! 能不能兩部主機都提供?但是我們只有一個對外 IP 位址喔!這時,就得要使用 nftables 的負載平衡 (load balance) 功能了! 這個功能還挺有趣的!我們可以使用底下的圖示來了解一下:

圖 8.5.2、透過 nftables 的 load balance 功能做負載平衡
圖 8.5.2、透過 nftables 的 load balance 功能做負載平衡

如上圖所示,我們有兩個 DNS 伺服器在 master 骨幹內部,當網路來的封包要使用我們的 DNS 伺服器時,1 號封包使用 dns1, 2 號封包使用 dns2,3 號封包回去使用 dns1,以此類推!也就是,針對封包以 2 作為迴圈,在 2 個系統間做切換! nftables 的指令執行挺容易的,如下所示:

[root@master ~]# nft 'add rule inet mynat mydnat iifname enp1s0 udp dport 53 \
> dnat ip to numgen inc mod 2 map { 0: 192.168.30.211, 1: 192.168.30.212 }'

重點在 numgen 那一段!原本的指令應該是『dnat ip to 192.168.30.211』類似這樣的處理,現在因為有 2 部, 所以就用 numgen inc mod 2 map,然後分別指定 1 去 192.168.30.211 而 2 去 192.168.30.212 這樣! 如此一來,就可以將 port 53 連線封包進行負載平衡了!相當的輕鬆愉快!實際加入系統設定,還得要依據第 7 章的內容, 修改 /root/nftables.sh 才行:

# 1. 在 master 骨幹系統底下,修改 nftables 的腳本檔案!
[root@master ~]# vim /root/nftables.sh
# part 2.4: 建立 DNAT 功能
nft add rule inet mynat mydnat iifname ${wanif} udp dport 53 dnat ip to \
    numgen inc mod 2 map { 0: 192.168.30.211, 1: 192.168.30.212 }
nft add rule inet mynat mydnat iifname ${wanif} tcp dport 53 dnat ip to \
    numgen inc mod 2 map { 0: 192.168.30.211, 1: 192.168.30.212 }
nft add rule inet mynat mydnat iifname ${wanif} tcp dport 80 dnat ip to 192.168.30.1

[root@master ~]# sh /root/nftables.sh

# 2. 觀察 mydnat 鏈的內容
[root@master ~]# nft list chain inet mynat mydnat
table inet mynat {
   chain mydnat {
      type nat hook prerouting priority dstnat; policy accept;
      iifname "enp1s0" tcp dport 2121 redirect to :22
      iifname "enp1s0" udp dport 53 dnat ip to numgen inc mod 2 map { 0 : 192.168.30.211, 1 : 192.168.30.212 }
      iifname "enp1s0" tcp dport 53 dnat ip to numgen inc mod 2 map { 0 : 192.168.30.211, 1 : 192.168.30.212 }
      iifname "enp1s0" tcp dport 80 dnat ip to 192.168.30.1
   }
}

如果想要測試,是不是真的會根據封包來進行負載平衡,可以這樣做:

  • 在 dns1, dns2 上面執行『 tcpdump -i enp1s0 -nn port 53 』
  • 在外網執行『 dig ap001.ap.vbird @192.168.201.245 』數次
  • 看看 dns1, dns2 那一部有回應 port 53

很快樂的就可以發現 nftables 幫我們搞定了負載平衡!

  • 直接放行 DNS 查詢的問題

我們的 server.vbird, ap.vbird, lan.vbird 這三個正解 zone,以及各個反解的 zone 都是只提供給企業內部使用的 DNS 主機名稱查詢環境,並不想提供給外網~而且也沒有必要提供給外網知道!另外,外網來的查詢,應該一致認為是不能遞迴查詢的! 只有內部可以遞迴查詢!應該是這樣才對啊!但是,我們可以從上一個練習當中知道,外部的 DNS 查詢,可以查到 ap001.ap.vbird 這個主機名稱的 IP 位址呢!這樣是相當不合理的!那,能不能將 zone 做個分類,有只提供給內網查詢的, 以及僅提供給外網查詢的資料呢?這就需要用到 view 的功能了!

8.5.3、使用 view 依來源分別提供 DNS 查詢服務

如前一章節所述,我們可能得要將外部來的 DNS 查詢結果與內部網段來的查詢結果,分開來設計! 簡單的說,我們應該要將 root zone file (.) 以及我們自己定的 6 個 zone 放置到內網查詢, 而外網基本上目前只能查到 root zone file 而已才對!這時,就得要 view 的幫忙了!

  • 使用 view 將內外 zone 切開

我們預計使用 view 切開兩個界面,分別是:

  • 一個稱為 intranet 給來源 IP 位址為內部的查詢,可遞迴查詢
  • 一個稱為 internet 給來源 IP 位址為其他非內部的來源查詢,不可遞迴查詢

內部的 IP 位址來源直接放行遞迴 (反正就是內部來源啊),外部的來源則不許遞迴查詢。 目前外部僅提供 root zone file 的 zone 而已,內部則需要全部的 zone 都放上去!所以,整體的主設定在 dns1 應該修改成這樣:

# 注意,所有動作應該都在 master DNS 亦即 dns1 伺服器上面實做
[root@dns1 ~]# vim /etc/named.conf
acl mynet  { 192.168.10.0/24; 192.168.20.0/24; 192.168.30.0/24; 127.0.0.0/8; };
acl outnet { ! mynet; any; };
options {
        listen-on port 53 { any; };
        listen-on-v6 port 53 { any; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        secroots-file   "/var/named/data/named.secroots";
        recursing-file  "/var/named/data/named.recursing";
        allow-query     { any; };
        allow-transfer  { none; };
        recursion no;

        dnssec-validation yes;
        managed-keys-directory "/var/named/dynamic";
        geoip-directory "/usr/share/GeoIP";
        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
        include "/etc/crypto-policies/back-ends/bind.config";
};
logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};
view intranet {
        match-clients { mynet; };
        recursion yes;
        forwarders { 120.114.150.1; 120.114.100.1; };
        zone "." IN {
                type hint;
                file "named.ca";
        };
        zone "lan.vbird" IN {
                type master;
                file "named.lan.vbird";
                allow-transfer { 192.168.30.212; };
        };
        zone "ap.vbird" IN {
                type master;
                file "named.ap.vbird";
                allow-transfer { 192.168.30.212; };
        };
        zone "server.vbird" IN {
                type master;
                file "named.server.vbird";
                allow-transfer { 192.168.30.212; };
        };
        zone "10.168.192.in-addr.arpa" IN {
                type master;
                file "named.192.168.10";
                allow-transfer { 192.168.30.212; };
        };
        zone "20.168.192.in-addr.arpa" IN {
                type master;
                file "named.192.168.20";
                allow-transfer { 192.168.30.212; };
        };
        zone "30.168.192.in-addr.arpa" IN {
                type master;
                file "named.192.168.30";
                allow-transfer { 192.168.30.212; };
        };
        include "/etc/named.rfc1912.zones";
};
view internet {
        match-clients { outnet; };
        recursion no;
        zone "." IN {
                type hint;
                file "named.ca";
        };
        include "/etc/named.rfc1912.zones";
};
include "/etc/named.root.key";

[root@dns1 ~]# named-checkconf
[root@dns1 ~]# systemctl restart named-chroot

[root@dns1 ~]# grep zone.*vbird.*intranet.*load /var/log/messages
Nov 29 14:54:15 dns1 named[12269]: zone lan.vbird/IN/intranet: loaded serial 2023112801
Nov 29 14:54:15 dns1 named[12269]: zone ap.vbird/IN/intranet: loaded serial 2023112801
Nov 29 14:54:15 dns1 named[12269]: zone server.vbird/IN/intranet: loaded serial 2023112902

[root@dns1 ~]# grep zone.*168.192.*intranet.*load /var/log/messages
Nov 29 14:54:15 dns1 named[12269]: zone 20.168.192.in-addr.arpa/IN/intranet: loaded serial 2023112801
Nov 29 14:54:15 dns1 named[12269]: zone 10.168.192.in-addr.arpa/IN/intranet: loaded serial 2023112801
Nov 29 14:54:15 dns1 named[12269]: zone 30.168.192.in-addr.arpa/IN/intranet: loaded serial 2023112801

看起來上頭我們設計過的 3 組正反解設定,都只出現在 intranet 是沒問題的!我們分別在內網與外網來測試看看:

# 1. 在內網,我們以 master 骨幹系統來測試:
[root@master ~]# dig client005.lan.vbird
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;client005.lan.vbird.           IN      A
;; ANSWER SECTION:
client005.lan.vbird.    600     IN      A       192.168.20.5

# 2. 在外網,我們以 cloud 系統來測試(一定要測試兩次以上):
[root@cloud ~]# dig client005.lan.vbird @192.168.201.245
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 26655
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

這樣果然可以讓 DNS 提供不同的來源查詢!只是,在外網的查詢測試部份,經常會一個成功一個失敗!很有趣喔! 這是因為我們使用了 nftables 的負載平衡的緣故!因此查詢一下子是正確的 master DNS,一下子是全部提供的 slave DNS 啊!

  • 處理 slave DNS 的同步
所以,DNS 同步很重要!現在,請自行將 slave DNS 設定修改成如上所示的 view 分類功能!注意喔! 因為 slave 使用的 zone file 都是同步來的 (type slave),所以你不能直接複製 /etc/named.conf!需要自行慢慢修改才行!

# 底下所有動作都應該要在 slave DNs (dns2) 上面進行
[root@dns2 ~]# vim /etc/named.conf
acl mynet { 192.168.10.0/24; 192.168.20.0/24; 192.168.30.0/24; 127.0.0.0/8; };
acl outnet { ! mynet; any; };
options {
	....
        allow-transfer  { none; };
        recursion no;
	....
};
...
view intranet {
        match-clients { mynet; };
        recursion yes;
        forwarders { 120.114.150.1; 120.114.100.1; };
        ....
};
view internet {
        match-clients { outnet; };
        recursion no;
        ....
};

[root@dns2 ~]# named-checkconf
[root@dns2 ~]# systemctl restart named-chroot
[root@dns2 ~]# grep zone.*vbird.*intranet.*load /var/log/messages
Nov 29 15:25:12 dns2 named[6977]: zone ap.vbird/IN/intranet: loaded serial 2023112801
Nov 29 15:25:12 dns2 named[6977]: zone lan.vbird/IN/intranet: loaded serial 2023112801
Nov 29 15:25:12 dns2 named[6977]: zone server.vbird/IN/intranet: loaded serial 2023112902

連 slave DNS 都設定好的話,外網應該就什麼也查不到了!

  • 外網/內網針對同一個 zone 的不同設計

上面的 view 是將內部/外部的 zone 都切開,不讓內部專用的 zone 被查詢到!那假設你在 DMZ 架設一部 WWW 伺服器, 名稱為 www.wan.vbird 好了,假設 'wan.vbird' 這個 domain 是實際可用的~那麼外部與內部要連線到這部網頁伺服器, 應該要如同底下這樣的連線方式才合理:

圖 8.5.3、不同來源連線時,同一個 hostname 應該給不同的 IP 位址
圖 8.5.3、不同來源連線時,同一個 hostname 應該給不同的 IP 位址

也就是說,相同的 wan.vbird 的 zone,應該要分別存在於 intranet 與 internet 的 view 界面中,且分別有不同的 zone file 設定! 如此一來,才有辦法提供同一個主機名稱,依據不同的來源,給予不一樣的 IP 位址!現在,假設實際存在 wan.vbird 這個 zone, 而且這個 zone 裡面暫時僅有 www.wan.vbird 這個主機名稱的正解對應而已~我們可以簡單的這樣設計:

# 1. 針對 master DNS (dns1) 的設定
# 1.1 針對主設定檔的 zone 與 zone file 檔名設定:
[root@dns1 ~]# vim /etc/named.conf
...
view intranet {
        zone "wan.vbird" IN {
                type master;
                file "named.wan.vbird.lan";
                allow-transfer { 192.168.30.212; };
        };
        ...
};
view internet {
        zone "wan.vbird" IN {
                type master;
                file "named.wan.vbird.wan";
                allow-transfer { 192.168.30.212; };
        };
};
# 特別注意兩者的 zone file 檔名並不相同喔!

[root@dns1 ~]# named-checkconf

# 1.2 開始設定內網的 zone file 內容
[root@dns1 ~]# cd /var/named
[root@dns1 named]# vim named.wan.vbird.lan
$TTL 600
@       IN SOA  dns1.wan.vbird. adm.mail.wan.vbird. ( 2023112901 3H 15M 1D 600 )
@       IN NS   dns1.wan.vbird.
@       IN NS   dns2.wan.vbird.
dns1    IN A    192.168.30.211
dns2    IN A    192.168.30.212
www     IN A    192.168.30.220

[root@dns1 named]# chmod 640 named.wan.vbird.lan
[root@dns1 named]# chown root.named named.wan.vbird.lan
[root@dns1 named]# named-checkzone wan.vbird named.wan.vbird.lan
zone wan.vbird/IN: loaded serial 2023112901
OK

# 1.3 開始設定外網的 zone file 內容
[root@dns1 named]# vim named.wan.vbird.wan
$TTL 600
@       IN SOA  dns1.wan.vbird. adm.mail.wan.vbird. ( 2023112901 3H 15M 1D 600 )
@       IN NS   dns1.wan.vbird.
dns1    IN A    192.168.201.245
www     IN A    192.168.201.245
# 首先,DNS server 只剩一台,因為只有對外 IP,而且 www 應該也要設定為外部 IP

[root@dns1 named]# chmod 640 named.wan.vbird.wan
[root@dns1 named]# chown root:named named.wan.vbird.wan
[root@dns1 named]# named-checkzone wan.vbird named.wan.vbird.wan
zone wan.vbird/IN: loaded serial 2023112901
OK

# 1.4 重新啟動並觀察
[root@dns1 named]# systemctl restart named-chroot
[root@dns1 named]# tail -n 100 /var/log/messages | grep zone.*wan.*load
Nov 29 22:54:42 dns1 named[12791]: zone wan.vbird/IN/intranet: loaded serial 2023112901
Nov 29 22:54:42 dns1 named[12791]: zone wan.vbird/IN/internet: loaded serial 2023112901
# 2. 針對 slave DNS (dns2) 的設定
# 2.1 主設定檔的修改
[root@dns2 ~]# cd /var/named
[root@dns2 named]# vim /etc/named.conf
view intranet {
        ...
        zone "wan.vbird" IN {
                type slave;
                file "slaves/named.wan.vbird.lan";
                masters { 192.168.30.211; };
        };
        ...
};
view internet {
        ...
        zone "wan.vbird" IN {
                type master;
                file "named.wan.vbird.wan";
        };
        ...
};
# 因為 dns1, dns2 都在內網,查詢不到外網~所以外網檔案要用 type master 的類型

[root@dns2 named]# named-checkconf
[root@dns2 named]# scp dns1:/var/named/named.wan.vbird.wan .
[root@dns2 named]# chown root:named named.wan.vbird.wan

# 2.2 重新啟動 named-chroot 與測試
[root@dns2 named]# systemctl restart named-chroot
[root@dns2 named]# journalctl -u named-chroot | grep zone.*wan.vbird | cut -d ']' -f 2-
: zone wan.vbird/IN/intranet: loaded serial 2023112901
: zone wan.vbird/IN/intranet: sending notifies (serial 2023112901)
: zone wan.vbird/IN/internet: loaded serial 2023112901

[root@dns2 named]# dig +short www.wan.vbird
192.168.30.220

這樣就搞定了!你在外網使用如下的方式查詢,應該可以查詢到正確的對外 IP 位址才對:

# 在外網,例如母機器 cloud 系統上,可以這樣追蹤
[root@cloud ~]# dig +short www.wan.vbird @192.168.201.245
192.168.201.245

8.5.4、使用 DDNS

什麼是 DDNS 呢?這是 Dynamic DNS, 動態 DNS 的縮寫,就是可以讓使用者去修改自己的 A 或其他紀錄的資料! 也就是說,使用者可以在自己的電腦上面,透過某些指令,去更新 DNS server 上面關於自己主機名稱的設定值! 所以才叫做動態 DNS 設定的意思。那什麼時候會用到 DDNS 呢?基本上有兩種情境經常會用到:

  • 在內網 DHCP 自動取得網路參數的情況下,當用戶取得 IP 位址之後,DHCP server 才主動向 DNS 要求動態加設主機名稱與 IP 的對應
  • 在外網 Internet 的環境中,某些主機的 public IP 位址是會改變的,例如中華電線的光纖到府服務,會有 8 個隨機取得的 IP 位址可用! 如果要用這種 IP 位址來架設公開的網站,就可以使用 DDNS 的協助,讓用戶的主機在 IP 位址改變後,可以立即前往 DNS server 更新主機名稱對應的最新對應!
  • 內網更新功能: 使用 allow-update

內網的設定相對簡單,我們可以針對某一台或者是某幾台電腦的 IP 位址進行 DDNS 更新權的放行,被規範到可更新的用戶電腦, 只要使用類似 nsupdate 這種 bind 提供的軟體,就可以更新了!我們現在假設內網的 192.168.30.213 以及 192.168.30.254 這兩部主機, 可以對我們的 master DNS (dns1) 進行主動更新~主要更新的 zone 只能是 lan.vbird 那個 zone 而已。那就可以這樣做看看:

# 1. 底下的所有設定值,請在 dns1 上面實做!
# 1.1 在主設定檔內,增加 allow-update 的功能(只對內網放行)
[root@dns1 ~]# vim /etc/named.conf
        zone "lan.vbird" IN {
                type master;
                file "named.lan.vbird";
                allow-transfer { 192.168.30.212; };
                allow-update { 192.168.30.213; 192.168.30.254; };
        };

# 1.2 讓 SELinux 放行更新功能
[root@dns1 ~]# setsebool -P named_write_master_zones on

# 1.3 讓相關的 zone file 變成可讓 named 用戶更新的模樣
[root@dns1 ~]# chmod 664 /var/named/named.lan.vbird
[root@dns1 ~]# chown named.named /var/named/named.lan.vbird
[root@dns1 ~]# ll /var/named/named.lan.vbird
-rw-rw-r--. 1 named named 3355 Nov 28 22:14 /var/named/named.lan.vbird

# 1.4 重新啟動 named-chroot
[root@dns1 ~]# systemctl restart named-chroot
# 這個 /var/named/named.lan.vbird 檔案內容以後會被自動修訂喔!所以請記得要備份

在 DNS 的設定階段,這樣就完成了!要注意喔! allow-update 是個很重大權限放行,所以,請僅針對內網的某些重要 server 放行! 不要全部放行喔!主要放行的伺服器,通常就是 dhcp 自動分配網路參數的伺服器主機而已。我們這邊還沒有設定好 dhcp, 所以才額外放行 master 骨幹啦!現在,我們到 master 骨幹系統上面,透過一般 DNS 設定方式,如下所示的功能,來處理一個 A 的紀錄:

  • 語法: domain ttl [RR] [RR data]
  • 範例: check.lan.vbird 600 A 192.168.30.112
# 2. 底下的所有動作,請在 master 骨幹系統上面運作,直接使用 nsupdat 更新!
[root@master ~]# nsupdate
> server 192.168.30.211
> update delete check.lan.vbird A
> update add check.lan.vbird 600 A 192.168.30.112
> send
> [ctrl]+d
[root@master ~]# dig +short check.lan.vbird
192.168.30.112
[root@master ~]# dig +short -t soa lan.vbird
dns1.lan.vbird. adm.mail.server.vbird. 2023112803 10800 900 86400 600

兩個重點,一個是 check.lanv.vbird (結尾不用加上小數點) 這個 hostname 可以有對應的 IP 位址了! 另外則是原本 lan.vbird 這個 zone 的 SOA 序號會主動加一!為什麼呢?因為這樣 slave DNS (dns2) 就可以主動更新到最新的資料庫 zone file 了! 現在,再讓我們回去看看 dns1 的 zone file 資料:

# 3. 底下回到 dns1 去看看 zone file 的變化:
[root@dns1 ~]# ll /var/named/named.lan*
-rw-r--r--. 1 named named 3161 Nov 30 14:31 /var/named/named.lan.vbird
-rw-r--r--. 1 named named  985 Nov 30 11:12 /var/named/named.lan.vbird.jnl
# 會多出一個副檔名為 .jnl 的檔案喔!那就是更改資料檔!

[root@dns1 ~]# grep check /var/named/named.lan.vbird
check                   A       192.168.30.112
# 果然被主動加入這個紀錄值了!

# 4. 嘗試管理 .jnl 的日誌檔,將他刪除吧!
[root@dns1 ~]# rndc sync -clean
# 這個動作會將 *.jnl 的資料倒回去原始的 zone file,之後再刪除 .jnl 檔

這樣,內網的比較重要的伺服器,就可以主動來 DNS server 上面修改它們需要的主機名稱對應紀錄資料了! 不用管理員跑來手動修改!同時,每次改了新的紀錄,序號還會主動 +1,可以讓 slave DNS 真的來更新資料庫! 啊!這樣管理真是輕鬆愉快的多!

  • 外網更新功能: 使用 update-policy 限縮權限

allow-update 雖然很好用,但是...功能實在太強了!所以,如果我們使用於 internet 的話,可能會造成許多的資安困擾。 另外,剛剛提到,DDNS 也可以開放給 IP 位址變化後,想要更新 IP 位址對應到主機名稱的用戶上,如此一來, allow-update 也無法寫入固定的 IP 位址啊!所以,就得要使用金鑰系統了。

所謂的金鑰系統,其實就是透過 bind 本身提供的 ddns-confgen 指令的功能,產生一把加密過後的密碼鎖, 這個密碼鎖其實就是一串運算過後的字串,DNS server 與想要更新 DNS 紀錄的用戶端,透過這把密碼鎖達成溝通之後, 就可以進行 DNS 紀錄的更新了!這樣一來,就安全的多。至少,沒有金鑰的連線要來進行 DNS 紀錄的修改時,我們的 DNS server 就不會理會!

讓我們開始來針對外網做個 update 的範例吧!我們主要針對 wan.vbird 的 zone,然後僅放行 web2.wan.vbird 這個主機名稱對 A 紀錄的更新! 實驗的方式流程如下:

# 1. 在 dns1 上面實做的流程!
# 1.1 使用 ddns-confgen 運算產生一把密碼鎖 (只是密碼字串)
[root@dns1 ~]# ddns-confgen -a [演算法] -k [金鑰名] -s [主機名]
# 選項與參數:
-a :後面接的演算法是加密的機制,主要演算法有 hmac-sha1 hmac-sha256 hmac-sha512. 
     預設使用 hmac-sha256 演算法
-k :金鑰的名稱為何,基本上只跟 named.conf 的設定有關而已!任何名稱均可
-s :後面接的就是我們想要變更的主機名稱!

[root@dns1 ~]# cd /var/named
[root@dns1 named]# ddns-confgen -a hmac-sha256 -k web2 -s web2.wan.vbird.
# To activate this key, place the following in named.conf, and
# in a separate keyfile on the system or systems from which nsupdate
# will be run:
key "web2" {
        algorithm hmac-sha256;
        secret "2CgYCqw7L3eWsXR3bS3Xtp+QtoRB1u7jighQk4W0xI0=";
};

# Then, in the "zone" statement for the zone containing the
# name "web2.wan.vbird.", place an "update-policy" statement
# like this one, adjusted as needed for your preferred permissions:
update-policy {
          grant web2 name web2.wan.vbird. ANY;
};

# After the keyfile has been placed, the following command will
# execute nsupdate using this key:
nsupdate -k <keyfile>
# 其實預設就會有詳細的說明!上面的特殊字體部份,就是密碼鎖了!

# 1.2 修改主設定檔,並且確認設定沒問題
[root@dns1 named]# vim /etc/named.conf
view internet {
        ...
        key "web2" {
                algorithm hmac-sha256;
                secret "2CgYCqw7L3eWsXR3bS3Xtp+QtoRB1u7jighQk4W0xI0=";
        };
        zone "wan.vbird" IN {
                type master;
                file "named.wan.vbird.wan";
                allow-transfer { 192.168.30.212; };
                update-policy {
                        grant web2 name web2.wan.vbird. A;
                        // 讓 web2 這把密碼鎖只能修改 web2.wan.vbird. 的 A 紀錄
                };
        };
        ...
};

[root@dns1 named]# named-checkconf

# 1.3 修改 zone file 的權限之後,重新啟動 named-chroot
[root@dns1 named]# chown named.named named.wan.vbird.wan
[root@dns1 named]# chmod 664 named.wan.vbird.wan
[root@dns1 named]# ll named.wan.vbird.wan
-rw-rw-r--. 1 named named 265 Nov 29 22:53 named.wan.vbird.wan

[root@dns1 named]# systemctl restart named-chroot

基本上,如果你內網只有一部 DNS 的話,那上面的動作就完成了!只是我們有兩部...同時還無法對外網進行 zone file 同步... 所以,上面同樣的步驟,得要在 dns2 上面全部實做一次才行!

# 2. 底下全部的動作,都需要在 dns2 上面完成!
[root@dns2 ~]# vim /etc/named.conf
# 修改方式跟 dns1 一模一樣!請往前參考!不需要重新執行 ddns-confgen 喔!

[root@dns2 ~]# named-checkconf
[root@dns2 ~]# cd /var/named
[root@dns2 named]# chown named.named named.wan.vbird.wan
[root@dns2 named]# chmod 664 named.wan.vbird.wan
[root@dns2 named]# systemctl restart named-chroot

這樣就做好了!

  • 在外網用戶端使用 nsupdate 進行更新 (要兩次!)

因為我們有金鑰在 DNS server 上,且只能在外網更新~所以,我們先跑到 cloud 母系統上面,測試一下:

# 底下的動作,我們都是模擬外網~預設在 cloud 母機器上面實做!
# 1. 使用相同的密碼鎖建立一把密碼檔,檔案內容就是密碼鎖
[root@cloud ]# vim web2.key
key "web2" {
        algorithm hmac-sha256;
        secret "2CgYCqw7L3eWsXR3bS3Xtp+QtoRB1u7jighQk4W0xI0=";
};

# 2. 嘗試使用這把鑰匙重新修改 web2.wan.vbird 的 A 成為 192.168.201.243
[root@cloud ]# nsupdate -k web2.key
> server 192.168.201.245
> update delete web2.wan.vbird
> update add web2.wan.vbird 300 A 192.168.201.244
> send
> [ctrl]+c

[root@cloud ]# nsupdate -k web2.key
# 因為我們有兩部輪詢的 DNS server,所以要做兩次才行!否則只會更新到一部

[root@cloud ]# dig +short web2.wan.vbird @192.168.201.245
192.168.201.244

這樣就完成了 DDNS 的設計囉!輕鬆愉快!

8.6、參考資料

修改歷史:
  • 2023/11/30:修改完 DNS 章節!加入全部都是 master/slave 架構的設計,而且還增加 nftables 的負載平衡!我覺得很有趣!
2023/11/30以來統計人數
計數器
其他連結
環境工程模式篇
鳥園討論區
鳥哥舊站

今日 人數統計
昨日 人數統計
本月 人數統計
上月 人數統計