systemd-resolvd本地网络域名解析服务

在使用Ubuntu 18.10 版本时,发现主机设置的 /etc/resolv.conf 解析器指向了IP地址是 127.0.0.53 这个本地回环地址。我很好奇为何本机并没有启动DNS服务也会如此,搜索了一下发现是 systemd 提供了一个 systemd-resolved 服务来提供本地应用DNS解析缓存,这个新技术需要学习掌握。

systemd-resolved是一个systemd服务,通过D-Bus接口提供本地应用程序网络域名解析,解析 NSS服务(nss-resolve)和一个本地DNS监听器位于127.0.0.53

systemd-resolved 是一个为本地应用程序提供网络域名解析的系统服务。它实现了一个缓存并且验证 DNS/DNSSEC 票据解析器,类似于 LLMNR 和多播DNS解析器和响应器。

LLMNRLink-Local Multicast Name Resolution是微软开发的主机名解析协议。

本地应用程序可以通过3个接口来发送域名解析:

  • 原生的,完全API功能的 systemd-resolved 输出的API,可以参考 API 文档 。建议使用这个API,因为 systemd-resolved 的API是异步并且提供所有功能(例如,可能返回 DNSSED 验证状态以及按需返回地址的接口范围来支持连接本地网络)。

  • glibc的getaddrinfo API在RFC3493定义并且提供了解析通能,包括gethostbyname。这个API被广泛支持,不仅在Linux平台。当前glibc的getaddrinfo API不能提供DNSSEC验证状态信息,并且只能采用同步方式。该API的后端是由glibc Name Service Switch(nss)提供。要允许glibc的NSS解析器工作能够通过systemd-resolved提供主机解析,需要使用glibc NSS模块nss-resolv

  • systemd-resolved提供了一个本地DNS监听在 127.0.0.531 回环地址接口。程序可以直接发送 DNS 请求,绕过任何本地API直接访问这个接口,这样可以直接连接 systemd-resolved。注意,虽然强烈建议使用这个方式,但是本地程序使用 glibc NSS 或者 bus API 的很多网络概念(例如 link-local addressing ,或者LLMNR Unicode domains)是不能映射成单播DNS协议。

DNS服务器通过从全局设置 /etc/systemd/resolved.conf 定义获取, per-link 状态设置在 /etc/systemd/network/*.network 文件(此时使用了systemd-networkd.service), per-link 动态设置通过DHCP获得,用户通过 resolvectl发出请求,并且任何DNS服务器信息由其他系统服务提供。为了提升兼容性,/etc/resolv.conf被读取以便能够发现配置好的系统DNS服务器,但是这个方式只在没有软链接到 /run/systemd/resolv/stub-resolv.conf/usr/lib/systemd/resolv.conf或者/run/systemd/resolv/resolv.conf时生效。

请注意:在Ubuntu 18.10上检查 /etc/resolv.conf 可以看到这个文件是软链接:

# ls -lh /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Feb 27 21:59 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

内容如下:

nameserver 127.0.0.53
options edns0

手工设置

在本地DNS,可替代的DNS服务器通过 resolved.conf 文件提供(可能位置有 /etc/systemd/resolved.conf.d/dns_servers.conf 或者 /etc/systemd/resolved.conf) 内容可能默认没有设置:

[Resolve]
#DNS=
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#Cache=yes
#DNSStubListener=yes

/etc/systemd/resolved.conf 是默认系统配置,建议在 /etc/systemd/resolved.conf.d/ 目录下增加自定义配置 /etc/systemd/resolved.conf.d/dns_servers.conf

可以手工设置DNS服务器在 /etc/systemd/resolved.conf.d/dns_servers.conf 中:

[Resolve]
DNS=91.239.100.100 89.233.43.71

故障切换(Fallback)

如果 systemd-resolved 没有从 network manager 接受到DNS服务器地址,并且没有手工配置,则可以采用 FallbackDNS,这提供了一个后备的解决昂安。

[Resolve]
FallbackDNS=127.0.0.1 ::1

如果不需要 fallback ,则可以在配置文件中将 FallbackDNS选项保持为空:

[Resolve]
FallbackDNS=

DNSSEC

默认情况下 DNSSEC验证只在上游DNS服务器支持的情况下激活。如果你希望总是验证DNSSEC,并阻断不支持DNSSEC的DNS解析,则设置 DNSSEC=TREU,即配置 /etc/systemd/resolved.conf.d/dnssec.conf

[Resolve]
DNSSEC=true

测试是否支持DNSSEC验证:

不支持DNSSEC验证案例:

$ resolvectl query sigfail.verteiltesysteme.net

sigfail.verteiltesysteme.net: resolve call failed: DNSSEC validation failed: invalid

支持DNSSEC验证:

$ resolvectl query sigok.verteiltesysteme.net

sigok.verteiltesysteme.net: 134.91.78.139

-- Information acquired via protocol DNS in 266.3ms.
-- Data is authenticated: yes

参考

Last updated