如何让Bind9 DNS服务器根据网络可用性返回不同解析结果?
兄弟,你现在的问题出在zone类型的配置上!你把example.com设成了master类型,这就相当于告诉Bind:“我是这个域名的权威DNS服务器”,所以它会直接返回你本地zone文件里的记录,完全不理会你写的forward配置——这就是为啥不管网络好不好,都返回172.16.2.2的原因。
Bind的master/slave类型zone优先级是最高的,只要定义了,它就不会去转发这个域名的查询。要实现“优先转发、失败 fallback 到本地”的需求,得换个配置思路,这里给你两种可行的方案:
方案一:用脚本动态切换配置(最可靠)
Bind本身没有内置“根据网络状态自动切换解析规则”的功能,所以我们可以写个小脚本定期检测网络,自动切换Bind的配置文件:
先准备两个配置片段:
- 转发用的配置文件
/etc/bind/named.conf.forward:zone "example.com" { type forward; forward first; forwarders { 8.8.8.8; }; }; - 本地解析用的配置文件
/etc/bind/named.conf.localzone:zone "example.com" { type master; max-zone-ttl 1; file "/etc/bind/db.example.com"; };
- 转发用的配置文件
写个检测脚本
/root/check_network.sh(记得给执行权限:chmod +x /root/check_network.sh):#!/bin/bash # 检测8.8.8.8是否可达,超时2秒,发送1个探测包 if ping -c 1 -W 2 8.8.8.8 > /dev/null 2>&1; then # 网络连通,切换到转发配置 cp /etc/bind/named.conf.forward /etc/bind/named.conf.example.com else # 网络断开,切换到本地解析配置 cp /etc/bind/named.conf.localzone /etc/bind/named.conf.example.com fi # 通知Bind重新加载配置 rndc reload把脚本加到定时任务,比如每5分钟执行一次:
执行crontab -e,添加一行:*/5 * * * * /root/check_network.sh在主配置文件
named.conf里引用这个动态配置:include "/etc/bind/named.conf.example.com";
这样一来,只要网络能连上8.8.8.8,Bind就会转发查询;断网了就自动切换到本地zone文件,返回你指定的172.16.2.2。
方案二:用响应策略区(RPZ)处理转发失败场景
如果不想用脚本,也可以用Bind的RPZ功能,当转发到8.8.8.8返回失败(比如返回NXDOMAIN)时,用本地记录兜底:
先配置转发zone:
zone "example.com" { type forward; forward first; forwarders { 8.8.8.8; }; };创建RPZ的zone文件
/etc/bind/db.rpz:$TTL 60 @ IN SOA localhost. root.localhost. ( 2024052001 ; 序列号,每次修改文件要加1 3600 ; 刷新时间 600 ; 重试时间 604800 ; 过期时间 60 ) ; 最小TTL @ IN NS localhost. example.com IN A 172.16.2.2在
named.conf的options块里启用RPZ:options { # 保留你原有的其他配置... response-policy { zone "rpz.local"; }; };定义RPZ的zone:
zone "rpz.local" { type master; file "/etc/bind/db.rpz"; allow-query { none; }; # 禁止外部查询这个RPZ域 };
这个方案的局限性是:如果是网络完全断连(比如8.8.8.8根本连不上),Bind会返回SERVFAIL错误,RPZ可能不会触发;但如果是8.8.8.8能连上,但返回NXDOMAIN(比如example.com不存在),就会用RPZ里的本地记录。所以如果你的需求是“只要网络不可达就返回本地IP”,方案一更靠谱。
最后提醒:不管用哪个方案,记得先把你原来的master zone配置删掉,避免冲突。
备注:内容来源于stack exchange,提问作者Navid777

