问题背景
“如果记录不存在,则进行转发”;
实际的情况是这样的:在同一个 ZONE 中,有些域名使用 ISP 的 DNS 服务器进行解析,而有些域名希望仅在本地 DNS 服务器解析的。比如域名 inner.k4nz.com 仅在内网的 DNS 服务器上解析,而 outer.k4nz.com 则由公网的 DNS 服务器解析。我们希望这二者可以共存,即“如果内网 DNS 服务找不到对应的记录,则到公网的 DNS 服务器查找”,亦即“如果记录不存在,则进行转发”;
这就会存在一个问题:内网的 DNS 服务器接管 k4nz.com 这个 ZONE 之后,导致同 ZONE 内的在公网 DNS 服务解析的域名无法解析。就是说,使用内网 DNS 服务接管 k4nz.com 这个 zone 后,在公网解析的 outer.k4nz.com 就无法解析了。(为什么?因为就这样,去了解以下 DNS 吧……)
解决方案
要怎么解决这个问题呢:首先想到的当然就是“如果记录不存在,则进行转发”,但是 BIND 好像没有提供这个功能“在 ZONE 里找不到就去其他 DNS 服务器查询的功能”(或许是我没找到)。所以,就去搜索了以下,给出的办法是“覆盖”,用到了“Response Policy Zones (RPZ)”配置,包含在 BIND 9.8.1 以后的版本中:定义一个 ZONE,这个 ZONE 用作覆盖原由的记录;
注意,本文侧重于从 DNS 服务层面解决这个问题,而不是在客户端中使用类似于“如果这个 DNS 服务器没有找到记录,则去下一个查找”的方法进行解决。相关方法参见「Ubuntu resolv.conf, not going to next nameserver?」「second nameserver in /etc/resolv.conf not picked up by wget」
WIP DNS – 如果没有找到对应的记录,则去下一台进行查找
实行配置
修改 /etc/named.conf 配置文件,内容如下:
options {
listen-on port 53 { any; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
recursing-file "/var/named/data/named.recursing";
secroots-file "/var/named/data/named.secroots";
allow-query { any; };
recursion yes;
allow-transfer { none; };
response-policy { zone "rpz"; };
};
zone "." IN {
type hint;
file "named.ca";
};
zone "rpz" IN {
type master;
file "named.rpz";
allow-query {
none;
};
};
创建 /var/named/named.rpz 配置文件,内容如下:
$TTL 600
@ IN SOA dns.example.com. root.example.com. (20190101 3H 15M 1W 1D)
NS dns.example.com.
note.example.com IN A 172.31.255.249
mgr.example.com IN A 172.31.255.80
sys.example.com IN A 172.31.255.33
重启 DNS 服务:
#!/bin/bash systemctl restart named.service
验证是否有效:
#!/bin/bash # 查询由内部 DNS 服务解析的域名 dig note.example.com dig mgr.example.com # 查询由外部 DNS 服务解析的域名 dig www.example.com
注意事项
用作 RPZ 的 ZONE 名不能和实际的 ZONE 名匹配,否则无法“覆盖”。比如,RPZ 的 ZONE 名为 k4nz.com,那么在 k4nz.com 下面的域名的“覆盖”会无效,这也是使用“rpz”作为 ZONE 名的原因;
参考文献
(1)BIND9 – Response Policy Zone Configuration
(1)How to configure your BIND resolvers to lie using Response Policy Zones (RPZ)
Overriding some DNS entries in BIND for internal networks
How do I resolve a DNS name for the same zone not found locally but that exists on another DNS server?