systemd-resolved 是 Linux 系统中 systemd 套件的一部分,主要负责 网络名称解析(DNS 解析) 服务。
介绍
systemd-resolved 不仅是一个简单的 DNS 客户端,还提供了本地 DNS 缓存、DNSSEC 验证、DNS over TLS (DoT) 支持、LLMNR 与 MulticastDNS 的解析(resolver)与应答(responder)以及对多网络接口的分割 DNS(Split DNS)管理。
核心功能
- 本地 DNS 缓存 (Caching):
它会在本地缓存 DNS 请求的结果。当应用程序再次请求相同的域名时,它可以直接从内存中返回结果,从而减少延迟并减轻上游 DNS 服务器的负载。
- 本地 Stub 监听器 (Stub Listener):
默认情况下,它会监听本地回环地址
127.0.0.53 的 53 端口。/etc/resolv.conf 通常被配置为指向这个地址,从而将系统所有的 DNS 请求转发给 systemd-resolved 处理。
- 分割 DNS (Split DNS):
这是 systemd-resolved 的杀手级功能。它允许为不同的网络接口配置不同的 DNS 服务器。
- 场景: 当你连接 VPN 时,公司内部域名的请求会发送到 VPN 接口的 DNS,而普通互联网请求则走原本的 Wi-Fi/以太网 DNS。
- 支持多种解析协议:
- 传统的单播 DNS。
- LLMNR (Link-Local Multicast Name Resolution) 和 mDNS (Multicast DNS):用于在没有 DNS 服务器的局域网内解析主机名(类似于 Windows 的网络发现或 Apple 的 Bonjour)。
- DNS over TLS (DoT): 支持加密 DNS 查询,防止隐私泄露和中间人篡改。
配置文件与工作模式
主配置文件
主要配置文件位于 /etc/systemd/resolved.conf。
常见的配置项包括:
[Resolve]
# 全局 DNS 服务器,配置 DNS,多个使用空格分隔
DNS=8.8.8.8 1.1.1.1
# 备用 DNS
FallbackDNS=114.114.114.114
# 是否开启多播 DNS 支持 (yes/no/resolve)
MulticastDNS=yes
# 是否开启 DNS over TLS (yes/no/opportunistic)
DNSOverTLS=no
# 是否开启缓存
Cache=yes
| 特性 |
DNS |
FallbackDNS |
| 作用 |
主要的 DNS 服务器列表 |
在主要服务器失败时使用的备用 DNS 服务器列表 |
| 使用场景 |
始终使用,根据配置的顺序尝试解析 |
在主要 DNS 服务器不可达或解析失败时才使用 |
| 配置方式 |
可以设置一个或多个地址 |
同样可以设置一个或多个地址 |
启动服务
# 启动服务,通过解析配置文件,实时更新 /run/systemd/resolve/resolv.conf、 /run/systemd/resolve/stub-resolv.conf
systemctl start systemd-resolved.service
systemctl restart systemd-resolved.service
与 /etc/resolv.conf 的关系
这是用户最容易困惑的地方。systemd-resolved 提供了几种管理 /etc/resolv.conf 的模式,通过软链接(Symbolic Link)来控制:
-
Stub 模式 (推荐/默认):
/etc/resolv.conf 指向 /run/systemd/resolve/stub-resolv.conf。
- 文件内容里
nameserver 是 127.0.0.53。
- 这是使用 systemd-resolved 缓存和高级功能的唯一方式。
-
Uplink 模式:
/etc/resolv.conf 指向 /run/systemd/resolve/resolv.conf。
- 文件内容列出了真实的全局 DNS 服务器(如 8.8.8.8)。
- 应用程序直接查询上游 DNS,绕过 systemd-resolved 的缓存,但 systemd-resolved 仍在后台更新这个文件。
-
非托管模式:
/etc/resolv.conf 是一个普通文件,不是软链接。
systemd-resolved 不会修改它,你需要手动管理或用其他工具(如 NetworkManager)管理。
-
系统的情况
$ ls -lhart /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Jan 13 2022 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
# 文件内容兼容 /etc/resolv.conf 的格式
$ cat /run/systemd/resolve/stub-resolv.conf
nameserver 127.0.0.53
options edns0 trust-ad
search localdomain
# 本地监听 53 端口,代理到 DNS 配置的地址
$ ss -lpn | grep 53
udp UNCONN 0 0 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=668,fd=16))
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=668,fd=14))
tcp LISTEN 0 4096 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=668,fd=17))
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=668,fd=15))
Linux 应用程序获取名称解析
- systemd-resolved 服务
- glibc 的
getaddrinfo、gethostbyname API
- 此方法通过
glibc Name Service Switch 实现
glibc NSS 通过 nss-resolve 模块才能让 glibc NSS 使用 systemd-resolved 提供的名字解析功能
systemd-resolved 在本地 127.0.0.53 上提供的本地DNS服务器
常用管理命令 (resolvectl)
在较新的 systemd 版本中,管理工具是 resolvectl(旧版本为 systemd-resolve)。
resolvectl 用来解析主机名、IP 地址、域名、DNS 记录等
resolvectl 通过 systemd-resolved.service 实现相关功能
$ resolvectl --help
resolvectl [OPTIONS...] COMMAND ...
Send control commands to the network name resolution manager, or
resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.
Commands:
query HOSTNAME|ADDRESS... Resolve domain names, IPv4 and IPv6 addresses
service [[NAME] TYPE] DOMAIN Resolve service (SRV)
openpgp EMAIL@DOMAIN... Query OpenPGP public key
tlsa DOMAIN[:PORT]... Query TLS public key
status [LINK...] Show link and server status
statistics Show resolver statistics
reset-statistics Reset resolver statistics
flush-caches Flush all local DNS caches
reset-server-features Forget learnt DNS server feature levels
dns [LINK [SERVER...]] Get/set per-interface DNS server address
domain [LINK [DOMAIN...]] Get/set per-interface search domain
default-route [LINK [BOOL]] Get/set per-interface default route flag
llmnr [LINK [MODE]] Get/set per-interface LLMNR mode
mdns [LINK [MODE]] Get/set per-interface MulticastDNS mode
dnsovertls [LINK [MODE]] Get/set per-interface DNS-over-TLS mode
dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode
nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA
revert LINK Revert per-interface configuration
Options:
-h --help Show this help
--version Show package version
--no-pager Do not pipe output into a pager
-4 Resolve IPv4 addresses
-6 Resolve IPv6 addresses
-i --interface=INTERFACE Look on interface
-p --protocol=PROTO|help Look via protocol
-t --type=TYPE|help Query RR with DNS type
-c --class=CLASS|help Query RR with DNS class
--service-address=BOOL Resolve address for services (default: yes)
--service-txt=BOOL Resolve TXT records for services (default: yes)
--cname=BOOL Follow CNAME redirects (default: yes)
--search=BOOL Use search domains for single-label names
(default: yes)
--raw[=payload|packet] Dump the answer as binary data
--legend=BOOL Print headers and additional info (default: yes)
See the resolvectl(1) man page for details.
-
查看 DNS 状态:
显示所有接口的 DNS 服务器配置、当前的 DNS 协议支持情况等。
-
查询域名 (测试解析):
类似于 dig 或 nslookup。
resolvectl query google.com
-
清空 DNS 缓存:
如果你修改了 DNS 记录但本地仍然解析到旧 IP,可以执行此命令。
-
查看缓存统计:
查看缓存命中率、缓存大小等。
-
重置服务器状态:
如果 DNS 解析卡住或状态异常。
resolvectl reset-server-features
-
查找 SRV 服务
resolvectl service
resolvectl openpgp me@xiexianbin.cn
# 查域名解析
$ resolvectl query www.xiexianbin.cn
www.xiexianbin.cn: 60.200.32.109 -- link: ens33
60.200.32.108 -- link: ens33
60.200.32.115 -- link: ens33
60.200.32.114 -- link: ens33
60.200.32.113 -- link: ens33
60.200.32.112 -- link: ens33
60.200.32.111 -- link: ens33
60.200.32.110 -- link: ens33
(www.xiexianbin.cn.w.cdngslb.com)
# 查 IP
$ resolvectl query 223.5.5.5
223.5.5.5: public1.alidns.com -- link: ens33
# 查 MX 记录
$ resolvectl --legend=no -t MX query xiexianbin.cn
xiexianbin.cn IN MX 10 mxw.mxhichina.com -- link: ens33
xiexianbin.cn IN MX 5 mxn.mxhichina.com -- link: ens33
# tlsa
$ resolvectl tlsa tcp fedoraproject.org:443
_443._tcp.fedoraproject.org IN TLSA 3 1 1 5441af1dc3c6df9a6bd408daea995bd1a5e328404a271a575f11b4feebd93b09
-- Cert. usage: Domain-issued certificate
-- Selector: SubjectPublicKeyInfo
-- Matching type: SHA-256 -- link: ens33
为什么有人想要禁用它?
尽管 systemd-resolved 功能强大,但在某些场景下可能带来麻烦:
- 端口冲突: 它占用 53 端口。如果你想自己运行
dnsmasq、bind9 或 AdGuard Home,会发生冲突。
- VPN 泄漏或兼容性问题: 某些老旧的 VPN 客户端可能无法正确处理 Split DNS,导致 DNS 泄漏。
- 习惯问题: 许多管理员习惯直接编辑
/etc/resolv.conf,发现修改被 systemd 覆盖后会感到困扰。
如何禁用?
如果你决定不使用它,可以按照以下步骤操作(以 Ubuntu 为例):
# 1. 停止并禁用服务
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
# 2. 删除指向 systemd 的软链接
sudo rm /etc/resolv.conf
# 3. 创建一个新的 resolv.conf 并填入 DNS
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
扩展
localhost 不会路由到网络上
- 不包含
. 的名称,使用 LLMNR 协议路由到所有支持 IP 多播的本地接口
.local 后缀的名称,使用多播 DNS(MulticastDNS)协议路由到所有支持 IP 多播的本地接口
_gateway 路由到默认网关(多网关到字典序第一个)
F&Q
systemd-resolved[]: Failed to add DNS server address
journalctl -u systemd-resolved 出现如上错误日志
- 原因:
/etc/systemd/resolved.conf 中 DNS 字段配置异常导致,注意多个 DNS 使用空格分隔
总结
systemd-resolved 是现代 Linux 发行版(如 Ubuntu 18.04+, Fedora 等)网络栈的重要组成部分。它通过统一管理 DNS 请求,提供了更好的性能(缓存)和灵活性(针对不同接口的 DNS 配置)。对于大多数普通用户和服务器管理员,保留其默认设置是最佳选择;但对于需要精细控制 DNS 流量的高级用户,理解其工作原理(尤其是与 /etc/resolv.conf 的关系)至关重要。