28.7. 網域名稱系統 (DNS)

網域名稱系統 (Domain Name System, DNS) 是一種協定用來轉換網域名稱為 IP 位址,反之亦然。DNS 會協調網際網路上有權的根節點 (Authoritative root)、最上層網域 (Top Level Domain, TLD) 及其他小規模名稱伺服器來取得結果,而這些伺服器可管理與快取個自的網域資訊。要在系統上做 DNS 查詢並不需要架設一個名稱伺服器。

在 FreeBSD 10,已自基礎系統移除了 Berkeley Internet Name Domain (BIND),並替換為 Unbound。Unbound 被設置來做為 FreeBSD 的基礎中的本地快取解析程式。BIND 仍可以自 Port 套件集取得,名稱為 dns/bind99dns/bind98。在 FreeBSD 9 與較先前的版本,FreeBSD 基礎系統中是內建 BIND,FreeBSD 的版本提供了增強的安全性功能、新檔案系統配置及自動化 chroot(8) 設置,而 BIND 是由 Internet Systems Consortium 所維護。

以下表格會說明一些與 DNS 有關的術語:

表格 28.4. DNS 術語
術語定義
正向 DNS (Forward DNS)將主機名稱對應 IP 位址的動作。
源頭 (Origin)代表某個轄區檔案中所涵蓋的網域。
named, BIND在 FreeBSD 中對 BIND 名稱伺服器套件的通用稱呼。
解析器 (Resolver)主機向名稱伺服器查詢轄區資訊的系統程序。
反向 DNS (Reverse DNS)IP 對應主機名稱的動作。
根轄區 (Root zone)網際網路轄區階層的最開始,所有的轄區會在根轄區之下,類似在檔案系統中所有的檔案會在根目錄底下。
轄區 (Zone)獨立的網域、子網域或或由相同授權 (Authority) 管理的部分 DNS

轄區範例:

如您所見,更詳細的主機名稱會加在左方,例如 example.org.org. 更具體,如同 org. 比根轄區更具體,主機名稱每一部份的架構很像檔案系統:/dev 目錄在根目錄底下,以此類推。

28.7.1. 要架設名稱伺服器的原因

名稱伺服器通常有兩種形式:有權的 (Authoritative) 名稱伺服器與快取 (或稱解析) 名稱伺服器。

以下情況會需要一台有權的名稱伺服器:

  • 想要提供 DNS 資訊給全世界,做為官方回覆查詢。

  • 已經註冊了一個網域,例如 example.org,且要將 IP 位址分配到主機名稱下。

  • 一段 IP 位址範圍需要反向 DNS 項目 (IP 轉主機名稱)。

  • 要有一台備援或次要名稱伺服器用來回覆查詢。

以下情況會需要一台快取名稱伺服器:

  • 比起查詢外部的名稱伺服器本地 DNS 伺服器可以快取並更快的回應。

當查詢 www.FreeBSD.org 時,解析程式通常會查詢上游 ISP 的名稱伺服器然後接收其回覆,使用本地、快取 DNS 伺服器,只需要由快取 DNS 伺服器對外部做一次查詢,其他的查詢則不需要再向區域網路之外查詢,因為這些資訊已經在本地被快取了。

28.7.2. DNS 伺服器設定於 FreeBSD 10.0 及之後版本

於 FreeBSD 10.0,BIND 已被替換為 UnboundUnbound 只會驗證快取解析程式,若需要有權的 (Authoritative) 伺服器,有很多可在 Port 套件集找到。

Unbound 由 FreeBSD 基礎系統提供,預設只會提供本機的 DNS 解析,雖然基礎系統的套件可被設定提供本機以外的解析服務,但要解決這樣的需求仍建議安裝 FreeBSD Port 套件集中的 Unbound

要開啟 Unbound 可加入下行到 /etc/rc.conf

local_unbound_enable="YES"

任何已存在於 /etc/resolv.conf 中的名稱伺服器會在新的 Unbound 設定中被設為追隨者 (Forwarder)。

注意:

若任一個列在清單中的名稱伺服器不支援 DNSSEC,則本地的 DNS 解析便會失敗,請確認有測試每一台名稱伺服器並移除所有測試失敗的項目。以下指令會顯示出信認樹或在 192.168.1.1 上執行失敗的名稱伺服器:

% drill -S FreeBSD.org @192.168.1.1

確認完每一台名稱伺服器都支援 DNSSEC 後啟動 Unbound

# service local_unbound onestart

這將會更新 /etc/resolv.conf 來讓查詢已用 DNSSEC 確保安全的網域現在可以運作。

% drill -S FreeBSD.org
;; Number of trusted keys: 1
;; Chasing: freebsd.org. A

DNSSEC Trust tree:
freebsd.org. (A)
|---freebsd.org. (DNSKEY keytag: 36786 alg: 8 flags: 256)
    |---freebsd.org. (DNSKEY keytag: 32659 alg: 8 flags: 257)
    |---freebsd.org. (DS keytag: 32659 digest type: 2)
        |---org. (DNSKEY keytag: 49587 alg: 7 flags: 256)
            |---org. (DNSKEY keytag: 9795 alg: 7 flags: 257)
            |---org. (DNSKEY keytag: 21366 alg: 7 flags: 257)
            |---org. (DS keytag: 21366 digest type: 1)
            |   |---. (DNSKEY keytag: 40926 alg: 8 flags: 256)
            |       |---. (DNSKEY keytag: 19036 alg: 8 flags: 257)
            |---org. (DS keytag: 21366 digest type: 2)
                |---. (DNSKEY keytag: 40926 alg: 8 flags: 256)
                    |---. (DNSKEY keytag: 19036 alg: 8 flags: 257)
;; Chase successful

28.7.3. DNS 伺服器設定於 FreeBSD 9.X

在 FreeBSD 中,會稱 BIND daemon 為 named

檔案說明
named(8)BIND daemon 本身。
rndc(8)名稱伺服器控制工具。
/etc/namedb儲存 BIND 轄區 (Zone) 資訊的目錄。
/etc/namedb/named.confDaemon 的設定檔。

依指定轄區在伺服器上設定的方式,與該轄區相關的檔案會存放在 /etc/namedb 目錄中的 master, slavedynamic 子目錄,這些檔案中會含有 DNS 資訊,會在名稱伺服器回覆查詢時使用到。

28.7.3.1. 啟動 BIND

由於 BIND 預設已經安裝,要設定它相對簡單。

預設的 named 設定成只做基本的名稱解析伺服器,運作於 chroot(8) 環境中,並限制只傾聽本地 IPv4 loopback 位址 (127.0.0.1),若只要使用這個設定啟動伺服器一次可使用以下指令:

# service named onestart

要讓 named 在每次開機都會啟動,可加入下行到 /etc/rc.conf

named_enable="YES"

還有許多 /etc/namedb/named.conf 的設定選項以超出本文章的範圍,named 其他在 FreeBSD 上的啟動選項可在 /etc/defaults/rc.conf 與在 rc.conf(5) 中尋找 named_* 項目,也建議閱讀 節 11.4, “管理 FreeBSD 中的服務” 一節。

28.7.3.2. 設定檔

named 的設定檔目前儲存在 /etc/namedb 目錄中且使用前必須先做修改,除非您只需要它做簡單的解析,這也是需要做最多設定的地方。

28.7.3.2.1. /etc/namedb/named.conf
// $FreeBSD: head/zh_TW.UTF-8/books/handbook/book.xml 51147 2017-10-26 15:25:09Z rcyu $
//
// Refer to the named.conf(5) and named(8) man pages, and the documentation
// in /usr/share/doc/bind9 for more details.
//
// If you are going to set up an authoritative server, make sure you
// understand the hairy details of how DNS works.  Even with
// simple mistakes, you can break connectivity for affected parties,
// or cause huge amounts of useless Internet traffic.

options {
	// All file and path names are relative to the chroot directory,
	// if any, and should be fully qualified.
	directory	"/etc/namedb/working";
	pid-file	"/var/run/named/pid";
	dump-file	"/var/dump/named_dump.db";
	statistics-file	"/var/stats/named.stats";

// If named is being used only as a local resolver, this is a safe default.
// For named to be accessible to the network, comment this option, specify
// the proper IP address, or delete this option.
	listen-on	{ 127.0.0.1; };

// If you have IPv6 enabled on this system, uncomment this option for
// use as a local resolver.  To give access to the network, specify
// an IPv6 address, or the keyword "any".
//	listen-on-v6	{ ::1; };

// These zones are already covered by the empty zones listed below.
// If you remove the related empty zones below, comment these lines out.
	disable-empty-zone "255.255.255.255.IN-ADDR.ARPA";
	disable-empty-zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";
	disable-empty-zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";

// If you have a DNS server around at your upstream provider, enter
// its IP address here, and enable the line below.  This will make you
// benefit from its cache, thus reduce overall DNS traffic in the Internet.
/*
	forwarders {
		127.0.0.1;
	};
*/

// If the 'forwarders' clause is not empty the default is to 'forward first'
// which will fall back to sending a query from your local server if the name
// servers in 'forwarders' do not have the answer.  Alternatively you can
// force your name server to never initiate queries of its own by enabling the
// following line:
//	forward only;

// If you wish to have forwarding configured automatically based on
// the entries in /etc/resolv.conf, uncomment the following line and
// set named_auto_forward=yes in /etc/rc.conf.  You can also enable
// named_auto_forward_only (the effect of which is described above).
//	include "/etc/namedb/auto_forward.conf";

如同註解所述,要利用上游的快取功能,可以在此啟動 forwarders,正常的情況下,名稱伺服器會在網際網路上做遞迴查詢來尋找特定名稱伺服器,直到找到要查詢的答案,開啟快取功能會讓名稱伺服器先查詢上游的名稱伺服器 (或自行設定的名稱伺服器) 來利用該伺服器的快取,若查詢的上游名稱伺服器是有規模營運且快速的名稱伺服器,則開啟此功能是相當值得的。

警告:

在此處使用 127.0.0.1沒有作用,請更改此 IP 位址為上游的名稱伺服器。

	/*
	   Modern versions of BIND use a random UDP port for each outgoing
	   query by default in order to dramatically reduce the possibility
	   of cache poisoning.  All users are strongly encouraged to utilize
	   this feature, and to configure their firewalls to accommodate it.

	   AS A LAST RESORT in order to get around a restrictive firewall
	   policy you can try enabling the option below.  Use of this option
	   will significantly reduce your ability to withstand cache poisoning
	   attacks, and should be avoided if at all possible.

	   Replace NNNNN in the example with a number between 49160 and 65530.
	*/
	// query-source address * port NNNNN;
};

// If you enable a local name server, do not forget to enter 127.0.0.1
// first in your /etc/resolv.conf so this server will be queried.
// Also, make sure to enable it in /etc/rc.conf.

// The traditional root hints mechanism. Use this, OR the slave zones below.
zone "." { type hint; file "/etc/namedb/named.root"; };

/*	Slaving the following zones from the root name servers has some
	significant advantages:
	1. Faster local resolution for your users
	2. No spurious traffic will be sent from your network to the roots
	3. Greater resilience to any potential root server failure/DDoS

	On the other hand, this method requires more monitoring than the
	hints file to be sure that an unexpected failure mode has not
	incapacitated your server.  Name servers that are serving a lot
	of clients will benefit more from this approach than individual
	hosts.  Use with caution.

	To use this mechanism, uncomment the entries below, and comment
	the hint zone above.

	As documented at http://dns.icann.org/services/axfr/ these zones:
	"." (the root), ARPA, IN-ADDR.ARPA, IP6.ARPA, and ROOT-SERVERS.NET
	are available for AXFR from these servers on IPv4 and IPv6:
	xfr.lax.dns.icann.org, xfr.cjr.dns.icann.org
*/
/*
zone "." {
	type slave;
	file "/etc/namedb/slave/root.slave";
	masters {
		192.5.5.241;	// F.ROOT-SERVERS.NET.
	};
	notify no;
};
zone "arpa" {
	type slave;
	file "/etc/namedb/slave/arpa.slave";
	masters {
		192.5.5.241;	// F.ROOT-SERVERS.NET.
	};
	notify no;
};
*/

/*	Serving the following zones locally will prevent any queries
	for these zones leaving your network and going to the root
	name servers.  This has two significant advantages:
	1. Faster local resolution for your users
	2. No spurious traffic will be sent from your network to the roots
*/
// RFCs 1912 and 5735 (and BCP 32 for localhost)
zone "localhost"	{ type master; file "/etc/namedb/master/localhost-forward.db"; };
zone "127.in-addr.arpa"	{ type master; file "/etc/namedb/master/localhost-reverse.db"; };
zone "255.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };

// RFC 1912-style zone for IPv6 localhost address
zone "0.ip6.arpa"	{ type master; file "/etc/namedb/master/localhost-reverse.db"; };

// "This" Network (RFCs 1912 and 5735)
zone "0.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };

// Private Use Networks (RFCs 1918 and 5735)
zone "10.in-addr.arpa"	   { type master; file "/etc/namedb/master/empty.db"; };
zone "16.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "17.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "18.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "19.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "20.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "21.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "22.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "23.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "24.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "25.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "26.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "27.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "28.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "29.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "30.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "31.172.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "168.192.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };

// Link-local/APIPA (RFCs 3927 and 5735)
zone "254.169.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };

// IETF protocol assignments (RFCs 5735 and 5736)
zone "0.0.192.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };

// TEST-NET-[1-3] for Documentation (RFCs 5735 and 5737)
zone "2.0.192.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "100.51.198.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "113.0.203.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };

// IPv6 Range for Documentation (RFC 3849)
zone "8.b.d.0.1.0.0.2.ip6.arpa" { type master; file "/etc/namedb/master/empty.db"; };

// Domain Names for Documentation and Testing (BCP 32)
zone "test" { type master; file "/etc/namedb/master/empty.db"; };
zone "example" { type master; file "/etc/namedb/master/empty.db"; };
zone "invalid" { type master; file "/etc/namedb/master/empty.db"; };
zone "example.com" { type master; file "/etc/namedb/master/empty.db"; };
zone "example.net" { type master; file "/etc/namedb/master/empty.db"; };
zone "example.org" { type master; file "/etc/namedb/master/empty.db"; };

// Router Benchmark Testing (RFCs 2544 and 5735)
zone "18.198.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };
zone "19.198.in-addr.arpa" { type master; file "/etc/namedb/master/empty.db"; };

// IANA Reserved - Old Class E Space (RFC 5735)
zone "240.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "241.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "242.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "243.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "244.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "245.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "246.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "247.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "248.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "249.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "250.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "251.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "252.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "253.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "254.in-addr.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };

// IPv6 Unassigned Addresses (RFC 4291)
zone "1.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "3.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "4.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "5.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "6.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "7.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "8.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "9.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "a.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "b.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "c.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "d.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "e.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "0.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "1.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "2.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "3.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "4.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "5.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "6.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "7.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "8.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "9.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "a.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "b.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "0.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "1.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "2.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "3.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "4.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "5.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "6.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "7.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };

// IPv6 ULA (RFC 4193)
zone "c.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "d.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };

// IPv6 Link Local (RFC 4291)
zone "8.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "9.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "a.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "b.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };

// IPv6 Deprecated Site-Local Addresses (RFC 3879)
zone "c.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "d.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "e.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };
zone "f.e.f.ip6.arpa"	{ type master; file "/etc/namedb/master/empty.db"; };

// IP6.INT is Deprecated (RFC 4159)
zone "ip6.int"		{ type master; file "/etc/namedb/master/empty.db"; };

// NB: Do not use the IP addresses below, they are faked, and only
// serve demonstration/documentation purposes!
//
// Example slave zone config entries.  It can be convenient to become
// a slave at least for the zone your own domain is in.  Ask
// your network administrator for the IP address of the responsible
// master name server.
//
// Do not forget to include the reverse lookup zone!
// This is named after the first bytes of the IP address, in reverse
// order, with ".IN-ADDR.ARPA" appended, or ".IP6.ARPA" for IPv6.
//
// Before starting to set up a master zone, make sure you fully
// understand how DNS and BIND work.  There are sometimes
// non-obvious pitfalls.  Setting up a slave zone is usually simpler.
//
// NB: Do not blindly enable the examples below. :-)  Use actual names
// and addresses instead.

/* An example dynamic zone
key "exampleorgkey" {
	algorithm hmac-md5;
	secret "sf87HJqjkqh8ac87a02lla==";
};
zone "example.org" {
	type master;
	allow-update {
		key "exampleorgkey";
	};
	file "/etc/namedb/dynamic/example.org";
};
*/

/* Example of a slave reverse zone
zone "1.168.192.in-addr.arpa" {
	type slave;
	file "/etc/namedb/slave/1.168.192.in-addr.arpa";
	masters {
		192.168.1.1;
	};
};
*/

named.conf 中,這些為正向與反向轄區的備援 (Slave) 項目範例。

每一個要提供的新轄區 (Zone),都必須在 named.conf 加入新轄區的項目。

以最簡單的轄區項目 example.org 來舉例:

zone "example.org" {
	type master;
	file "master/example.org";
};

該轄區的角色為主要 (Master),使用 type 述敘句來指定,該轄區的資訊會儲存在 /etc/namedb/master/example.org,使用 file 述敘句來指定。

zone "example.org" {
	type slave;
	file "slave/example.org";
};

若為次要轄區,則會由主要名稱伺服器接收特定轄區的轄區資訊,並儲存到指定的檔案,若主要伺服器故障或無法連線,次要名稱伺服器會有先前接收過的轄區資訊可用來繼續提供服務。

28.7.3.2.2. 轄區檔案

example.org 的主要轄區檔範例 (位於 /etc/namedb/master/example.org) 如下:

$TTL 3600        ; 1 hour default TTL
example.org.    IN      SOA      ns1.example.org. admin.example.org. (
                                2006051501      ; Serial
                                10800           ; Refresh
                                3600            ; Retry
                                604800          ; Expire
                                300             ; Negative Response TTL
                        )

; DNS Servers
                IN      NS      ns1.example.org.
                IN      NS      ns2.example.org.

; MX Records
                IN      MX 10   mx.example.org.
                IN      MX 20   mail.example.org.

                IN      A       192.168.1.1

; Machine Names
localhost       IN      A       127.0.0.1
ns1             IN      A       192.168.1.2
ns2             IN      A       192.168.1.3
mx              IN      A       192.168.1.4
mail            IN      A       192.168.1.5

; Aliases
www             IN      CNAME   example.org.

注意,每個有以 . 號結尾的主機是完整的主機名稱,也就是說,若沒有以 . 結尾則是該源頭 (Origin) 的相對主機名稱。例如 ns1 會被轉換成 ns1.example.org.

轄區檔案的格式如下:

recordname      IN recordtype   value

最常用到的 DNS 記錄有:

SOA

開始轄區授權 (Authority)

NS

一台有權的名稱伺服器

A

主機位址

CNAME

別名的正規名稱 (Canonical name)

MX

郵件交換器 (Mail exchanger)

PTR

網域名稱指標 (用在反向 DNS)

example.org. IN SOA ns1.example.org. admin.example.org. (
                        2006051501      ; Serial
                        10800           ; Refresh after 3 hours
                        3600            ; Retry after 1 hour
                        604800          ; Expire after 1 week
                        300 )           ; Negative Response TTL
example.org.

網域名稱,也同樣是此轄區檔案的源頭 (Origin)。

ns1.example.org.

此轄區主要/有權的名稱伺服器。

admin.example.org.

此轄區的負責人,將 @ 取代後的電子郵件位址。 ( 會變成 admin.example.org)

2006051501

該檔案的序號,每次修改轄區檔案之後應該增加此序號,目前許多管理者會偏好採用 yyyymmddrr 格式來編號,如 2006051501 代表最後一次修改於 2006 年 5 月 15 號,再後面的 01 代表這是在那一天做的第一次修改,序號的編號很重要,因為它會在更新轄區之後用來通知備援 (Slave) 的名稱伺服器。

       IN NS           ns1.example.org.

這是一個 NS 項目,每個要有權力能做回覆的名稱伺服器必須具有至少設定一個項目。

localhost       IN      A       127.0.0.1
ns1             IN      A       192.168.1.2
ns2             IN      A       192.168.1.3
mx              IN      A       192.168.1.4
mail            IN      A       192.168.1.5

A 記錄代表主機名稱,以上述例子來說,ns1.example.org 會解析為 192.168.1.2

                IN      A       192.168.1.1

這行會分配 IP 位址 192.168.1.1 給目前的源頭 (Origin),在這個例子為 example.org

www             IN CNAME        @

canonical name 記錄通常用來替主機設定別名,在這個例子中 wwwmaster 主機的別名,其名稱會與網域名稱 example.org (192.168.1.1) 相同。CNAME 不能與其他類型的記錄同時用在一個主機上。

               IN MX   10      mail.example.org.

MX 記錄用來指定該轄區要負責處理內寄郵件的郵件伺服器,mail.example.org 是郵件伺服器的主機名稱,而 10 是該郵件伺服器的優先順序。

一個轄區可以有很多台郵件伺服器,每一台使用不同的優先順序 10, 20 以此類推,一台郵件伺服器嘗試要寄件給 example.org 會先嘗試優先順序最高的 MX (優先順序數字最低的記錄),然後第二高的,接著繼續,直到郵件被寄出。

in-addr.arpa 轄區檔案 (反向 DNS) 也使用相同的格式,除了項目要改使用 PTR 而非 A 或 CNAME。

$TTL 3600

1.168.192.in-addr.arpa. IN SOA ns1.example.org. admin.example.org. (
                        2006051501      ; Serial
                        10800           ; Refresh
                        3600            ; Retry
                        604800          ; Expire
                        300 )           ; Negative Response TTL

        IN      NS      ns1.example.org.
        IN      NS      ns2.example.org.

1       IN      PTR     example.org.
2       IN      PTR     ns1.example.org.
3       IN      PTR     ns2.example.org.
4       IN      PTR     mx.example.org.
5       IN      PTR     mail.example.org.

這個檔案會對上述虛擬網域給予 IP 位置到主機名稱的正確對應表。

值得注意的是,所有在 PTR 記錄右邊的名字必須要是完整的 (即以 . 結尾)。

28.7.3.3. 快取名稱伺服器

快取名稱伺服器是一種主要用來解析遞迴查詢的名稱伺服器,它只會詢問自己的查詢並記住結果供以後使用。

28.7.3.4. DNSSEC

網域名稱系統安全性擴充 (Domain Name System Security Extension),或簡稱 DNSSEC,是一套規範,用來保護解析名稱伺服器收到偽造的 DNS 資料,如:假 DNS 記錄,利用數位簽章,解析器可以驗証記錄的正確性。注意,DNSSEC 只提供透過數位簽署資源記錄 (Resource Records, RR) 的方式來確認正確性,這代表它無法保護要前往 example.net 但卻跑去 example.com 的使用者,DNSSEC 所做的唯一一件事便是認証資料在傳輸時沒有被竄改。DNS 的安全性是保護網際網路重要的一步,要取得更進一步有關 DNSSEC 如何運作的資訊可從相關的 RFC 文件開始,請參考 節 28.7.3.6, “延伸閱讀” 清單。

接下來的章節會示範如何在一台運行 BIND 9 的有權的 DNS 伺服器與遞迴 (或快取) DNS 伺服器開啟 DNSSEC。雖然所有 BIND 9 的版本階支援 DNSSEC,但要能夠在驗証 DNS 查詢時使用已簽署的根轄區必須使用版本 9.6.2 以上,這是因為較先前的版本缺少必要的演算法來開啟使用根轄區金鑰驗證的功能,強烈建議使用 BIND 9.7 的最新版本或之後的版本以支援根金鑰的自動自動金鑰更新以及自動確保轄區已簽署與更新簽名為最新版的功能,9.6.2 與 9.7 之後版本的設定會有一些差異,差異點會再特別說明。

28.7.3.4.1. Recursive DNS Server Configuration

需要對 named.conf 做一些修改才能開啟遞迴 DNS 伺服器執行查詢 DNSSEC 的驗証,在做這更改前,必須先取得根轄區金鑰或信任的錨點 (Anchor),目前 BIND 可用的檔案格式不支援根轄區金鑰 (Root zone key),因此必須手動轉換為需要的格式,金鑰本身可使用 dig 查詢根轄區來取得,透過執行

% dig +multi +noall +answer DNSKEY . > root.dnskey

金鑰會儲存到 root.dnskey,其內容應會如下:

. 93910 IN DNSKEY 257 3 8 (
	AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ
	bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh
	/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWA
	JQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXp
	oY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3
	LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGO
	Yl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGc
	LmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=
	) ; key id = 19036
. 93910 IN DNSKEY 256 3 8 (
	AwEAAcaGQEA+OJmOzfzVfoYN249JId7gx+OZMbxy69Hf
	UyuGBbRN0+HuTOpBxxBCkNOL+EJB9qJxt+0FEY6ZUVjE
	g58sRr4ZQ6Iu6b1xTBKgc193zUARk4mmQ/PPGxn7Cn5V
	EGJ/1h6dNaiXuRHwR+7oWh7DnzkIJChcTqlFrXDW3tjt
) ; key id = 34525

若取得的金鑰與此範例不同不要感到訝異,可能在最後一次更新這些操作指示之後有更改過,這個輸出結果實際上包含了兩組金鑰,在清單中的第一組金鑰,即在 DNSKEY 記錄類型之後有數值 257 的這組,是我們需要的,這個數值代表該金鑰是一個 Secure Entry Point (SEP)、俗稱 Key Signing Key (KSK)。第二組金鑰,數值為 256,這是一個附屬金鑰,俗稱 Zone Signing Key (ZSK)。更多有關不同金鑰類型的資訊之後在 節 28.7.3.4.2, “Authoritative DNS Server Configuration” 會說明。

現在必須驗証這個金鑰並格式化才可供 BIND 使用。產生 DS RR 集來驗証這個金鑰,使用以下指令建立一個包含這些 RR 的檔案

% dnssec-dsfromkey -f root.dnskey . > root.ds

這些記錄分別使用 SHA-1 與 SHA-256,且如下範例所示,使用 SHA-256 的段落較長。

.  IN DS 19036 8 1
	B256BD09DC8DD59F0E0F0D8541B8328DD986DF6E
. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5

SHA-256 RR 現在可以與在 https://data.iana.org/root-anchors/root-anchors.xml 中的 digest 比對。要完全確保該金鑰沒有被竄改,XML 檔案中的資料應使用正確的 PGP 簽名來驗證。

接著,金鑰必須正確的格式化,BIND 版本 9.6.2 與 9.7 及之後的版本有一些不同,在版本 9.7 開始支援自動追蹤對金鑰的變更並在需要的時候更新,這可使用 managed-keys 如下範例所示來達成。若使用較舊的版本,金鑰必須使用 trusted-keys 敘述加入且必須手動更新,供 BIND 9.6.2 的格式如下:

trusted-keys {
	"." 257 3 8
	"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF
	FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX
	bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD
	X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz
	W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS
	Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq
	QxA+Uk1ihz0=";
};

供 9.7 的格式則為:

managed-keys {
	"." initial-key 257 3 8
	"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF
	FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX
	bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD
	X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz
	W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS
	Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq
	QxA+Uk1ihz0=";
};

現在可以直接或透過引用包含金鑰的檔案將根金鑰 (Root key) 加入到 named.conf,完成這些步驟後,編輯 named.conf 來設定 BIND 執行 DNSSEC 在查詢時驗證並加入以下項目到 options 指示項目中:

dnssec-enable yes;
dnssec-validation yes;

To verify that it is actually working use dig to make a query for a signed zone using the resolver just configured. A successful reply will contain the AD flag to indicate the data was authenticated. Running a query such as

% dig @resolver +dnssec se ds 

should return the DS RR for the .se zone. In the flags: section the AD flag should be set, as seen in:

...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
...

The resolver is now capable of authenticating DNS queries.

28.7.3.4.2. Authoritative DNS Server Configuration

In order to get an authoritative name server to serve a DNSSEC signed zone a little more work is required. A zone is signed using cryptographic keys which must be generated. It is possible to use only one key for this. The preferred method however is to have a strong well-protected Key Signing Key (KSK) that is not rotated very often and a Zone Signing Key (ZSK) that is rotated more frequently. Information on recommended operational practices can be found in RFC 4641: DNSSEC Operational Practices. Practices regarding the root zone can be found in DNSSEC Practice Statement for the Root Zone KSK operator and DNSSEC Practice Statement for the Root Zone ZSK operator. The KSK is used to build a chain of authority to the data in need of validation and as such is also called a Secure Entry Point (SEP) key. A message digest of this key, called a Delegation Signer (DS) record, must be published in the parent zone to establish the trust chain. How this is accomplished depends on the parent zone owner. The ZSK is used to sign the zone, and only needs to be published there.

To enable DNSSEC for the example.com zone depicted in previous examples, the first step is to use dnssec-keygen to generate the KSK and ZSK key pair. This key pair can utilize different cryptographic algorithms. It is recommended to use RSA/SHA256 for the keys and 2048 bits key length should be enough. To generate the KSK for example.com, run

% dnssec-keygen -f KSK -a RSASHA256 -b 2048 -n ZONE example.com

and to generate the ZSK, run

% dnssec-keygen -a RSASHA256 -b 2048 -n ZONE example.com

dnssec-keygen outputs two files, the public and the private keys in files named similar to Kexample.com.+005+nnnnn.key (public) and Kexample.com.+005+nnnnn.private (private). The nnnnn part of the file name is a five digit key ID. Keep track of which key ID belongs to which key. This is especially important when having more than one key in a zone. It is also possible to rename the keys. For each KSK file do:

% mv Kexample.com.+005+nnnnn.key Kexample.com.+005+nnnnn.KSK.key
% mv Kexample.com.+005+nnnnn.private Kexample.com.+005+nnnnn.KSK.private

For the ZSK files, substitute KSK for ZSK as necessary. The files can now be included in the zone file, using the $include statement. It should look something like this:

$include Kexample.com.+005+nnnnn.KSK.key ; KSK
$include Kexample.com.+005+nnnnn.ZSK.key    ; ZSK

Finally, sign the zone and tell BIND to use the signed zone file. To sign a zone dnssec-signzone is used. The command to sign the zone example.com, located in example.com.db would look similar to

% dnssec-signzone -o example.com -k Kexample.com.+005+nnnnn.KSK example.com.db Kexample.com.+005+nnnnn.ZSK.key

The key supplied to the -k argument is the KSK and the other key file is the ZSK that should be used in the signing. It is possible to supply more than one KSK and ZSK, which will result in the zone being signed with all supplied keys. This can be needed to supply zone data signed using more than one algorithm. The output of dnssec-signzone is a zone file with all RRs signed. This output will end up in a file with the extension .signed, such as example.com.db.signed. The DS records will also be written to a separate file dsset-example.com. To use this signed zone just modify the zone directive in named.conf to use example.com.db.signed. By default, the signatures are only valid 30 days, meaning that the zone needs to be resigned in about 15 days to be sure that resolvers are not caching records with stale signatures. It is possible to make a script and a cron job to do this. See relevant manuals for details.

Be sure to keep private keys confidential, as with all cryptographic keys. When changing a key it is best to include the new key into the zone, while still signing with the old one, and then move over to using the new key to sign. After these steps are done the old key can be removed from the zone. Failure to do this might render the DNS data unavailable for a time, until the new key has propagated through the DNS hierarchy. For more information on key rollovers and other DNSSEC operational issues, see RFC 4641: DNSSEC Operational practices.

28.7.3.4.3. Automation Using BIND 9.7 or Later

Beginning with BIND version 9.7 a new feature called Smart Signing was introduced. This feature aims to make the key management and signing process simpler by automating parts of the task. By putting the keys into a directory called a key repository, and using the new option auto-dnssec, it is possible to create a dynamic zone which will be resigned as needed. To update this zone use nsupdate with the new option -l. rndc has also grown the ability to sign zones with keys in the key repository, using the option sign. To tell BIND to use this automatic signing and zone updating for example.com, add the following to named.conf:

zone example.com {
	type master;
	key-directory "/etc/named/keys";
	update-policy local;
	auto-dnssec maintain;
	file "/etc/named/dynamic/example.com.zone";
};

After making these changes, generate keys for the zone as explained in 節 28.7.3.4.2, “Authoritative DNS Server Configuration”, put those keys in the key repository given as the argument to the key-directory in the zone configuration and the zone will be signed automatically. Updates to a zone configured this way must be done using nsupdate, which will take care of re-signing the zone with the new data added. For further details, see 節 28.7.3.6, “延伸閱讀” and the BIND documentation.

28.7.3.5. 安全性

Although BIND is the most common implementation of DNS, there is always the issue of security. Possible and exploitable security holes are sometimes found.

While FreeBSD automatically drops named into a chroot(8) environment; there are several other security mechanisms in place which could help to lure off possible DNS service attacks.

It is always good idea to read CERT's security advisories and to subscribe to the FreeBSD security notifications mailing list to stay up to date with the current Internet and FreeBSD security issues.

提示:

If a problem arises, keeping sources up to date and having a fresh build of named may help.

本文及其他文件,可由此下載: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/

若有 FreeBSD 方面疑問,請先閱讀 FreeBSD 相關文件,如不能解決的話,再洽詢 <questions@FreeBSD.org>。

關於本文件的問題,請洽詢 <doc@FreeBSD.org>。