ISC的bind一直以来基本上都是DNS的工业标准,不过BIND一直是漏洞不断,直到出了BIND9,isc的开发人员对bind9进行了重写,才相对好了一点。
BIND9的安装就不用多说了,这里使用最新版本9.2.3,说白了也就是需要named这个可执行文件就可以了,其他的配置文件完全可以自己来写。如果需要进行服务的控制的话,则需要rndc这个文件了。named大约有4M多,strip一下也就1M多点,再裁减裁减完全可以做到400K的,做嵌入式的朋友也不妨考虑考虑这个了。
服务的启动与停止可以完全自己来写一个脚本来控制,启动的话先判断是否已经启动,pidof named
,如果已经启动,则提示已经启动,否则执行named –c /etc/named.conf
,停止的时候先判断是否已经启动,是的话则killproc named
,否的话提示没有启动,具体可在网上查找。
下面重点来说说BIND9的新功能.
named.conf
是bind9
的最先读取的一个文件,named
支持如下语句:
其中主要的是 acl
,controls
,include
,logging
,key
,options
,view
,zone
其他的很少用到我们就来详细的对这些进行解释一下.
acl 用来对bind的访问进行限制,是一个全局的设置,前面配置的acl
在整个bind
中都适用,和路由器里面的access-list
有同工之处,语法是
acl acl-name { address_match_list };
其中的address_match_list
是一个地址列表,如192.168.0.0/24;
,记住最后一定得有分号,有多个的话中间用分号格开,如192.168.0.0/32;192.168.1.0/24;
bind内置了4个acl分别是:
any
:对应所有的,也就是0.0.0.0/0.none
:对应为空.localhost
:对应本地机器.localnets
:对应本地网络.controls主要用于对bind进行控制,如:
key "rndc-key" { algorithm hmac-md5; secret "VkMaNHXfOiPQqcMVYJRyjQ=="; };
controls { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; }; };
设置rndc
控制的端口以及端口,keys
用来设置控制的密钥
include是一个非常有用的选项,如果需要写程序来读写bind的配置文件,这个将会用到,因为bind的配置文件很不规则,但是用了include后,就可以变的很规则,就和数据库一样了,功用和c语言里面的include
一样。
用于导入拆分的配置文件。
options是用于设置bind的一些选项,我们将重点介绍,BING9支持的选项如下:
options { additional-from-auth boolean; additional-from-cache boolean; // *allow-recursion允许递归查询的地址列表(allow-recursion):设置允许进行递归查询的ip地址列表,缺省值是允许所有地址进行查询,需要注意的是当设置了不允许递归查询后,如果仍然能够查询部分外部的域名,那是因为dns的缓存在起作用,将缓存清除以后就可以了。 allow-recursion { address_match_element; }; allow-v6-synthesis { address_match_element; }; // *allow-query 允许普通查询的地址列表(allow-query):设置允许进行普通查询的ip地址列表,在域中的设置将覆盖全局设置,默认情况下是允许所有的地址进行普通查询。 allow-query { address_match_element; }; // *allow-transfer允许服务器进行区域传输的地址列表(Allow-transfer):(注意的是视区和域中的设置将覆盖全局设置) allow-transfer { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; // *allow-notify 允许更新通知的地址列表(allow-notify),当服务器作为辅助服务器的时候,设置这个可以对收到的更新通知进行判断,只是接收该列表的更新通知.默认情况下,只是接收来自主服务器的更新通知。对于其他服务器的更新通知,会忽略掉. allow-notify { address_match_element; ... }; // *auth-nxdomain 是否做为权威服务器回答域不存在(Auth-nxdomain) 如果设置为'yes',则允许服务器以权威性(authoritatively)的方式返回NXDOMAIN(该域不存在)的回答,否则就不会作权威性的回答,缺省值为”是”. auth-nxdomain boolean; // default changed // *blockhole 定义服务器不对查询进行反应的地址列表,也就是”黑名单”,比如说3721的ip段:218.244.44.0/24,当设置了黑名单后,对于这个段的请求查询,服务器将不会作出反应. blackhole { address_match_element; }; coresize size; datasize size; deallocate-on-exit boolean; // obsolete // *directory 设置bind的数据文件的存放位置:如 directory “/var/named”. directory quoted_string; // *dump-file 设置当执行rndc dumpdb命令后的导出文件存放绝对路径,如果没有指定的话,缺省文件为named_dump.db,放在directory指定的目录下面. dump-file quoted_string; fake-iquery boolean; // obsolete files size; has-old-clients boolean; // obsolete heartbeat-interval integer; host-statistics boolean; // not implemented // *interface-interval 设置bind检查网卡变化的周期. interface-interval integer; // *listen-on 设置bind的绑定ip和端口,如listen-on 53 {192.168.0.1;}; listen-on [ port integer ] { address_match_element; ... }; listen-on-v6 [ port integer ] { address_match_element; ... }; match-mapped-addresses boolean; memstatistics-file quoted_string; // not implemented multiple-cnames boolean; // obsolete named-xfer quoted_string; // obsolete // *pid-file 设置bind的进程号pid文件. pid-file quoted_string; port integer; random-device quoted_string; recursive-clients integer; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; // not implemented serial-queries integer; // obsolete serial-query-rate integer; stacksize size; statistics-file quoted_string; statistics-interval integer; // not yet implemented tcp-clients integer; tkey-dhkey quoted_string integer; tkey-gssapi-credential quoted_string; tkey-domain quoted_string; transfers-per-ns integer; transfers-in integer; transfers-out integer; treat-cr-as-space boolean; // obsolete use-id-pool boolean; // obsolete use-ixfr boolean; // *version 设置客户查询DNS版本好的返回信息,如果不想让客户探测到当前的版本好,就用这个好了,如version mydns1.0; version quoted_string; sortlist { address_match_element; ... }; topology { address_match_element; ... }; // not implemented minimal-responses boolean; // *recursion 是否允许递规查询(recursion)如果设置为”yes”,则允许服务器采用递归的方式进行查询,也就是当要查询的地址不在服务器的数据库列表中时,服务器将一级一级的查询,直到查到为止(一般对局域网都打开)。设置为”no”,并不意味着服务器对于请求的递归查询不给予回答,而是对于请求的递归查询,不再向上级服务器请求,也不缓存,如果不对请求的递归查询回答,可以清空缓存,然后设置为“NO”。 recursion boolean; provide-ixfr boolean; request-ixfr boolean; fetch-glue boolean; // obsolete rfc2308-type1 boolean; // not yet implemented query-source querysource4; query-source-v6 querysource6; cleaning-interval integer; min-roots integer; // not implemented lame-ttl integer; max-ncache-ttl integer; max-cache-ttl integer; transfer-format ( many-answers | one-answer ); // *max-cache-size 设置最大缓存的大小,如max-cache-size 5M max-cache-size size_no_default; check-names string string; // not implemented cache-file quoted_string; // *notify 在主服务器更新时是否通知辅助服务器(notify) 如果设置为”yes”,则在主服务器区域数据发生变化时,就会向在域的”域名服务器“中列出的服务器和“亦通知”中列出的服务器发送更新通知。这些服务器接受到更新通知后,就会向主服务器发送请求传输的消息,然后区域文件得以更新。 notify notifytype; notify-source ( ipv4_address | * ) [ port ( integer | * ) ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]; // *also-notify 更新时亦通知下列地址(also-notify),设置发送更新通知的时候,不仅是域名服务器中列出的地址,亦通知此地址列表中的地址。 also-notify [ port integer ] { ( ipv4_address | ipv6_address ) [ port integer ]; }; dialup dialuptype; // *forward 值有first和only两项, first则首先转发到"forwarders"中的服务器,然后自己查询,only则仅转发到 "转发服务器列表"中的服务器,不再自己查询 forward ( first | only ); // *forwarders设置转发服务器地址列表,语法同acl中的语法. forwarders [ port integer ] { ( ipv4_address | ipv6_address ) [ port integer ]; }; maintain-ixfr-base boolean; // obsolete max-ixfr-log-size size; // obsolete transfer-source ( ipv4_address | * ) [ port ( integer | * ) ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]; max-transfer-time-in integer; max-transfer-time-out integer; max-transfer-idle-in integer; max-transfer-idle-out integer; max-retry-time integer; min-retry-time integer; max-refresh-time integer; min-refresh-time integer; sig-validity-interval integer; zone-statistics boolean; };
obsolete
是已经过时的选项,这里不用考虑,not yet implemented
是尚未完成的选项,这里也不用考虑,下面详细介绍这里面的有用选项 注意,前面打*
的为选项
view(视)是bind9中提出的一个新概念,在这里可以理解为”从不同的眼光来看dns”,在这里view
这个词可真是取的经典呀,具体而已,就是根据不同的源地址,目的地址,解析请求来判断该给客户提供什么样的解析.其语法如下:
view string optional_class { match-clients { address_match_element; ... }; match-destinations { address_match_element; ... }; match-recursive-only boolean; key string { algorithm string; secret string; }; zone string optional_class { type ( master | slave | stub | hint | forward ); allow-update { address_match_element; }; file quoted_string; ixfr-base quoted_string; // obsolete ixfr-tmp-file quoted_string; // obsolete masters [ port integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ key string ]; }; pubkey integer integer integer quoted_string; // obsolete update-policy { ( grant | deny ) string ( name | subdomain | wildcard | self ) string rrtypelist; }; database string; check-names string; // not implemented allow-query { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; allow-notify { address_match_element; ... }; notify notifytype; notify-source ( ipv4_address | * ) [ port ( integer | * ) ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]; also-notify [ port integer ] { ( ipv4_address | ipv6_address ) [ port integer ]; }; dialup dialuptype; forward ( first | only ); forwarders [ port integer ] { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; maintain-ixfr-base boolean; // obsolete max-ixfr-log-size size; // obsolete transfer-source ( ipv4_address | * ) [ port ( integer | * ) ]; transfer-source-v6 ( ipv6_address | * ) [ port (integer | * ) ]; max-transfer-time-in integer; max-transfer-time-out integer; max-transfer-idle-in integer; max-transfer-idle-out integer; max-retry-time integer; min-retry-time integer; max-refresh-time integer; min-refresh-time integer; sig-validity-interval integer; zone-statistics boolean; }; server { bogus boolean; provide-ixfr boolean; request-ixfr boolean; support-ixfr boolean; // obsolete transfers integer; transfer-format ( many-answers | one-answer ); keys server_key; edns boolean; }; trusted-keys { string integer integer integer quoted_string; }; allow-recursion { address_match_element; ... }; allow-v6-synthesis { address_match_element; ... }; sortlist { address_match_element; ... }; topology { address_match_element; ... }; // not implemented auth-nxdomain boolean; // default changed minimal-responses boolean; recursion boolean; provide-ixfr boolean; request-ixfr boolean; fetch-glue boolean; // obsolete rfc2308-type1 boolean; // not yet implemented additional-from-auth boolean; additional-from-cache boolean; query-source querysource4; query-source-v6 querysource6; cleaning-interval integer; min-roots integer; // not implemented lame-ttl integer; max-ncache-ttl integer; max-cache-ttl integer; transfer-format ( many-answers | one-answer ); max-cache-size size_no_default; check-names string string; // not implemented cache-file quoted_string; allow-query { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; allow-notify { address_match_element; ... }; notify notifytype; notify-source ( ipv4_address | * ) [ port ( integer | * ) ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]; also-notify [ port integer ] { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; dialup dialuptype; forward ( first | only ); forwarders [ port integer ] { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; maintain-ixfr-base boolean; // obsolete max-ixfr-log-size size; // obsolete transfer-source ( ipv4_address | * ) [ port ( integer | * ) ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]; max-transfer-time-in integer; max-transfer-time-out integer; max-transfer-idle-in integer; max-transfer-idle-out integer; max-retry-time integer; min-retry-time integer; max-refresh-time integer; min-refresh-time integer; sig-validity-interval integer; zone-statistics boolean; };
其中:
match-clients
,指的是view对应的源地址,match-destinations
指的是view对应的目的地址,match-recursive-only
指的是view对应是否仅仅是递归请求。BIND在收到DNS的解析请求后,会首先判断该请求包的源地址和目标地址,然后根据视区里面的match-clients
和match-destinations
和match-recursive-only
,判断是否属于第一个视区,符合的话就用第一个视区来进行解析,否则就判断下一个视区。然后再进行解析。如果所有的视区都不能对应,则DNS将返回Query refused
的消息。
这样在防火墙的情况下,就有一个很好的解决办法了,比如一个典型的网络结构下,DMZ区全部在防火墙外网口上做的地址映射(DNAT),当DMZ区要访问本地网络的时候,单纯用传统的域名解析的话,是无法达到要求的,因为防火墙无法同时又做SNAT和DNAT,比如DMZ地址192.168.0.14
映射到外部地址202.196.160.14
,而域名服务器解析www.yourdomain.com
到202.196.160.14
,则192.168.0.0/24
的网络将无法访问www.yourdomain.com
,但是当用了VIEW后,你可以对来自该网络的解析请求将www.yourdomain.com
直接解析到192.168.0.14
,这样就可以访问了。
view里面可以包含zone
,优先级是zoneviewoptions
,zone
里面的选项好多和options
里面一样,不过它只是对本zone
一样,同样view里面的选项也只是对本view有效。
zone
是bind的一个重要选项,不过关于zone
网上的文章很多,在这里只是补充几点小技巧:
如何将域名直接解析为www服务器的地址,比如像freshmeat.net
那样直接解析freshmeat.net
为www.freshmeat.net
,这里可以在域的数据文件里面增加一个这样的地址记录:
@ IN A 202.196.160.14
这样的主机记录就可以实现了,202.196.160.14
为www
服务器的ip地址。
Can't find server name for address *.*.*.*: Non-existent domain
,这种情况是没有对域名服务器本身做反向地址解析造成的,给域名服务器增加一条反向地址解析就可以了。DNS request timed out.timeout was 2 seconds.DNS request timed out.
这种情况一般是在DNS进行递归查询的时候,超时造成的,可能是由于网络速度问题,也可能是路由等其他问题,或者对方域名服务器没有响应造成的.xxx dns.cbchen.com can't find www.ite.com: Non-existent domain
,这种情况一般是域中没有该地址记录或没有别名记录.***.server failed
一般是配置问题,请检测配置,或者是辅助域无法从主域中得到数据,再请求辅助域的时候会出现这种故障.BIND的有用的网站:
强烈推荐BIND9解压目录下的/doc/arm管理员手册
其他第三方DNS服务器软件: