systemd-resolved:拆分 DNS 介绍

[ad_1]

Fedora 33 将默认 DNS 解析器切换到 系统解析. 简单来说,这意味着 systemd-resolved 将作为守护进程运行。 所有想要将域名转换为网络地址的程序都会与之对话。 这取代了当前的默认查找机制,其中每个程序单独与远程服务器对话,并且没有共享缓存。

如有必要,systemd-resolved 将联系远程 DNS 服务器。 systemd-resolved 是一个“存根解析器”——它本身不解析所有名称(通过从 DNS 层次结构的根开始并逐个标签向下),而是将查询转发到远程服务器。

处理名称查找的单个守护程序提供了显着的好处。 守护进程会缓存答案,从而加快对常用名称的回答速度。 守护进程会记住哪些服务器没有响应,而以前每个程序都必须在超时后自行解决。 单个程序仅通过本地传输与守护程序对话,并且与网络更加隔离。 守护进程支持花哨的规则,这些规则指定哪些域名服务器应该用于哪些域名——事实上,本文的其余部分是关于这些规则的。

拆分DNS

假设一台机器连接到两个半可信网络(wifi 和以太网),并且还与您的雇主建立了 VPN 连接。 这三个连接中的每一个在内核中都有自己的网络接口。 并且有多个名称服务器:一个来自 wifi 热点的 DHCP 租用,两个由 VPN 指定并由您的雇主控制,以及一些额外的手动配置的名称服务器。 路由是决定哪些服务器请求给定域名的过程。 不要将这一点与决定向何处发送网络数据包的过程混淆,这也称为路由。

网络接口是 systemd-resolved 中的王者。 systemd-resolved 首先选择一个或多个适合给定名称的接口,然后查询连接到该接口的名称服务器之一。 这称为“拆分 DNS”。

有两种类型的域附加到网络接口:路由域和搜索域。 它们都指定给定的域和任何子域都适用于该接口。 搜索域具有附加功能,即单标签名称在解析之前以该搜索域为后缀。 例如,如果搜索域是“example.com”,则对“server”的查找被视为对“server.example.com”的查找。 在 systemd 解析的配置文件中,路由域以波浪号 (~) 字符为前缀。

具体例子

现在考虑一个具体的例子:你的 VPN 接口 tun0 有一个搜索域 private.company.com 和一个路由域 ~company.com。 如果您请求 mail.private.company.com,它会被两个域匹配,因此该名称将被路由到 tun0。

对 www.company.com 的请求与第二个域匹配,也会转到 tun0。 如果您请求 www,(换句话说,如果您指定一个不带任何点的单标签名称),路由域和搜索域之间的区别就会发挥作用。 systemd-resolved 尝试将单标签名称与搜索域结合起来,并尝试在 tun0 上解析 www.private.company.com。

如果您有多个带有搜索域的接口,则单标签名称将作为所有搜索域的后缀并并行解析。 对于多标签名称,不做后缀; 搜索和路由域用于将名称路由到适当的接口。 最长的比赛获胜。 当不同接口上有多个相同长度的匹配时,它们并行解析。

一个特殊情况是当一个接口有一个路由域~。 (路由域的波浪号和根 DNS 标签的点)。 这样的接口总是匹配任何名称,但长度尽可能短。 任何具有匹配搜索或路由域的接口都具有更高的优先级,但带有 ~. 用于所有其他名称。 最后,如果没有匹配的路由或搜索域,则该名称将路由到至少连接了一个名称服务器的所有接口。

systemd-resolved 中的查找路由

域路由

这似乎相当复杂,部分原因是历史名称令人困惑。 在实际操作中,它并不像看起来那么复杂。

要检查正在运行的系统,请使用 resolvectl domain 命令。 例如:

$ resolvectl domain
Global:
Link 4 (wlp4s0): ~.
Link 18 (hub0):
Link 26 (tun0): redhat.com

您可以看到 www 将解析为 www.redhat.com。 超过 tun0。 任何以 redhat.com 结尾的内容都可以通过 tun0 解析。 其他一切都将通过 wlp4s0(无线接口)解决。 特别是,像 www.foobar 这样的多标签名称将通过 wlp4s0 解析,并且很可能会失败,因为还没有 foobar 顶级域。

服务器路由

既然您知道应该查询哪个或哪些接口,就很容易确定要查询的服务器。 每个接口都配置了一个或多个名称服务器。 systemd-resolved 将向第一个发送查询。 如果服务器离线并且请求超时,或者如果服务器发送一个语法无效的答案(这不应该发生在“正常”查询中,但在启用 DNSSEC 时通常会成为一个问题),systemd-resolved 切换到下一个名单上的服务器。 只要它继续响应,它就会使用第二台服务器。 所有服务器都以循环方式使用。

要检查正在运行的系统,请使用 resolvectl dns 命令:

$ resolvectl dns
Global:
Link 4 (wlp4s0): 192.168.1.1 8.8.4.4 8.8.8.8
Link 18 (hub0):
Link 26 (tun0): 10.45.248.15 10.38.5.26

结合前面的列表,您知道对于 www.redhat.com,systemd-resolved 将查询 10.45.248.15,如果没有响应,则查询 10.38.5.26。 对于 www.google.com,systemd-resolved 将查询 192.168.1.1 或两个 Google 服务器 8.8.4.4 和 8.8.8.8。

与 nss-dns 的区别

在进一步了解细节之前,您可能会问这与之前的默认实现 (nss-dns) 有何不同。 使用 nss-dns,只有一个最多三个名称服务器的全局列表和一个搜索域的全局列表(指定为名称服务器并在 /etc/resolv.conf 中搜索)。

要查询的每个名称都会发送到第一个名称服务器。 如果它没有响应,则将相同的查询发送到第二个名称服务器,依此类推。 systemd-resolved 实现了 split-DNS 并记住哪些服务器当前被认为是活动的。

对于单标签名称,查询是在每个搜索域后缀的情况下执行的。 这与 systemd-resolved 相同。 对于多标签名称,首先查询不带后缀的名称,如果查询失败,则依次查询每个搜索域后缀的名称。 systemd-resolved 不做最后一步; 它只为单标签名称添加后缀。

第二个区别是使用 nss-dns,这个模块被加载到每个进程中。 该过程本身与远程服务器通信并在内部实现完整的 DNS 堆栈。 使用 systemd-resolved,nss-resolve 模块被加载到进程中,但它只通过本地传输 (D-Bus) 将查询转发给 systemd-resolved,并且本身不做任何工作。 systemd 解析的进程使用 systemd 服务功能进行了大量沙盒处理。

第三个区别是 systemd-resolved 的所有状态都是动态的,可以使用 D-Bus 调用进行查询和更新。 这允许与其他守护程序或图形界面非常强大的集成。

配置 systemd-resolved

到目前为止,本文只讨论了服务器和域的路由,而没有解释如何配置它们。 systemd-resolved 有一个配置文件 (/etc/systemd/resolv.conf),您可以在其中使用 DNS= 指定名称服务器,并使用 Domains= 指定路由或搜索域(使用 ~ 路由域,不使用搜索域)。 这对应于上面两个列表中的 Global: 列表。

在本文的示例中,两个列表都是空的。 大多数时候配置附加到特定接口,“全局”配置不是很有用。 接口来来去去,在关闭的接口上联系服务器并不是非常聪明。 一旦创建 VPN 连接,您就想使用为该连接配置的服务器来解析名称,并且一旦连接中断,您就想停止。

那么 systemd-resolved 如何获取每个接口的配置呢? 这是动态发生的,网络管理服务通过 D-Bus 将此配置推送到 systemd-resolved。 默认在 Fedora 是 NetworkManager,它与 systemd-resolved 有很好的集成。 systemd 自己的 systemd-networkd 等替代方案实现了类似的功能。 但该 接口已打开 和其他程序可以进行适当的 D-Bus 调用。

或者,可以使用 resolvectl(它只是 D-Bus API 的包装器)。 最后,resolvconf 以与 Debian 中同名工具兼容的形式提供了类似的功能。

场景:本地连接比 VPN 更受信任

重要的是,在常见场景中,systemd-resolved 遵循其他工具指定的配置,尤其是 NetworkManager。 因此,要了解 systemd 是如何解析名称的,您需要查看 NetworkManager 告诉它做什么。 通常 NM 会告诉 systemd-resolved 使用名称服务器并搜索在某个接口上的 DHCP 租约中收到的域。 例如,查看上面显示的两个列表的配置源:

有两个连接:“帕金森”wifi 和“布尔诺(BRQ)”VPN。 在第一个面板中 DNS:Automatic 已启用,这意味着作为 DHCP 租约 (192.168.1.1) 的一部分收到的 DNS 服务器将传递给 systemd-resolved。 此外。 8.8.4.4 和 8.8.8.8 被列为备用名称服务器。 如果您想解析 192.168.1.1 提供的本地网络中其他机器的名称,则此配置很有用。 不幸的是,热点 DNS 服务器偶尔会卡住,而其他两台服务器会在发生这种情况时提供备份。

第二个面板类似,但不提供任何特殊配置。 NetworkManager 为来自 DHCP、SLAAC RDNSS 和 VPN 的给定连接组合路由域,最后手动配置并将其转发到 systemd-resolved。 这是上面列表中搜索域 redhat.com 的来源。

不过,这两个接口之间有一个重要区别:在第二个面板中,“仅将此连接用于其网络上的资源”是 检查. 这告诉 NetworkManager 告诉 systemd-resolved 仅将此接口用于作为租约的一部分收到的搜索域下的名称(链接 26(tun0):上面第一个列表中的 redhat.com)。 在第一个面板中,此复选框是 未经检查,并且 NetworkManager 告诉 systemd-resolved 将此接口用于所有其他名称(链接 4 (wlp4s0): ~.)。 这实际上意味着无线连接更受信任。

场景:VPN 比本地网络更受信任

在另一种情况下,VPN 比本地网络更受信任,并且域路由配置相反。 如果没有“仅将此连接用于其网络上的资源”的 VPN 处于活动状态,NetworkManager 会告诉 systemd-resolved 将默认路由域附加到此接口。 取消选中复选框并重新启动 VPN 连接后:

$ resolvectl domain
Global:
Link 4 (wlp4s0):
Link 18 (hub0):
Link 28 (tun0): ~. redhat.com
$ resolvectl dns
Global:
Link 4 (wlp4s0):
Link 18 (hub0):
Link 28 (tun0): 10.45.248.15 10.38.5.26

现在所有域名都路由到 VPN。 网络管理守护进程控制systemd-resolved,用户控制网络管理守护进程。

额外的 systemd 解析功能

如前所述,systemd-resolved 为机器上运行的所有程序提供了通用名称查找机制。 现在效果有限:共享解析器和缓存以及拆分 DNS(上述查找路由逻辑)。 systemd-resolved 提供了超越传统单播 DNS 的额外解析机制。 这些是本地解析协议 MulticastDNS 和 LLMNR,以及附加的远程传输 DNS-over-TLS。

Fedora 33 未在 systemd-resolved 中启用 MulticastDNS 和 DNS-over-TLS。 MulticastDNS 由 nss-mdns4_minimal 和 Avahi 实现。 未来 Fedora 随着上游项目改进支持,发布可能会启用这些。

在具有运行时状态的单个守护进程中实现这一切允许智能行为:可以在机会模式下启用 DNS-over-TLS,如果远程服务器不支持它,则自动回退到经典 DNS。 如果没有可以包含复杂逻辑和运行时状态的守护进程,这将变得更加困难。 启用后,这些附加功能将适用于系统上的所有程序。

systemd-resolved 还有更多:特别是 LLMNR 和 DNSSEC,这里只简要提及。 以后的文章将探讨这些主题。

[ad_2]

Related Posts