systemd 教程 / DNS 解析(systemd-resolved)
DNS 解析(systemd-resolved)
概述
systemd-resolved 是 systemd 提供的 DNS 解析守护进程,提供域名解析、DNS 缓存、mDNS/LLMNR 支持等功能。它支持 DNS-over-TLS(DoT)加密、多链路 DNS(Split DNS)等现代 DNS 特性,是 systemd 网络栈的重要组成部分。
架构概览
┌──────────────┐
│ 应用程序 │ getaddrinfo() / NSS
├──────────────┤
│ glibc NSS │ nss-resolve
├──────────────┤
│ systemd- │ D-Bus 接口
│ resolved │ 本地 DNS stub (127.0.0.53)
├──────────────┤
│ 上游 DNS │ 递归解析器 / DoT / DoH
└──────────────┘
resolvectl 命令
resolvectl 是 systemd-resolved 的管理工具,功能非常丰富。
基本查询
# 查询域名
resolvectl query www.example.com
# 查询特定类型的 DNS 记录
resolvectl query --type=MX example.com
resolvectl query --type=TXT example.com
resolvectl query --type=AAAA example.com
# 反向查询(IP → 域名)
resolvectl query 8.8.8.8
查看状态
# 查看全局 DNS 配置
resolvectl status
# 查看特定链路的 DNS 配置
resolvectl status eth0
# 查看 DNS 缓存统计
resolvectl statistics
# 输出示例:
# DNSSEC supported: current no
#
# Cache: hit: 150 miss: 23
# Positive hits: 120
# Negative hits: 30
# Miss (DNS): 23
DNS 缓存管理
# 清除 DNS 缓存
resolvectl flush-caches
# 重置统计信息
resolvectl reset-statistics
# 查看缓存大小
resolvectl show-cache-size
DNSSEC 验证
# 查看 DNSSEC 状态
resolvectl show-dnssec
# 验证域名的 DNSSEC
resolvectl query --legend=no --verify=yes example.com
DNS 配置
全局配置
# /etc/systemd/resolved.conf
[Resolve]
# 配置上游 DNS 服务器
DNS=8.8.8.8 8.8.4.4 1.1.1.1
# 备用 DNS 服务器
FallbackDNS=9.9.9.9 149.112.112.112
# 搜索域
Domains=~.
# DNSSEC 模式
DNSSEC=allow-downgrade
# DNS-over-TLS
DNSOverTLS=opportunistic
# 缓存设置
Cache=yes
CacheFromLocalhost=no
# LLMNR 支持
LLMNR=yes
# mDNS 支持
MulticastDNS=yes
# DNS stub 监听
DNSStubListener=yes
# DNSStubListenerExtra=udp:127.0.0.54:53
[Resolve] 段参数详解
| 参数 | 说明 | 默认值 | 可选值 |
|---|---|---|---|
DNS | 上游 DNS 服务器 | - | IP 地址列表 |
FallbackDNS | 备用 DNS | 各发行版不同 | IP 地址列表 |
Domains | 搜索域 | - | 域名列表,~. 表示全局 |
DNSSEC | DNSSEC 模式 | allow-downgrade | yes / no / allow-downgrade |
DNSOverTLS | DoT 模式 | opportunistic | yes / no / opportunistic |
Cache | 启用缓存 | yes | yes / no / no-negative |
CacheFromLocalhost | 缓存本地响应 | no | yes / no |
LLMNR | LLMNR 支持 | yes | yes / no / resolve |
MulticastDNS | mDNS 支持 | yes | yes / no / resolve |
DNSStubListener | 监听 DNS stub | yes | yes / no / udp / tcp |
ReadEtcHosts | 读取 /etc/hosts | yes | yes / no |
ResolveUnicastSingleLabel | 解析单标签域名 | no | yes / no |
⚠️ 注意:修改配置后需要重启 systemd-resolved 才能生效。
DNS-over-TLS(DoT)
DNS-over-TLS 通过 TLS 加密 DNS 查询,防止 DNS 窥探和篡改。
配置 DoT
# /etc/systemd/resolved.conf
[Resolve]
# 严格模式:强制使用 TLS
DNS=1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google
DNSOverTLS=yes
DoT 模式
| 模式 | 说明 |
|---|---|
no | 不使用 DoT |
opportunistic | 尝试 DoT,失败则回退明文 |
yes(strict) | 强制 DoT,连接失败则查询失败 |
⚠️ 注意:严格模式需要 DNS 服务器支持 TLS,且服务器名称需正确配置(DNS=IP#hostname)。
验证 DoT
# 查看 DoT 状态
resolvectl status | grep -i "DNSOverTLS"
# 测试查询
resolvectl query www.example.com
多链路 DNS(Split DNS)
systemd-resolved 支持按网络接口路由 DNS 查询,即 Split DNS。
工作原理
当不同网络接口配置了不同 DNS 服务器时,查询会根据搜索域路由到对应 DNS:
eth0: DNS=10.0.0.1, Domains=internal.corp
eth1: DNS=8.8.8.8, Domains=~.
查询 app.internal.corp → 通过 eth0 (10.0.0.1)
查询 www.google.com → 通过 eth1 (8.8.8.8)
配置示例
# /etc/systemd/network/20-eth0.network
[Match]
Name=eth0
[Network]
Address=10.0.0.100/24
DNS=10.0.0.1
Domains=internal.corp
# /etc/systemd/network/20-eth1.network
[Match]
Name=eth1
[Network]
Address=192.168.1.100/24
DNS=8.8.8.8
Domains=~.
💡 提示:~. 前缀表示该 DNS 服务器作为全局默认。没有前缀的域表示精确匹配。
查看路由规则
# 查看各链路的 DNS 配置
resolvectl status
# 测试特定域的解析
resolvectl query app.internal.corp
# 输出应显示通过 eth0 解析
DNS 缓存
systemd-resolved 内建 DNS 缓存,减少对上游 DNS 的查询。
缓存行为
| 配置 | 说明 |
|---|---|
Cache=yes | 缓存所有 DNS 响应(默认) |
Cache=no | 禁用缓存 |
CacheFromLocalhost=yes | 缓存来自 127.0.0.1 的响应 |
管理缓存
# 查看缓存命中统计
resolvectl statistics
# 清除缓存
resolvectl flush-caches
# 清除特定域名的缓存
resolvectl query --flush-caches www.example.com
mDNS 与 LLMNR
mDNS(Multicast DNS)
mDNS 用于局域网内的名称解析,使用 .local 域名:
# 查询 mDNS 名称
resolvectl query myhost.local
# 查看 mDNS 状态
resolvectl status | grep -i mDNS
LLMNR(Link-Local Multicast Name Resolution)
LLMNR 是 Microsoft 的本地链路名称解析协议:
# 查看 LLMNR 状态
resolvectl status | grep -i LLMNR
| 参数 | 值 | 说明 |
|---|---|---|
yes | 启用 | 同时提供解析和响应 |
no | 禁用 | 不参与 LLMNR |
resolve | 仅解析 | 只做客户端,不响应 |
⚠️ 注意:在生产环境中,建议禁用 LLMNR(存在安全风险),mDNS 按需启用。
与 /etc/resolv.conf 兼容
连接方式
systemd-resolved 通过 127.0.0.53 的 DNS stub 监听器提供兼容性:
# 查看当前 resolv.conf
cat /etc/resolv.conf
# 推荐的符号链接
ls -la /etc/resolv.conf
# /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf
resolv.conf 文件
| 文件路径 | 说明 |
|---|---|
/run/systemd/resolve/stub-resolv.conf | 指向 127.0.0.53(推荐) |
/run/systemd/resolve/resolv.conf | 直接指向上游 DNS |
配置符号链接
# 创建正确的符号链接
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
# 验证
ls -la /etc/resolv.conf
⚠️ 注意:某些 VPN 客户端可能会覆盖 /etc/resolv.conf,导致 DNS 解析异常。建议使用符号链接方式。
实际场景
场景 1:VPN DNS 配置
当连接 VPN 时,需要将内部域名路由到 VPN 的 DNS 服务器:
# VPN 配置自动下发的 .network 文件
[Match]
Name=tun0
[Network]
DNS=10.8.0.1
Domains=~internal.corp ~vpn.corp
# 验证内部域名解析
resolvectl query wiki.internal.corp
# 应通过 VPN 解析
场景 2:容器 DNS
为容器配置专用 DNS:
# /etc/systemd/network/30-cni0.network
[Match]
Name=cni0
[Network]
DNS=10.96.0.10
Domains=~cluster.local
场景 3:企业内部 DNS + 公网 DNS
# /etc/systemd/resolved.conf
[Resolve]
# 公网 DNS
DNS=1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google
# 内部 DNS 通过 .network 文件配置
Domains=~.
DNSOverTLS=opportunistic
# /etc/systemd/network/20-eth0.network
[Match]
Name=eth0
[Network]
DNS=10.0.0.1
Domains=internal.corp ~intranet.corp
调试 DNS 解析
常用调试命令
# 查看完整状态
resolvectl status
# 查询域名并查看详细信息
resolvectl query www.example.com
# 查看 DNS 缓存统计
resolvectl statistics
# 清除缓存后重新查询
resolvectl flush-caches
resolvectl query www.example.com
# 查看日志
journalctl -u systemd-resolved
# 实时监控
journalctl -fu systemd-resolved
使用 dig/nslookup 对比
# 使用 resolvectl
resolvectl query www.example.com
# 使用 dig(通过 systemd-resolved)
dig @127.0.0.53 www.example.com
# 使用 nslookup
nslookup www.example.com 127.0.0.53
常见问题排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
| DNS 解析缓慢 | 缓存被禁用 | 确认 Cache=yes |
| 无法解析内部域名 | Split DNS 配置错误 | 检查 .network 文件的 Domains |
| VPN DNS 不工作 | resolv.conf 被覆盖 | 重新创建符号链接 |
| DoT 连接失败 | 服务器不支持 TLS | 改用 opportunistic 模式 |
| DNSSEC 验证失败 | 域名无 DNSSEC 记录 | 使用 allow-downgrade |
实用命令汇总
# 状态查看
resolvectl status
resolvectl statistics
# DNS 查询
resolvectl query example.com
resolvectl query --type=MX example.com
resolvectl query 8.8.8.8
# 缓存管理
resolvectl flush-caches
resolvectl reset-statistics
# 服务管理
sudo systemctl restart systemd-resolved
sudo systemctl status systemd-resolved
journalctl -u systemd-resolved
# 配置文件
sudo vim /etc/systemd/resolved.conf
sudo systemctl restart systemd-resolved