强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

NetworkManager 运维教程 / 第 7 章:DNS 配置

第 7 章:DNS 配置

7.1 NM DNS 管理机制

NetworkManager 通过 DNS 后端(backend)管理系统 DNS 配置,支持多种后端方案。

DNS 后端类型

后端配置值说明适用场景
内建默认defaultNM 直接写 /etc/resolv.conf简单场景
systemd-resolvedsystemd-resolved通过 systemd-resolved 管理现代发行版推荐
dnsmasqdnsmasq本地 DNS 缓存 + 转发需要本地缓存
nonenoneNM 不管理 DNS手动管理

查看当前 DNS 后端

# 方法 1:查看配置
cat /etc/NetworkManager/conf.d/*.conf | grep dns
cat /etc/NetworkManager/NetworkManager.conf | grep dns

# 方法 2:NM 输出的 DNS 配置信息
# 查看 NM 管理的 DNS 配置
nmcli device show | grep DNS

# 方法 3:查看 resolv.conf 指向
ls -la /etc/resolv.conf
# 如果是符号链接,说明使用了 resolved 或其他管理器

7.2 默认 DNS 后端(default)

NM 默认后端直接管理 /etc/resolv.conf

连接级 DNS 配置

# 查看连接的 DNS 设置
nmcli connection show "Wired connection 1" | grep ipv4.dns

# 设置手动 DNS(覆盖 DHCP 获取的)
nmcli connection modify "Wired connection 1" \
    ipv4.dns "8.8.8.8 8.8.4.4"

# 添加 DNS(追加到 DHCP 获取的 DNS 之后)
nmcli connection modify "Wired connection 1" \
    +ipv4.dns "1.1.1.1"

# 移除手动 DNS(恢复为自动获取)
nmcli connection modify "Wired connection 1" \
    ipv4.dns "" \
    ipv4.ignore-auto-dns no

# 忽略 DHCP 提供的 DNS
nmcli connection modify "Wired connection 1" \
    ipv4.ignore-auto-dns yes

# 设置搜索域
nmcli connection modify "Wired connection 1" \
    ipv4.dns-search "example.com internal.example.com"

# IPv6 DNS
nmcli connection modify "Wired connection 1" \
    ipv6.dns "2001:4860:4860::8888 2606:4700:4700::1111"

# 生效
nmcli connection up "Wired connection 1"

DNS 优先级

当有多个连接时,NM 根据路由度量值决定 DNS 顺序。也可以手动设置优先级:

# 设置 DNS 优先级(数值越小越优先)
nmcli connection modify "Wired connection 1" \
    ipv4.dns-priority 100

nmcli connection modify "VPN-Connection" \
    ipv4.dns-priority 50    # VPN 的 DNS 更优先

# 负值表示排除该连接的 DNS
nmcli connection modify "Guest-WiFi" \
    ipv4.dns-priority -1

# 查看所有连接的 DNS 配置
nmcli -f NAME,IP4.DNS,IP4.DNS-PRIORITY connection show

resolv.conf 管理

# NM 管理 resolv.conf 的行为由 rc-manager 配置

# 查看当前 resolv.conf
cat /etc/resolv.conf

# 检查是否为符号链接
ls -la /etc/resolv.conf

# NM 的 rc-manager 选项
# /etc/NetworkManager/conf.d/dns.conf
[main]
dns=default
# rc-manager=auto    # 默认,自动选择
# rc-manager=symlink # 创建符号链接到 NM 管理的文件
# rc-manager=file    # 直接写入 /etc/resolv.conf
# rc-manager=resolvconf # 使用 resolvconf 工具
# rc-manager=unmanaged # 不管理

# 如果 /etc/resolv.conf 被其他程序锁定
# 解决:删除并让 NM 管理
sudo rm /etc/resolv.conf
sudo systemctl restart NetworkManager

7.3 systemd-resolved 后端

systemd-resolved 是现代 Linux 发行版推荐的 DNS 解析服务。

启用 systemd-resolved

# 安装(如果未安装)
sudo apt install systemd-resolved    # Debian/Ubuntu(通常已安装)

# 配置 NM 使用 systemd-resolved
sudo tee /etc/NetworkManager/conf.d/dns.conf << 'EOF'
[main]
dns=systemd-resolved
EOF

# 确保 systemd-resolved 运行
sudo systemctl enable --now systemd-resolved

# 创建 resolv.conf 符号链接
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

# 重载 NM
sudo nmcli general reload conf
sudo systemctl restart NetworkManager

# 验证
resolvectl status

systemd-resolved 管理

# 查看全局 DNS 状态
resolvectl status

# 查看特定接口的 DNS
resolvectl status wlan0

# 查看 DNS 统计信息
resolvectl statistics

# 查看 DNS 缓存
resolvectl statistics
# 缓存命中/未命中会显示在输出中

# 清除 DNS 缓存
resolvectl flush-caches

# 查询 DNS(使用 resolved)
resolvectl query example.com
resolvectl query 192.168.1.1    # 反向解析

# 查看 DNSSEC 状态
resolvectl status | grep -i dnssec

systemd-resolved 配置文件

# /etc/systemd/resolved.conf
[Resolve]
# 全局 DNS 服务器(连接未指定时使用)
DNS=8.8.8.8 1.1.1.1
FallbackDNS=8.8.4.4 1.0.0.1

# 搜索域
Domains=~.

# DNSSEC 设置
# yes     = 启用
# no      = 禁用
# allow-downgrade = 允许降级
DNSSEC=allow-downgrade

# DNS over TLS
# yes     = 强制
# opportunistic = 尝试
# no      = 禁用
DNSOverTLS=opportunistic

# 缓存
Cache=yes
CacheFromLocalhost=no

# LLMNR(本地链路多播名称解析)
LLMNR=yes

# MulticastDNS
MulticastDNS=yes

# DNS Stub 监听器
DNSStubListener=yes
# DNSStubListenerExtra=udp:10.0.0.1:53
# 修改后重启
sudo systemctl restart systemd-resolved

7.4 dnsmasq 后端

dnsmasq 提供本地 DNS 缓存和 DHCP 服务。

# 安装 dnsmasq
sudo apt install dnsmasq-base    # 只需要 base,不需要独立服务

# 配置 NM 使用 dnsmasq
sudo tee /etc/NetworkManager/conf.d/dns.conf << 'EOF'
[main]
dns=dnsmasq
EOF

# 重载
sudo nmcli general reload conf
sudo systemctl restart NetworkManager

# dnsmasq 由 NM 自动启动和管理
# 查看 dnsmasq 进程
ps aux | grep dnsmasq

# dnsmasq 配置(NM 管理时通过 NM 配置)
# 自定义 dnsmasq 配置
sudo tee /etc/NetworkManager/dnsmasq.d/custom.conf << 'EOF'
# 缓存大小
cache-size=1000

# 日志查询
log-queries
log-facility=/var/log/dnsmasq.log

# 自定义域名解析
address=/internal.example.com/10.0.0.1

# 转发特定域名到特定 DNS
server=/vpn.example.com/10.0.0.53
EOF

# 重载 NM 生效
sudo nmcli general reload conf

三种 DNS 后端对比

特性defaultsystemd-resolveddnsmasq
缓存
DNSSEC
DNS over TLS
LLMNR/mDNS
自定义域名
内存占用极低
复杂度
推荐场景简单/容器桌面/服务器需要本地缓存

7.5 DNSSEC

# 查看 DNSSEC 状态
resolvectl status | grep -i "DNSSEC"

# 启用 DNSSEC(systemd-resolved)
sudo tee /etc/systemd/resolved.conf.d/dnssec.conf << 'EOF'
[Resolve]
DNSSEC=allow-downgrade
EOF
sudo systemctl restart systemd-resolved

# DNSSEC 模式说明:
# yes             - 严格验证,验证失败则拒绝
# allow-downgrade - 尝试验证,不支持时降级
# no              - 不验证

# 测试 DNSSEC 验证
resolvectl query dnssec-failed.org
# 如果 DNSSEC 工作正常,这个域名应该解析失败

# 查看 DNSSEC 验证详情
resolvectl query --statistics example.com

# 手动验证 DNSSEC
dig +dnssec example.com
dig +dnssec example.com DNSKEY

DNSSEC 故障处理

# 问题:某些域名无法解析(DNSSEC 验证失败)
# 临时方案:禁用 DNSSEC
sudo tee /etc/systemd/resolved.conf.d/no-dnssec.conf << 'EOF'
[Resolve]
DNSSEC=no
EOF
sudo systemctl restart systemd-resolved

# 更好的方案:使用 allow-downgrade
sudo tee /etc/systemd/resolved.conf.d/dnssec.conf << 'EOF'
[Resolve]
DNSSEC=allow-downgrade
EOF

7.6 DNS over TLS (DoT)

# 启用 DNS over TLS(systemd-resolved)
sudo tee /etc/systemd/resolved.conf.d/dot.conf << 'EOF'
[Resolve]
DNSOverTLS=opportunistic
# 可选值:
# yes            - 强制 TLS(服务器必须支持)
# opportunistic  - 尝试 TLS(不支持则回退明文)
# no             - 禁用
EOF
sudo systemctl restart systemd-resolved

# 使用支持 DoT 的 DNS 服务器
# Cloudflare: 1.1.1.1, 1.0.0.1
# Google: 8.8.8.8, 8.8.4.4
# Quad9: 9.9.9.9, 149.112.112.112

# 测试 DoT 是否工作
resolvectl query example.com
# 查看输出中的 "Protocols:" 字段

7.7 搜索域配置

搜索域用于简化域名输入,当输入不完整域名时自动补全。

# 设置搜索域
nmcli connection modify "Wired connection 1" \
    ipv4.dns-search "example.com internal.example.com"

# 多个连接的不同搜索域
nmcli connection modify "VPN-Connection" \
    ipv4.dns-search "corp.example.com"

# 查看当前搜索域
nmcli connection show "Wired connection 1" | grep dns-search

# 生效
nmcli connection up "Wired connection 1"

# 验证
cat /etc/resolv.conf
# search example.com internal.example.com

# 测试搜索域
# 如果搜索域是 example.com
# 输入 "server1" 会自动查询 "server1.example.com"
nslookup server1
resolvectl query server1

搜索域 vs DNS 域路由

# 搜索域:补全域名
nmcli connection modify "Office" \
    ipv4.dns-search "example.com"

# DNS 域路由:将特定域名的解析交给特定 DNS
# 在 systemd-resolved 中
# ~example.com 表示该连接负责解析 example.com 域
nmcli connection modify "VPN-Connection" \
    ipv4.dns-search "~corp.example.com"

7.8 DNS 问题排查

# 1. 查看当前使用的 DNS 服务器
resolvectl status
cat /etc/resolv.conf

# 2. 测试 DNS 解析
nslookup example.com
dig example.com
host example.com
resolvectl query example.com

# 3. 指定 DNS 服务器测试
nslookup example.com 8.8.8.8
dig @8.8.8.8 example.com

# 4. 查看 NM 管理的 DNS
nmcli device show | grep DNS

# 5. 清除 DNS 缓存
resolvectl flush-caches          # systemd-resolved
sudo systemctl restart dnsmasq   # dnsmasq

# 6. DNS 解析延迟测试
time nslookup example.com

# 7. 详细 DNS 调试
resolvectl query --legend=no example.com
dig +trace example.com

# 8. 检查 DNS 配置冲突
# 可能的问题:多个服务同时管理 resolv.conf
ls -la /etc/resolv.conf
# 检查是否有 symlink 指向错误的目标

7.9 常见 DNS 场景配置

场景 1:公司内网 + 公网 DNS

# 公网 DNS 作为默认
nmcli connection modify "Office-LAN" \
    ipv4.dns "8.8.8.8 8.8.4.4" \
    ipv4.dns-search "example.com" \
    ipv4.ignore-auto-dns yes

# 内网 DNS 用于公司域名
# 使用 systemd-resolved 的路由 DNS 功能
nmcli connection modify "Office-LAN" \
    +ipv4.dns "10.0.0.53" \
    +ipv4.dns-search "~internal.example.com"

场景 2:VPN 完整 DNS 隧道

# VPN 连接时使用 VPN 的 DNS
nmcli connection modify "Corp-VPN" \
    ipv4.dns "10.0.0.53" \
    ipv4.dns-search "corp.example.com" \
    ipv4.dns-priority -50 \
    ipv4.ignore-auto-dns no

场景 3:开发环境自定义 DNS

# 本地开发域名解析
# 使用 dnsmasq 后端
sudo tee /etc/NetworkManager/dnsmasq.d/dev.conf << 'EOF'
address=/dev.local/127.0.0.1
address=/api.dev.local/127.0.0.1
address=/db.dev.local/10.0.0.50
EOF
sudo nmcli general reload conf

7.10 本章小结

要点说明
DNS 后端default(直接写 resolv.conf)、systemd-resolveddnsmasqnone
推荐后端现代系统推荐 systemd-resolved
连接 DNSipv4.dns 设置手动 DNS,ipv4.ignore-auto-dns 忽略 DHCP DNS
DNS 优先级ipv4.dns-priority,负值排除
搜索域ipv4.dns-search~ 前缀表示域路由
DNSSECsystemd-resolved 支持,建议 allow-downgrade
DNS over TLSsystemd-resolved 支持 opportunistic 模式

扩展阅读