在這系列 DNS 文章上集中介紹架設 Caching-only DNS Server、DNS 客戶端工具使用介紹、架設內部專用的 DNS Server(正向解析,例 ol 網域);接著在本文中將承接前文繼續介紹架設內部專用的反解 DNS Server(以 172.18.Y.Z 為例)、DNS Server 與主機名稱整合應用(包括使用 Dynamic DNS 與架設 DHCP Server)。
本文描述的重點在於實際將 DNS Server 拿來中小企業實務應用,而不僅僅是教怎麼架設 Linux DNS Server 而已,內容著重於如何應用 Linux 使得 IT/MIS 工作更加輕鬆;此外並將常見的 DNS Server 架設錯誤訊息以及可能的處理方式介紹說明,為的是要將基礎打好以增進除錯能力,對於 Linux 的實力才能夠有所提昇。
在上一期的文章中,設定內部專用的 ol 網域 DNS Server 算是已經有個雛型,接下來是建立內部網段反解的 DNS Server,就先從測試現成既有的反解來做說明。
我們以中華電信知名 DNS 伺服器(IP 是 168.95.192.1)來作為反解查詢示範,直覺地使用指令「dig 168.95.192.1」(特別注意此為『錯誤示範』)會發現他查的是 168.95.192.1 的 A 紀錄,結果是查無此紀錄(錯誤示範如下圖)。

正確地查詢反解方式應該使用指令 dig 搭配 -x 選項,例如:「dig -x 168.95.192.1」此時會發現查詢所問的是『1.192.95.168.in-addr.arpa. 的 PTR 紀錄(Pointer)』有解答出主機名稱 hntp1.hinet.net.。

照這樣來看以我們上一期學會的 dig 使用方法,若輸入「dig 1.192.95.168.in-addr.arpa ptr」查詢結果應該會是一樣的訊息(意思是查詢『1.192.95.168.in-addr.arpa 的 ptr 紀錄』)。

由上述測試概括地了解到,反解是查詢 W.X.Y.Z.in-addr.arpa 的 PTR 紀錄;反解以網域名稱『in-addr.arpa』結尾是固定不變的,需要注意 W.X.Y.Z(填寫 IP 的部份)要倒過來寫,舉例來說 IP 是 168.95.192.1 需倒過來寫成 1.192.95.168.in-addr.arpa。
公開 IP(Public IP)的 DNS 反解通常是由 ISP 業者代為管理,原因是買到的 Public IP 都是一小段(也許是 3、8、16 個 IP)而不是一整個網段(256 個 IP)的關係,例如:公開 IP 是向中華電信這個 ISP 所租用的話,就到 Hinet 這個網頁 http://hidomain.hinet.net/top1.html 提出反解的申請。

設定公開 IP 反解的好處是,有些 Mail Server 會查詢送信過來的來源 IP 是否有 DNS 反解,沒有設定反解可能會被拒收信件;若遇到上述這種情況時,有設定反解的話信件往來狀況會比沒有設定時好一些。
大多數的企業內部會有個內部專用網段(因為有做 NAT 的關係),理論上 IP 範圍會介於以下這幾段:10.X.Y.Z 不然就是 172.16.Y.Z~172.31.Y.Z 要不就是 192.168.Y.Z;上述這些網段其實就是 Private IP(私有 IP)網段。
接下來就以網段 172.18.Y.Z 來實作反解 DNS 設定。
開啟 /etc/named.conf 增加檔案內容如下:
zone "18.172.in-addr.arpa" in {
type master;
file "172.18.db"; // record 檔案位於 /var/named/172.18.db
};
以上輸入 zone "18.172.in-addr.arpa" 這一段是用來新增 172.18.Y.Z 反解網域且角色為 master。

寫好了之後接著重啟 named(指令「/etc/init.d/named restart」)會有『loading master file 172.18.db: file not found』的訊息,我們先用『touch /var/named/172.18.db』產生剛剛 load 不到的那個檔案,再度重啟 named 這次則是得到需要有『SOA 與 NS 的 records』的錯誤訊息,然後才是編寫 record 檔案正確後,重啟才會正常。

在上述有個警告訊息『ol.db:1: no TTL specified; using SOA MINTTL instead』意思是我們並未在 ol.db 檔案的第一行設定 TTL 數值,因此使用 MINTTL 來取代;要消掉這個警告訊息的話,就開啟 ol.db(位於 /var/named/ol.db)增加編寫第一行『$TTL 86400』(一天的意思;一天有 86400 秒)後重啟 named 即可。

開啟檔案 /var/named/172.18.db 編寫內容如下:
$TTL 86400
@ IN SOA ns1.ol. root.ol. (
2008081511 ; 序號 serial number
43200 ; 重整 refresh
21600 ; 重試 retry
3600000 ; 過期 expire
86400 ; 存活時間 TTL
)
IN NS ns1.ol. ; 此行開頭空白,續接上一筆紀錄 @ (代表此 zone)
35.0 IN PTR ns1.ol. ; 就是 172.18.0.35 這台 DNS Server 的反解
上述那段內容大概十行左右,其實只有三筆紀錄,分別是 SOA、NS 與 PTR 紀錄。
第一筆是 SOA 紀錄:開頭的 @ 代表這個 zone(也就是 ol)在 SOA 後面的 ns1.ol. 是 master DNS Server 的名字(在此有使用 . 結尾,所以是『完整名稱』),接在後面的 root.ol. 是 e-mail 名稱『root@ol』在此採用輸入完整 e-mail 名稱的方式,所以寫成 root.ol.(因為 @ 在此已經被用掉了,所以只好換成一點 .),然後用小括號內放了五個數字,這五個數字依舊是屬於這筆 SOA 紀錄,分別是 序號(serial number)、重整(refresh)、重試(retry)、過期(expire)與 存活時間(TTL),這五個數字各有用途,留到後面再詳述。
第二筆是 NS 紀錄:此行的開頭空白,意思是續接上一筆紀錄的 @ (代表這個 zone),Name Server 紀錄為 ns1.ol.(在此有使用 . 結尾,所以是『完整名稱』)。
第三筆是 PTR 紀錄:此行開頭的 35.0(因為沒有 . 結尾,所以補上這個 zone 所以變成 35.0.18.172.in-addr.arpa),有一筆 PTR 紀錄(Pointer)指向到主機名稱為 ns1.ol.(有 . 結尾的是完整名稱),也就是這台 Name Server 的主機名稱。

輸入完成之後,重啟 named 應該會正常才對。

重啟 named 正常後,使用指令「dig -x 172.18.0.35」來測試剛才輸入的第三筆紀錄(也就是 PTR 的那一筆紀錄)。

要查詢 18.172.in-addr.arpa 的 NS 紀錄時,使用指令「dig 18.172.in-addr.arpa ns」。

要查詢 18.172.in-addr.arpa 的 SOA 紀錄時,使用指令「dig 18.172.in-addr.arpa soa」。

在輸入 Record 檔案的內容時,『有沒有 . 結尾』這個「點」蠻重要的,以 172.18.db 檔案內容舉例來說:
| 有點結尾的 | ns1.ol. | 正常的結果應該是完整名稱 ns1.ol | 如果漏了(忘記)輸入結尾的點 就會錯誤的補上這個 zone 成為 ns1.ol.18.172.in-addr.arpa |
| 有點結尾的 | root.ol. | 正常的結果應該是完整名稱 root.ol | 如果漏了(忘記)輸入結尾的點 就會錯誤的補上這個 zone 成為 root.ol.18.172.in-addr.arpa |
當設定好內部反解的 DNS Server 後,許多網路程式都會加快「連線初始化」的動作,尤其是當「來源主機 IP」有設定反解時會更快一些。
像是 ssh、telnet 這些網路程式,連線到伺服器時(sshd、in.telnetd),伺服器會嘗試地查詢「來源主機 IP」的反解(查到反解以後還會順便查詢一下正解有無對應,能正反解對應會更好);試想倘若沒有內部 DNS Server 快速的回應「有解析」或是「沒有解析」的話,伺服器勢必會將此 IP 的反解查詢,向外部 DNS Server 詢問(例如說向 168.95.1.1 來查),這可能要花上大約三~七秒左右的時間,才會回答出『沒有這個 IP 的反解』。
這也是為何有些主機 telnet 要連進去之前會頓頓的反應很慢(因為她在查詢來源 IP 的反解),但在輸入帳號密碼連線成功以後卻反而超順的(完全不會頓頓的)可能原因。
下圖為主機 i59.ol(172.18.0.59)登入到 ns1.ol(172.18.0.35)情況,執行指令「w」可看到來源主機是 i59.ol;那是因為我們已經將 172.18.db 加上一筆『59.0 IN PTR i59.ol.』反解;以及在 ol.db 加上一筆『i59 IN A 172.18.0.59』正解的關係(連線很順暢不會頓)。

既然「IP / 主機名稱」有設定正解反解比較好,可是一筆一筆輸入卻很沒有效率,而且我們發現欲輸入的資料是有規律的(1~254)那麼待會就用迴圈的方式來做吧!
按照筆者使用經驗,在 Red Hat Linux 設定主機名稱時,主機名稱的設定會與網路設定以及名稱解析(尤其是反解)有著些許關係,歸納如下:
| 狀況一 | Red Hat Enterprise Linux 主機名稱 安裝的時候就可以設定,安裝完成也可以修改 | 一般來說可於安裝時手動命名,在 Red Hat Linux 假如使用預設值就會是 localhost.localdomain |
| 狀況二 | 倘若查詢的到這台主機 IP 的反解 | Red Hat Linux 會自動使用反解當成主機名稱 |
| 狀況三 | 自訂主機名稱,使用固定 IP 方式設定網路 | 若要自訂主機名稱解析正確,需手動改 DNS Server 紀錄 |
| 狀況四 | 自訂主機名稱,使用 DHCP 方式取得網路設定 | 可利用 DDNS 機制動態更新自訂主機名稱至 DNS Server 紀錄 |
接下來針對狀況二(使用反解當做主機名稱,適用於部屬數量較大的 Linux 主機)與狀況四(採用 DDNS 機制更新主機名稱正解與反解)來分別說明。
我們可以利用『自動使用反解當成主機名稱』這個特性,在大量部屬 Linux 主機的同時,主機名稱既不會重複而且遠端連線控管時方便好管理(例 ssh 連線),前提是 DNS Server 要先把正解、反解都先輸入好才行。
比如說像 Linux 教室環境建置或是營造 Linux Cluster 架構,動輒二十~四十台以上 Linux 主機,如果還能夠搭配 KickStart 快速部屬安裝,加上會寫 Shell Script 批次處理的話,要集群管理一大堆 Linux 主機會比管一大堆 Windows 主機來的輕鬆許多。
我們就以二十台主機為例,假設希望這二十台主機分別使用主機名稱 i20.ol~i39.ol 且這二十台主機使用 IP 介於 172.18.0.20~172.18.0.39 接下來就是要在 DNS Server 正確地加上正解與反解,不論是使用 DHCP 或是固定 IP 設定這些主機的網路,對於後續的管控都會方便許多。
撰寫迴圈給 ol.db(正解)增加紀錄如下:
for i in $(seq 20 39) do echo -e "i$i\tIN\tA\t172.18.0.$i" >> /var/named/ol.db done
其中 seq 指令(sequence;中文是『順序』、『一連串的』的意思)是用來製造出 20 21 22 等等這個數列,使用 $( )括號使得「seq 20 39」指令先行執行產生結果後(也就是 20 21 22 ...)再與 for 迴圈一同執行,這與 for i in 20 21 22 一直輸入到 39 執行幾無差異。
do 與 done 之間執行 echo 的 -e 選項與接著輸入的『\t』(Tab 鍵)有關,因為 DNS 紀錄檔案建議採用 Tab 鍵(『\t』)來做分隔。
在 do 與 done 之間的 $i 會取值(對應到 for i in 的『i』)成為 20 21 22 等等(一共執行二十次)『>>』意思是會補(Append)在 /var/named/ol.db 檔案的尾端。

類似地撰寫迴圈給 172.18.db(反解)增加紀錄如下:
for i in $(seq 20 39) do echo -e "$i.0\tIN\tPTR\ti$i.ol." >> /var/named/172.18.db done
解說的部份因為極其類似,故不贅述;記得重新啟動 named 並測試結果是否正確(例:使用 dig 做測試)。

在客戶端主機使用 DHCP 自動取得網路設定的時候,除了可以使用反解來當作主機名稱以外,也可以『自訂』主機名稱經由 DHCP Server『動態更新』至 DNS Server 的正反解。
在 Red Hat Linux 客戶端主機使用『自訂』主機名稱(網路設定採用 DHCP 方式)配套措施設定如下:
開啟「/etc/sysconfig/network-scripts/ifcfg-eth0」(也就是 eth0 網路卡的設定檔)補上一筆『DHCP_HOSTNAME=foo』(以主機名稱 foo.ol 為例)後重新開機(或重啟網路)即可。

Client 設定好而 Server 卻沒跟著調整配合這可是行不通的,接下來談談 DHCP Server 如何與 DNS Server 配合。
欲完成 DDNS 的 DHCP Server 配合 DNS Server 功能,方便的話最好將這兩者放在同一台主機上(設定上也比較簡單),非不得已才會選擇拆開成兩台主機。
使用指令「yum install -y dhcp」即可。

設定的重點在於 DHCP Server 設定檔案 dhcpd.conf(位於 /etc/ 下)依照原先檔案的指示,拷貝位於共享文件區的 sample 檔案,將之修改成適合自己測試的環境即可(前置作如下)。
指令「cp /usr/share/doc/dhcp*/dhcpd.conf.sample /etc/dhcpd.conf」用來將 sample 檔案拷貝成預設的設定檔。

修改 dhcpd.conf 後的內文如下:
ddns-update-style interim;
ignore client-updates;
subnet 172.18.0.0 netmask 255.255.0.0 {
option routers 172.18.1.1;
option subnet-mask 255.255.0.0;
option domain-name "ol";
option domain-name-servers 172.18.0.35;
range dynamic-bootp 172.18.0.128 172.18.0.254;
default-lease-time 21600;
max-lease-time 43200;
}
上述許多都是採用 sample 檔案的預設值,也精簡了許多不一定要輸入的部份,修改到的內容簡述如下:
網段使用「172.18.0.0/255.255.0.0」這一段
預設閘道「routers 172.18.1.1」
網域名稱使用 "ol"「domain-name "ol"」這裡填寫的 "ol" 要與 DNS Server 管理的正解 zone 一致。
名稱解析伺服器(就是我們架的那一台)「domain-name-servers 172.18.0.35」這樣才會找這台主機做動態更新。
發配給客戶端主機的 IP 範圍「range dynamic-bootp 172.18.0.128 172.18.0.254」

設定好之後就啟動 DHCP Server「/etc/init.d/dhcpd restart」與設定下次開機自動啟動「chkconfig dhcpd on」

利用測試主機(foo.ol)網路重新啟動「/etc/init.d/network restart」或是重新開機,皆可以達到測試目的。
回到 Server 來觀察 DHCP 已經正確發配 IP 網路設定出去給 foo.ol 客戶端(觀察時所用到的指令「cat /var/lib/dhcpd/dhcpd.leases」)

但是這時候動態更新正反解功能尚未成功,原因是 DNS Server 預設是不允許 DHCP Server 更新的要求,藉由觀察 messages 檔案的末段(位於 /var/log/ 目錄下)指令「tail /var/log/messages」會看到『update 'ol/IN' denied』訊息。

編寫 DNS Server 設定檔案 /etc/named.conf 將『allow-update { localhost; };」加到 ol 與 18.172.in-addr.arpa 的 zone 區裡面,這樣這兩區就允許來自 DHCP Server(因為是同一台,所以也就是來自於 localhost)的更新要求。
zone "ol" in {
type master;
file "ol.db"; // record 檔案位於 /var/named/ol.db
allow-update { localhost; };
};
zone "18.172.in-addr.arpa" in {
type master;
file "172.18.db"; // record 檔案位於 /var/named/172.18.db
allow-update { localhost; };
};

別以為這樣子就能搞定,更新後的資料還有寫入檔案目錄權限的問題;重啟 named、重新啟動 foo.ol 的網路二度測試以後,還是沒有成功更新,這次觀察 messages 檔案內容發現『ol.db.jnl: create: permission denied』權限不足的問題。

要解決這個問題,最好先了解 named 寫入的權限是誰?由指令「ps ax | grep named」發現 named 執行選項『-u named』是使用 named 這個帳號的權限來讀取與寫入,而觀察 /var/named/ 目錄下有個現成的 data/ 目錄權限可供 named 這個帳號寫入,乾脆將 ol.db 跟 172.18.db 都搬到這 data/ 目錄底下,之後的 ol.db.jnl 應該也是產生在這裡,這樣子權限也就沒有問題了。

最終使用指令「mv /var/named/*.db /var/named/data/」將 ol.db 以及 172.18.db 搬到 /var/named/data/ 目錄下

並調整 named.conf 內 file 的位置成為『file "data/ol.db";』以及『file "data/172.18.db";』別忘記重啟 named 後再測試喔!

這次終於沒有 Error messages,成功的完成 DDNS 動態更新功能,檔案『ol.db.jnl』、『172.18.db.jnl』也都成功產生在 /var/named/data/ 目錄下,使用 dig 來測試查詢也都 OK 沒問題。
