问题背景
“如果记录不存在,则进行转发”。
实际的情况是这样的:在同一个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」
TODO 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?