我有一个带有运行 BIND 的 DNS 服务器的内部网络,通过单个网关连接到 Internet。我的域“example.com”由外部 DNS 提供商管理。该域中的一些条目,例如“host1.example.com”和“host2.example.com”,以及顶级条目“example.com”,指向网关的公共 IP 地址。
我希望位于内部网络上的主机将“host1.example.com”、“host2.example.com”和“example.com”解析为内部 IP 地址,而不是网关的 IP 地址。“otherhost.example.com”等其他主机仍应由外部 DNS 提供商解析。
通过在 BIND 中为“host1.example.com”和“host2.example.com”定义两个单条目区域,我成功地为 host1 和 host2 条目做到了这一点。但是,如果我为“example.com”添加一个区域,则该域的所有查询都由我的本地 DNS 服务器解析,例如查询“otherhost.example.com”会导致错误。
是否可以将 BIND 配置为仅覆盖域的某些条目,并递归解析其余条目?
最好的方法是通过 Bind 9.8.1 或更高版本中的响应策略区域。它允许您覆盖任意区域中的单个记录(并且无需为此创建整个子域,只需要更改的单个记录),它允许您覆盖 CNAME 等。其他解决方案,如 Unbound 不能覆盖 CNAME .
https://www.redpill-linpro.com/sysadvent/2015/12/08/dns-rpz.html
编辑:那么让我们正确地做到这一点。我将根据上面链接的教程记录我所做的事情。
我的操作系统是用于 Raspberry Pi 的 Raspbian 4.4,但该技术应该可以在 Debian 和 Ubuntu 上无需任何更改或在其他平台上进行最小更改即可工作。
转到您的 Bind 配置文件保存在系统上的位置 - 它位于
/etc/bind
. 在那里创建一个名为的文件db.rpz
,其内容如下:它有什么作用?
www.some-website.com
它使用假地址覆盖 IP 地址127.0.0.1
,有效地将所有流量发送到该站点的环回地址www.other-website.com
到另一个名为fake-hostname.com
可以在此处使用的绑定区域文件中的任何内容。
要激活这些更改,还有几个步骤:
编辑
named.conf.local
并添加此部分:上面链接的教程告诉您添加更多东西,
zone "rpz" { }
但这在简单设置中不是必需的 - 我在这里展示的是使其在本地解析器上工作的最低要求。编辑
named.conf.options
并在该部分的某处options { }
添加response-policy
选项:现在重新启动绑定:
而已。名称服务器现在应该开始覆盖这些记录。
如果您需要进行更改,只需编辑
db.rpz
,然后再次重新启动 Bind。奖励:如果您想将 DNS 查询记录到 syslog,以便您可以密切关注程序,请编辑
named.conf.local
并确保有一个logging
部分包含这些语句:再次重新启动Bind,就是这样。
在运行 Bind 的机器上测试:
如果您在另一台机器上运行 dig,只需使用 @the-ip-address-of-Bind-server 而不是 @127.0.0.1
我已经成功地使用这种技术覆盖了我正在开发的网站的 CNAME,并将其发送到我刚刚测试的新 AWS 负载均衡器。Raspberry Pi 用于运行 Bind,并且 RPi 还配置为用作 WiFi 路由器 - 因此通过将设备连接到在 RPi 上运行的 SSID,我将获得测试所需的 DNS 覆盖。
未绑定递归 DNS 服务器具有覆盖单个资源记录的能力。
查看手册
local-zone
中的和local-data
配置设置,例如:上的
transparent
设置local-zone
告诉它对未提供的任何名称进行正常的递归查找local-data
。您可能想查看“dnsmasq”,它可以让您通过调整分辨率来做一些非常聪明的事情。
您正在寻找的是拆分 DNS,Webopedia将其定义为:
本质上,您需要制作外部区域文件的副本并将其支持在内部 DNS 服务器上,然后更改或添加专门用于内部网络的记录。这是一个非常常见的设置,尽管在两个 DNS 服务器之间保持“外部”记录同步可能会很痛苦。如果您在公共服务器上创建或更改记录,则还需要在私人服务器上创建或更改记录。
无论您使用什么 DNS 服务器实现,都可以实现这一点。在大多数设置中,您将拥有一台服务于外部网络的 DNS 服务器,以及一台服务于内部网络的不同的 DNS 服务器。使用 BIND,可能与其他实现一样,您可以通过在 named.conf 文件的 zone 部分中使用“allow-query”语句在同一台服务器上拥有两个版本的 zone。
BIND 的另一种可能性(我从未尝试过)是在内部 DNS 服务器上设置您的 example.com 域,仅包含您在内部使用的记录。然后,使用“first”参数(与“forwarders”一起)设置“forward”语句。从理论上讲,这会询问外部 DNS 服务器(如“转发器”中设置的那样),它不会有您的内部记录并返回失败响应。然后,内部服务器会查看自己的答案。不是确定这是否可行,但这是一个想法。
使用 dnsmasq 让它变得非常容易。http://www.thekelleys.org.uk/dnsmasq/doc.html 充当 dns 服务器,但从本地 dns 服务器获取答案。好消息是您可以覆盖单个域记录而不会弄乱区域文件
在 BIND 中,我通过使用所需主机名定义区域来获得此结果。如果您只想覆盖几个主机,这种方法很好。
我的区域声明如下所示:
我的区域定义如下所示:
因此,如果我在 Intranet DNS 和 ISP DNS 上查询 example.com,我会得到相同的 IP,但如果我查询 override.example.com,如果 Intranet DNS(主)可访问,我会得到不同的结果。
你已经在正确的轨道上。
在您的内部 DNS 服务器上,您需要为“example.com”正下方的每个异常主机定义一个区域。为了尽量减少这些例外情况,通常将所有内部机器命名为“hosta.internal.example.com”,DNS 服务器将大部分查询发送到外部 DNS 服务器,但对“internal.example.com”区域具有权威性。(一旦你通过了一个小操作,通常会有一对客户端被定向到的 DNS 服务器和一个单独的权威 DNS,这些服务器被定向到“internal.example.com”。)
通常,只有当主机必须在外部和内部都可以访问时,才会创建您描述的异常。即使这样,您也可能希望从外部使用“host1.example.com”,从内部使用“host1.internal.example.com”。内部主机被配置为在“internal.example.com”中查找名称。在某些情况下,您已经在做的事情是合适的,例如,如果服务器的证书将服务器标识为“host1.example.com”,在这种情况下,您希望它是客户端连接的名称。
事实上,还有另一种方法,即使可能略有不同,也可以做到这一点。我有同样的情况,我有一个在外部和内部使用的域,我有外部静态和动态主机。唯一真正痛苦的是外部动态的。该解决方案可能不是最优雅的,但可以通过一个小脚本实现。大多数情况下,我正在使用我的动态 DNS 提供商的 API 执行我自己的动态 DNS 脚本,我通过 cron 每 5 分钟运行一次此脚本:
1)获取我的外部IP。它改变了吗?没有出口。
2)更改IP,调用dyndns-provider的API,使用新的IP地址,
3) 使用外部 IP 对 db.mydomain.com 进行 sed
4)重启绑定。
对我的家庭网络非常可靠