30.6 域名系统 (DNS)

Contributed by Chern Lee、 Tom Rhodes 和 Daniel Gerzo.

30.6.1 纵览

  FreeBSD 在默认情况下使用一个版本的 BIND (Berkeley Internet Name Domain), 这是目前最为流行的 DNS 协议实现。 DNS 是一种协议, 可以通过它将域名同 IP 地址相互对应。 例如, 查询 www.FreeBSD.org 将得到 FreeBSD Project 的 web 服务器的 IP 地址, 而查询 ftp.FreeBSD.org 则将得到响应的 FTP 机器的 IP 地址。 类似地, 也可以做相反的事情。 查询 IP 地址可以得到其主机名。 当然, 完成 DNS 查询并不需要在系统中运行域名服务器。

  目前, 默认情况下FreeBSD 使用的是 BIND9 DNS 服务软件。 我们内建于系统中的版本提供了增强的安全特性、 新的文件目录结构, 以及自动的 chroot(8) 配置。

  在 Internet 上的 DNS 是通过一套较为复杂的权威根域名系统, 顶级域名 (TLD), 以及一系列小规模的, 提供少量域名解析服务并对域名信息进行缓存的域名服务器组成的。

  目前, BIND 由 Internet Systems Consortium https://www.isc.org/ 维护。

30.6.2 术语

  要理解这份文档, 需要首先了解一些相关的 DNS 术语。

术语 定义
正向 DNS 将域名映射到 IP 地址
原点 (Origin) 表示特定域文件所在的域
named, BIND 在 FreeBSD 中 BIND 域名服务器软件包的常见叫法。
解析器 (Resolver) 计算机用以向域名服务器查询域名信息的一个系统进程
反向 DNS IP 地址映射为主机名
根域 Internet 域层次的起点。 所有的域都在根域之下, 类似文件系统中, 文件都在根目录之下那样。
域 (Zone) 独立的域, 子域, 或者由同一机构管理的 DNS 的一部分。

  域的例子:

  如您所见, 域名中越细节的部分会越靠左出现。 例如, example.org. 就比 org. 范围更小, 类似地 org. 又比根域更小。 域名各个部分的格局与文件系统十分类似: /dev 目录在根目录之下, 等等。

30.6.3 运行域名服务器的理由

  域名服务器通常会有两种形式: 权威域名服务器, 以及缓存域名(也称解析)服务器。

  下列情况需要有权威域名服务器:

  下列情况需要有缓存域名服务器:

  当有人查询 www.FreeBSD.org 时,解析器通常会向上级 ISP 的域名服务器发出请求, 并获得回应。 如果有本地的缓存 DNS 服务器, 查询只有在第一次被缓存 DNS 服务器发到外部世界。 其他的查询不会发向局域网外, 因为它们已经有在本地的缓存了。

30.6.4 DNS 如何运作

  在 FreeBSD 中, BIND 服务程序被称为 named

文件 描述
named(8) BIND 服务程序
rndc(8) 域名服务控制程序
/etc/namedb BIND 存放域名信息的位置。
/etc/namedb/named.conf 域名服务配置文件

  随在服务器上配置的域的性质不同, 域的定义文件一般会存放到 /etc/namedb 目录中的 masterslave, 或 dynamic 子目录中。 这些文件中提供了域名服务器在响应查询时所需要的 DNS 信息。

30.6.5 启动 BIND

  由于 BIND 是默认安装的, 因此配置它相对而言很简单。

  默认的 named 配置, 是在 chroot(8) 环境中提供基本的域名解析服务, 并且只限于监听本地 IPv4 回环地址 (127.0.0.1)。 如果希望启动这一配置, 可以使用下面的命令:

# /etc/rc.d/named onestart

  如果希望 named 服务在每次启动的时候都能够启动, 需要在 /etc/rc.conf 中加入:

named_enable="YES"

  当然, 除了这份文档所介绍的配置选项之外, 在 /etc/namedb/named.conf 中还有很多其它的选项。 不过, 如果您需要了解 FreeBSD 中用于启动 named 的那些选项的话, 则可以查看 /etc/defaults/rc.conf 中的 named_* 参数, 并参考 rc.conf(5) 联机手册。 除此之外, 第 12.7 节 也是一个不错的起点。

30.6.6 配置文件

  目前, named 的配置文件存放于 /etc/namedb 目录, 在使用前应根据需要进行修改, 除非您只打算让它完成简单的域名解析服务。 这个目录同时也是您进行绝大多数配置的地方。

30.6.6.1 /etc/namedb/named.conf

// $FreeBSD$
//
// 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've got 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。 正常情况下, 域名服务器会逐级地查询 Internet 来找到特定的域名服务器, 直到得到答案为止。 这个选项将让它首先查询上级域名服务器 (或另外提供的域名服务器), 从而从它们的缓存中得到结果。 如果上级域名服务器是一个繁忙的高速域名服务器, 则启用它将有助于改善服务品质。

警告: 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, don't 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 availble 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: Don't 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 中, 还给出了从域、转发域和反解析域的例子。

  如果新增了域, 就必需在 named.conf 中加入对应的项目。

  例如, 用于 example.org 的域文件的描述类似下面这样:

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

  如 type 语句所标示的那样, 这是一个主域, 其信息保存在 /etc/namedb/master/example.org 中, 如 file 语句所示。

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

  在从域的情形中, 所指定的域的信息会从主域名服务器传递过来, 并保存到对应的文件中。 当主域服务器发生问题或不可达时, 从域名服务器就有一份可用的域名信息, 从而能够对外提供服务。

30.6.6.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.

  请注意以 “.” 结尾的主机名是全称主机名, 而结尾没有 “.” 的则是相对于原点的主机名。 例如, ns1 将被转换为 ns1.example.org.

  域信息文件的格式如下:

记录名          IN 记录类型     值

  最常用的 DNS 记录:

SOA

域权威开始

NS

权威域名服务器

A

主机地址

CNAME

别名对应的正规名称

MX

邮件传递服务器

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.

域名, 同时也是这个域信息文件的原点。

ns1.example.org.

该域的主/权威域名服务器。

admin.example.org.

此域的负责人的电子邮件地址, 其中 “@” 需要换掉 ( 对应 admin.example.org)

2006051501

文件的序号。 每次修改域文件时都必须增加这个数字。 现今, 许多管理员会考虑使用 yyyymmddrr 这样的格式来表示序号。 2006051501 通常表示上次修改于 05/15/2006, 而后面的 01 则表示在那天的第一次修改。 序号非常重要, 它用于通知从域服务器更新数据。

       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

  这一行把当前原点 example.org 指定为使用 IP 地址 192.168.1.1

www             IN CNAME        @

  正规名 (CNAME) 记录通常用于为某台机器指定别名。 在这个例子中, 将 www 指定成了 “主” 机器的一个别名, 后者的名字与域名 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 记录右侧的名字必须是全称域名 (也就是必须以 “.” 结束)。

30.6.7 缓存域名服务器

  缓存域名服务器是一种主要承担解析递归查询角色的域名服务器。 它简单地自行进行查询, 并将查询结果记住以备后续使用。

30.6.8 DNSSEC

  域名系统安全扩展 (Domain Name System Security Extensions), 或简写为 DNSSEC, 是一组用于保护域名解析服务器不受伪造的 DNS 数据, 例如伪造的 DNS 记录影响的安全协议。 通过使用数字签名, 解析服务起可以验证记录的完整性。 需要注意的是, DNSSEC 只提供资源记录 Resource Record (RR) 的数字签名完整性验证。 它并不提供保密性, 也不能阻止最终用户免受钓鱼网站的侵害。 也就是说, 它并不能阻止用户错误地访问 example.net 而不是他们所希望的 example.comDNSSEC 只能验证数据没有在传输过程中遭到篡改。 DNS 的安全性是 Internet 安全性的重要一环。 如果希望深入了解关于 DNSSEC 的运作原理, 相关的 RFC 会是很好的开始。 请参阅 第 30.6.10 节 的列表。

  下面一节将介绍如何为运行 BIND 9 的权威 DNS 服务器和解析 (缓存) DNS 服务器启用 DNSSEC。 虽然所有版本的 BIND 9 都支持 DNSSEC, 但您需要使用不低于 9.6.2 的版本才能在验证 DNS 查询时使用签名过的根域, 这是因为更早的版本缺少启用根域验证所需的算法支持。 此外, 强烈建议您使用 BIND 9.7 或更新系列的最新版本, 因为它们支持自动更新根公钥, 并提供了包括自动更新域签名等功能。 当 9.6.2 和 9.7 的配置存在差异时, 我们会特别指出。

30.6.8.1 递归解析 DNS 服务器的配置

  为解析 DNS 服务器启用 DNSSEC 验证需要对 named.conf 的配置做一些改动。 在做这些改动之前, 您需要首先获得根域公钥, 或授信源 (trust anchor)。 目前, 根域公钥没有以 BIND 能够识别的格式提供, 因此需要手工将其转换为需要的格式。 您可以用 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)。 关于公钥类型的更多介绍请参考稍后的 第 30.6.8.2 节

  接下来需要验证这个公钥的有效性, 并将其改为 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 中公布的比对。 如果希望进一步确认这个 XML 文件中的数据没有被篡改, 还使用位于 https://data.iana.org/root-anchors/root-anchors.ascPGP 签名来验证。

  接下来, 需要修改公钥的格式。 在 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=";
};

  可以在 named.conf 中直接添加公钥, 也可以使用另外的文件保存它。 在完成这些操作之后, 就可以配置 BIND 来启用查询的 DNSSEC 验证了, 具体做法是编辑 named.conf 并在其中添加下列 options 语句:

dnssec-enable yes;
dnssec-validation yes;

  要验证它已经正常工作, 可以用 dig 来通过刚配置好的解析服务器来查询一个签名的域。 如果成功的话, 回应应包含 AD 标志来表示验证通过。 运行类似下面的查询:

% dig @resolver +dnssec se ds 

  应返回 .se 域的 DS RR。 在 flags: 部分应该有 AD 标志, 类似下面这样:

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

  现在这台解析服务器已经可以验证 DNS 查询了。

30.6.8.2 权威 DNS 服务器配置

  将权威域名服务器配置为提供 DNSSEC 签名的域需要一些额外的工作。 域需要使用密钥来签名, 因此需要首先生成密钥。 完成这项工作可以只使用一个密钥。 不过, 强烈推荐的做法是使用一个不经常更换的强公钥签名公钥 Key Signing Key (KSK), 以及一个经常更换的域签名公钥 Zone Signing Key (ZSK)。 关于推荐的运营实践, 请参阅 RFC 4641: DNSSEC Operational Practices。 关于根域采用的运营实践在 DNSSEC Practice Statement for the Root Zone KSK operatorDNSSEC Practice Statement for the Root Zone ZSK operator 中有所介绍。 KSK 用于构建信任链, 也称作安全入口 Secure Entry Point (SEP) 公钥。 这个 key 的消息摘要称为签名代理 Delegation Signer (DS) 记录, 必须在父域发布以构成信任链。 如何完成这项工作取决于父域的所有者。 ZSK 用来对域签名, 也只需随域发布。

  要为 example.com 启用 DNSSEC, 首先需要用 dnssec-keygen 来生成 KSKZSK 密钥对。 这个密钥对可以使用不同的密码学算法。 推荐为密钥使用 RSA/SHA256, 长度为 2048 位的密钥应该足够了。 要生成 example.comKSK运行:

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

  接着生成 ZSK, 运行:

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

  dnssec-keygen 输出两个文件, 公钥和私钥的文件名类似于 Kexample.com.+005+nnnnn.key (公钥) 和 Kexample.com.+005+nnnnn.private (私钥)。 文件名中的 nnnnn 部分是五位的密钥 ID。 您应记录哪个密钥 ID 对应于哪个密钥。 对于采用多个密钥的域来说, 这一点尤为重要。 此外, 您可以重命名这些密钥。 对每一个 KSK 文件, 运行:

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

  对于 ZSK 文件, 将 KSK 相应改为 ZSK。 这些文件现在可以使用 $include 语句来引入到域的定义中了, 类似这样:

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

  最后, 对域进行签名并告诉 BIND 使用签名后的域文件。 对域进行签名的工具是 dnssec-signzone。 用于对位于 example.com.dbexample.com 域签名的命令如下:

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

  其中 -k 参数指定的是 KSK 而另一个密钥文件, 也就是 ZSK 则用于实际的签名。 可以指定多个 KSKZSK, 这样做会令域以全部指定的密钥签名, 如果需要使用超过一种算法来签名域数据, 就需要如此操作。 dnssec-signzone 的输出是包含全部签名 RR 的域文件。 输出结果会以 .signed 为扩展名, 例如 example.com.db.signedDS 记录也会写入一个单独的文件 dsset-example.com。 要使用这个签名域, 只需修改 named.conf 中的 zone 语句使用 example.com.db.signed。 默认情况下, 签名的有效期为 30 天, 也就是说每 15 天就需要重新签名, 以确保解析服务器不缓存包含过期签名的记录。 可以使用脚本和 cron 任务来完成这项工作, 请参阅相关的联机手册以了解进一步的细节。

  和任何密钥类似, 您应务必确保私钥是机密的。 当更换密钥时, 最好将其加入到域中, 使用旧密钥签名, 然后再改为使用新密钥签名。 在完成这些步骤之后再从域中删去旧密钥。 如果不这样做, 可能会导致在新密钥在 DNS 中散步开之前的那段时间无法解析域名。 关于密钥更换和其他 DNSSEC 运营问题的讨论, 请参阅 RFC 4641: DNSSEC Operational practices

30.6.8.3 使用 BIND 9.7 和更高版本的自动化操作

  从 BIND 版本 9.7 开始, 引入来一项称为 智能签名 的新功能。 这个功能期望通过自动化一些部分来简化密钥管理和签名操作。 通过把密钥放入 密钥库, 并使用新增的 auto-dnssec 选项, 可以创建会根据需要自动重签名的动态域。 要更新这个域, 可以使用 nsupdate 新增的 -l 选项。 rndc 也新增了使用密钥库中的密钥对域进行签名的 sign 选项。 如果希望 BIND 使用这种自动签名和更新方法来维护 example.com, 在 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";
};

  完成这些改动之后, 按照 第 30.6.8.2 节 中介绍的方法生成密钥, 将它们放到前面 key-directory 参数指定的密钥库中, 域就会自动签名了。 这种方式配置的域必须使用 nsupdate 来进行更新, 因为它需要处理重签名等操作。 更多细节, 请参阅 第 30.6.10 节 以及 BIND 文档。

30.6.9 安全

  尽管 BIND 是最为常用的 DNS 实现, 但它总是有一些安全问题。 时常会有人发现一些可能的甚至可以利用的安全漏洞。

  尽管 FreeBSD 会自动将 named 放到 chroot(8) 环境中运行, 但仍有一些其它可用的安全机制来帮助您规避潜在的针对 DNS 服务的攻击。

  阅读 CERT 的安全公告, 并订阅 the FreeBSD 安全问题通知邮件列表 是一个有助于帮助您了解最新 Internet 及 FreeBSD 安全问题的好习惯。

提示: 如果发现了问题, 确保源代码是最新的, 并重新联编一份 named 有可能会有所帮助。

30.6.10 进一步阅读

  BIND/named 联机手册: rndc(8) named(8) named.conf(5) nsupdate(8) dnssec-signzone(8) dnssec-keygen(8)

本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.