BIND(Berkeley Internet Name Domain)是全世界最廣泛用來提供DNS服務的軟體,能夠將網域名稱與IP相互對應,提供了「named」和能用來遠端管理named的「rndc」工具。
安裝BIND
要在Ubuntu Server上安裝BIND,可以直接在終端機中執行以下指令:
DNS預設使用的TCP和UDP連接埠為53,可以使用以下指令來查看BIND是否有確實安裝成功。
ss
指令可以顯示出Socket相關的資訊。-l
參數可以只顯示正在監聽中的連線。若使用ss
指令時都沒給任何參數的話,會忽略掉監聽中的連線。-t
參數可以只顯示TCP連線。-u
參數可以只顯示UDP連線。-t
參數和-u
參數一起用時就表示可以只顯示TCP和UDP連線。-n
參數可以讓連接埠數字直接被輸出,而不是用一個名稱代替。-p
參數可以顯示佔用連線的行程。
如上圖,如果有看到TCP和UDP都有在監聽連接埠53的話,就表示BIND安裝成功了!另外您可能還會注意到TCP的連接埠953也正在被程式監聽,這個是「rndc」會使用到的連接埠,本文稍候會提到。
named
named是BIND提供的守護行程(daemon),用來接收並處理使用者發送的網域名稱或是IP查詢的請求,使用者通常會先將查詢請求發送到我們DNS的UDP連接埠,因為速度比較快。如果使用者請求失敗,才會將查詢請求發送到我們DNS的TCP連接埠53。
named的主要設定檔─named.conf
named.conf
是named的主要設定檔,在不同的Linux發行版會有不同的儲存目錄,且也會以不同的分類方式將設定檔拆成很多小設定檔。
Ubuntu Server的named.conf
存在於/etc/bind/named.conf
。它預設的模樣長成這樣:
從上圖可以看到,named.conf
設定檔內又用了include
命令去連結到其它存在於/etc/bind
目樹下的設定檔。
named.conf.options
顧名思義,這個設定檔是專門用來存放options
區塊(options { ... }
)的檔案。它預設的模樣長成這樣:
directory "/var/cache/bind";
directory
命令可以指定一個目錄,作為DNS資料庫來使用,這個目錄預設是在/var/cache/bind
。
forwarders { 0.0.0.0; };
forwarders
命令可以指定多個IP,以分號;
區隔。可以讓使用者的查詢請求在我們的DNS無法回答時,被轉遞給其它的DNS來回答。
forward only;
雖然在預設的設定檔中並沒有forward
命令的身影,但是它經常會與forwarders
命令一同使用。當forward
被設為only
時,使用者的查詢請求就只能透過forwarders
命令列出的IP所連結到的DNS來回答。
dnssec-validation auto;
dnssec-validation
命令可以使用auto
來做設定,如此一來就能直接讓我們的DNS擁有DNSSEC(Domain Name System Security Extensions)的支援,運行起來就更安全了!
listen-on-v6 { any; };
listen-on-v6
命令可以用來設定要監聽的IPv6範圍。
另外還有一個很常用的命令就是allow-query
,它可以用來指定允許向這個DNS查詢的網路,預設是全都允許。
named.conf.local
這個設定檔是專門用來存放本地和使用者自訂的zone
區塊(zone ... { ... }
)。zone
可以針對每個網域名稱和IP來作正解(用網域名稱查IP)、反解(用IP查網域名稱)的設定。它預設的模樣長成這樣:
從預設的檔案內容中,我們可以看到註解建議我們,如果沒有有特殊的需求的話,應該要將zone.rfc1918
這個檔案也include
進來。
zone.rfc1918
RFC 1918定義了私有IPv4的區段,zone.rfc1918
這個檔案的使用目的就是要區分出私有IPv4的區段。它預設的模樣長成這樣:
IPv4的私有區段範圍是:10.0.0.0 ~ 10.255.255.255、172.16.0.0 ~ 172.31.255.255、192.168.0.0 ~ 192.168.255.255。
zone
區塊的IPv4反解寫法如下:
zone "將要反解的IPv4以8位元為一組倒過來寫.in-addr.arpa" { ... };
zone
區塊的IPv6反解寫法如下:
zone "將要反解的IPv6以4位元為一組倒過來寫.ip6.arpa" { ... };
用以下這個實例來解釋:
zone "16.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
16.172
表示要對應172.16.*.*
這個IPv4區段。
zone
區塊中的file
命令,可以指定一個存有DNS資源記錄的檔案來給該zone
區塊所對應到的網域或是IP來使用。/etc/bind/db.empty
是BIND內建的設定檔,它預設的模樣長成這樣:
這個檔案的構造稍候會進行比較詳細的講解。簡單來說,就是當named接收到使用者的查詢請求之後,會去對應使用者要查詢的網域或是IP是否在本機端所定義的zone
區塊,如果有的話,file
命令所指派的DNS資源記錄(RR)檔案就是該查詢的解答了。
zone
區塊中的type
命令,可以有以下幾種設定值:
master
:表示此zone
區塊是主從架構的DNS中的「主要主機」。主從架構的DNS在文章之後會提到。slave
:表示此zone
區塊是主從架構的DNS中的「從屬主機」。主從架構的DNS在文章之後會提到。hint
:用於對應.
的時候。.
表示「根域名」(root name)。這個在文章之後會再提到。
接著繼續談談剛才的DNS資源記錄檔案吧!
$TTL 86400
$TTL
這個命令可以設定此DNS資源記錄作為解答的快取時間,單位是秒。設為86400
就表示這個DNS查詢請求只要問過DNS一次,客戶端得到的解答就可以持續用一整天,期間內不需要再去向DNS詢問新的解答。$TTL
通常會存在,但若不存在,則會以SOA記錄所設定的最小TTL作為TTL值,設定方式稍候會說明。
@ IN SOA localhost. root.localhost. ( 1 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 86400 ) ; Negative Cache TTL
以上,@
所在的這個欄位表示此筆DNS資源記錄要影響哪個網域(或是說是屬於哪個網域的)。@
這個值表示要讓使用這個DNS資源記錄檔案的zone
區塊所指定的名稱去取代這個@
。換句話說使用@
的話,相同的DNS資源記錄檔案,就可以適用於不同的zone
區塊中。但是,如果DNS資源記錄檔中有$ORIGIN
這個命令存在,就會被用來取代@
,而不會去使用zone
區塊所指定的名稱。如果這個欄位是空格的話,表示要沿用前一筆DNS資源記錄的這個欄位。
IN
所在的這個欄位表示這筆DNS記錄的類別。IN
這個值表示這筆DNS記錄是用於網際網路的。雖然還有其它值可以用,但我們幾乎用不到,詳細資訊可以參考RFC 1035。在這個欄位之前也可以插入一個TTL欄位,來針對這筆DNS記錄做TTL的控制,而不是去使用$TTL
命令所指定的值或是SOA記錄所指定的最小TTL值。
SOA
所在的這個欄位表示這筆DNS記錄的類型,同時也決定了下一個欄位,也就是這筆DNS記錄值的格式。SOA
這個值必須用在整個zone
區塊的DNS資源記錄的第一筆,用來指定這個使用主從架構的zone
區塊的一些資訊。DNS的主從架構就是,使用兩台以上的DNS,將其中一台作為「主要主機」,其它的都作為「從屬主機」,管理員只需要維護「主要主機」的DNS資源記錄,就可以讓「從屬主機」也跟著同步資料。當使用者要使用DNS來查詢網域名稱或IP時,主從架構中只要有一台DNS還活著,使用者就可以查詢到資料。
關於SOA記錄的值,格式如下:
注意寫在DNS記錄值的網域名稱,最好都使用完整網域名稱(FQDN, Fully Qualified Domain Name),也就是將一般的網域名稱在結尾處,加上半形句號.
,以示結尾。例如localhost
就寫成localhost.
。否則,DNS會自動在網域名稱之後再串接上.@.
,其中的@
的作用如同剛才所提到的那樣,會根據DNS資源記錄檔中有沒有$ORIGIN
這個命令存在,來決定要使用$ORIGIN
的值還是zone
區塊所指定的名稱。
電子郵件信箱正常的表示方式會使用@
來區隔使用者名稱和主機名稱。但因為@
在DNS記錄中有特殊的意義,因此需要被替換為.
。也就是說,如果您的電子郵件信箱為root@localhost
,就要寫成root.localhost.
。
SOA記錄的版本序號是指其所屬DNS資源記錄檔案的更動版本號,應為32位元的正整數,主從架構中屬於「從屬主機」的DNS會根據「主要主機」的DNS所傳來的SOA記錄的版本號,來決定是否要更新其所同步到的DNS資源記錄檔案。愈新的資料,版本號的值會愈大。
重試的時間間隔為主從架構中屬於「從屬主機」的DNS向「主要主機」的DNS獲取最新的DNS資源記錄的錯誤重試時間間隔,單位是秒。
逾時時間為主從架構中屬於「從屬主機」的DNS向「主要主機」的DNS獲取到的DNS資源記錄的有效時間,單位是秒,如果超過這個時間,「從屬主機」的DNS所儲存的該DNS資源記錄就會被刪除。
最小的TTL值即為這整個zone
區塊中的DNS資源記錄所能指定的最小TTL值。
接著再來看看下一筆DNS資源記錄吧!
@ IN NS localhost.
這是一筆NS記錄,可以在DNS記錄值中指定下一級的DNS的網域名稱,也就是要把使用者的問題再交給哪台DNS做解答的意思。由於這是私有IP的DNS資源記錄的實例,因此將下一級的DNS指定給localhost.
,就是再交還給使用者本地端的DNS來負責域名或是IP的對應啦!
整理一下常用的DNS資源記錄類型,如下:
SOA
:指定這個使用主從架構的zone
區塊的一些資訊。全名為Start Of Authority。NS
:指定下一級的DNS的網域名稱。A
:指定網域名稱所對應的IPv4。正解用。AAAA
:指定網域名稱所對應的IPv6。正解用。PTR
:指定IP所對應的網域名稱。反解用。CNAME
:指定別名。正解用。使用者收到網域名稱的別名之後會再使用這個別名進行DNS的查詢。這種DNS記錄可以擴展其它正解用記錄的網域名稱,反過來說就是可以使用不同的網域名稱來查詢到相同的記錄。MX
:用於指定電子郵件交換器的主機名稱。TXT
:指定網域名稱對應某筆字串資料,通常用於驗證網域所有權。
named.conf.default-zones
這個設定檔是專門用來存放預設的zone
區塊。它預設的模樣長成這樣:
zone "." { type hint; file "/etc/bind/db.root"; };
對應.
(根域名)的時候,zone
區塊的類型需使用hint
。其file
命令所指定的檔案是BIND內建的/etc/bind/db.root
,這個DNS資源記錄檔的資料來源為InterNIC,定義了網際網路通用的Root DNS。
接下來的幾個zone
區塊用來處理本地端網域名稱和IP。
zone "localhost" { type master; file "/etc/bind/db.local"; }; zone "127.in-addr.arpa" { type master; file "/etc/bind/db.127"; }; zone "0.in-addr.arpa" { type master; file "/etc/bind/db.0"; }; zone "255.in-addr.arpa" { type master; file "/etc/bind/db.255"; };
加入我們自己的zone
區塊
我們可以依照自己的Linux發行版所預設的BIND設定架構來加入自己的zone
區塊。以Ubuntu Server來說,根據/etc/bind/named.conf
的註解,我們應該要將自己的zone
區塊寫進/etc/bind/named.conf.local
中,所以就在/etc/bind
目錄中添加一個新的zone
區塊設定檔(在此取名為zones.inner.magiclen.org
),並在該設定檔內撰寫我們的zone
區塊設定,接著再在/etc/bind/named.conf.local
中,使用include
命令將剛才建立的zone
區塊設定檔給引用進來。
設定檔的內容如下:
zone "inner.magiclen.org" { type master; file "/etc/bind/db.inner.magiclen.org"; };
$TTL 86400 @ IN SOA ns1.inner.magiclen.org. admin.magiclen.org. ( 1 ; Serial 86400 ; Refresh 3600 ; Retry 2419200 ; Expire 84600 ) ; Negative Cache TTL IN A 192.168.56.2 IN NS ns1.inner.magiclen.org. ns1 IN A 192.168.56.103 host1 IN CNAME inner.magiclen.org. host2 IN A 192.168.56.3 nas IN CNAME host2.inner.magiclen.org.
記得每次更改db.inner.magiclen.org
這個檔案時,版本序號的欄位都要遞增。
設定好後必須讓named重新載入設定檔,可以使用以下指令:
除了用這個方式重新啟動named之外,還可以使用kill
指令來傳送SIGHUP信號給named的行程。
使用以下指令來檢查named的設定檔是否都有載入成功:
接著直接在DNS上使用dig
指令來做測試,指令如下:
在此補充一點,如果要用dig
指令來反解IP位址的網域名稱(PTR記錄),需要加上-x
參數。
然後會發現dig
指令查不到我們所設定的結果,因為此時的Linux作業系統環境所使用的DNS還不是我們所架設的DNS,所以dig
指令預設不會去使用到。要讓dig
指令使用我們在本機內架設的DNS,可以加上@127.0.0.1
這樣的參數。完整的指令如下:
這樣我們的DNS就架設成功啦!再查一個試試,指令如下:
手動指定Linux作業系統環境所使用的DNS
手動指定Linux作業系統環境所使用的DNS的方式有很多種。以Ubuntu或是其衍生的Linux發行版本來說的話,可以使用以下指令來查看不同網路介面所使用的DNS:
如果要手動指定DNS的話,可以在netplan這套網路管理程式的設定檔進行設定。設定檔位於/etc/netplan
目錄中,可在網路介面的名稱下增加nameservers
欄位來指定要用的DNS。如下圖:
接著使用以下指令來套用設定。
然後再次使用以下指令來檢查網路介面的DNS是否有設定完成:
最後使用dig
指令來驗證DNS能否正常查詢。指令如下:
增加從屬主機
前面雖然有提到DNS的主從架構,可以將解答同一個zone
區塊的DNS分為「主要主機」和「從屬主機」,但是我們都只有用到「主要主機」。接下來就談談怎麼設定「從屬主機」吧!
從屬主機和主要主機的DNS安裝方式相同,只有有使用主從架構的「zone」區塊會有所變化。「從屬主機」的zone
區塊,需使用type
命令,將值指定為slave
,而不是master
。且必須要另外使用masters
命令來指定「主要主機」的IP位址。繼續以剛才設定的inner.magiclen.org
網域來作為例子吧!
同樣地,我們需要將自己的zone
區塊寫進/etc/bind/named.conf.local
中,所以就在/etc/bind
目錄中添加一個新的zone
區塊設定檔(在此取名為zones.inner.magiclen.org
),並在該設定檔內撰寫我們的zone
區塊設定,接著再在/etc/bind/named.conf.local
中,使用include
命令將剛才建立的zone
區塊設定檔給引用進來。
設定檔撰寫方式如下:
zone "inner.magiclen.org" { type slave; masters {192.168.56.103;}; };
設定好後必須讓named重新載入設定檔,可以使用以下指令:
一樣使用dig
指令做測試,指令如下:
「從屬」DNS若成功運作的話,會把從「主要主機」拿到的資料快取至記憶體中。如果想要快取至檔案的話,需要在「從屬主機」的zone
區塊中加上file
命令。如下:
zone "inner.magiclen.org" { type slave; masters {192.168.56.103;}; file "db.inner.magiclen.org"; };
注意這邊的file
命令是使用相對路徑,如此一來就可以去使用options
區塊中directory
命令所指定的目錄作為DNS資料庫來使用。換句話說,這個「從屬主機」的zone
區塊,就會把從「主要主機」拿到的資料快取至/var/cache/bind/db.inner.magiclen.org
檔案中。如果要放到更下層的子目錄或是另外的目錄的話,必須事先將該目錄建立好,並且把目錄的擁有者和群組都設定為bind
,否則快取檔案是不會被建立出來的。
如果要限制「主要主機」所能夠擁有的「從屬主機」的話(即不允許陌生的「從屬主機」),需要在「主要主機」的zone
區塊中加上allow-transfer
命令。建議使用acl
區塊來建立一個有名稱的網路,讓包含在這個網路的節點都可以成為這台DNS的「從屬主機」。如下:
acl "my_slave_servers" { 192.168.56.104; }; zone "inner.magiclen.org" { type master; file "/etc/bind/db.inner.magiclen.org"; allow-transfer { my_slave_servers; }; };
至此,一台「從屬主機」就設定完成了,如法再炮製,即可建立出更多台「從屬主機」。全都設定完成之後,就會有好幾台IP不同的DNS,在設定給客戶端使用的時候直接把所有DNS的IP都設定進去就行了。DNS的查詢是先搶先贏的機制,每個DNS都會有機會被用到,沒有順序和優先權的問題。
主動通知從屬主機更新
從屬主機除了能每隔一段時間就去向主要主機要求最新的DNS資源記錄外,也可以由主要主機主動通知從屬主機來進行更新。我們只需要在「主要主機」的zone
區塊中,利用notify yes;
命令來啟用通知功能。一旦「主要主機」的zone
區塊有任何DNS資源記錄的更新,就會去主動通知相同區塊下,除了SOA記錄所指定「主要主機」的網域名稱之外,其它用NS記錄所指定的DNS。
改寫「主要主機」的zone
區塊後,檔案內容如下:
zone "inner.magiclen.org" { type master; file "/etc/bind/db.inner.magiclen.org"; notify yes; };
notify
命令還可以用explicit
這個值來設定。如果是用explicit
的話,就會去通知options
區塊中以also-notify
命令定義的IP位址所對應的DNS。
用named-checkconf
指令檢查named的設定檔是否有誤
named-checkconf
指令可以檢查named的設定檔是否有誤,不需要重啟或是重新載入設定檔。注意這個指令並不會檢查zone
區塊的DNS資源記錄檔。
用named-checkzone
指令檢查named的DNS資源記錄檔是否有誤
named-checkzone
指令可以檢查named的資源記錄檔是否有誤,不需要重啟或是重新載入設定檔。
用法如下:
rndc
rndc可以管理本地端或是遠端的named。在使用rndc前必須要先有個rndc的金鑰,Ubuntu Server已經將它包含在BIND裡面,設定檔的路徑為/etc/bind/rndc.key
。它預設的模樣長成這樣:
那個secret
命令所指定的金鑰是BIND隨機產生出來的,如果想要手動產生新的金鑰,並且讓named能夠與rndc搭配使用的話,可以使用以下指令:
這邊要注意的是,每次執行rndc-confgen
指令時出現的金鑰都會不一樣,此外它還會告訴我們named的設定檔應該要怎麼寫,照它講的方式做就好了。
首先覆蓋原本的rndc.key
檔案中定義的key
區塊。這個檔案其實就是rndc客戶端所使用的金鑰檔。
接著把rndc-confgen
指令提示要加進named.conf
檔案的內容加進去。加進去後的結果會像以下這樣:
named.conf
檔案中所設定的rndc金鑰是rndc伺服器端的金鑰。rndc客戶端和rndc伺服器端若要成功連線,它們持有的金鑰必須要相同才行。
設定好後必須讓named重新載入設定檔,可以使用以下指令:
再來就可以使用rndc
指令來管理本機的DNS了!
rndc
指令的第一個參數為其的子命令,常用的有:
reload
:重新載入named的設定檔。可以全部重新載入,或是在下一個參數指定一個要重新載入的zone
區塊。stats
:將DNS的統計輸出成檔案dumpdb
:將目前快取的DNS資源記錄輸出成檔案flush
:清空DNS快取。status
:顯示目前DNS的狀態。
例如:
遠端管理DNS
rndc
指令可以加上-s
參數來指定要管理的DNS的IP或是網域名稱。當然,管理端不一定要安裝完整的BIND來架設DNS,只需要安裝部份工具即可。以Debian或是其衍生的Linux發行版為例,使用以下指令即可安裝「rndc」。
然後要建立一個與遠端rndc伺服器相同的/etc/bind/rndc.key
金鑰檔。/etc/bind
這個目錄不一定會存在,可能需要手動建立。
rndc伺服器端,也就是DNS端的named.conf
也需要做一些修改,建議使用acl
區塊來建立一個有名稱的網路,讓包含在這個網路的節點都可以管理這台DNS。監聽的IP(inet
命令的第一個參數)也需要改成星號*
。
修改後的named.conf
檔案如下:
設定好後必須讓named重新載入設定檔,可以使用以下指令:
之後在管理DNS網路內的節點就可以透過rndc
指令來遠端管理DNS了!