
Unbound 是由 NLnet Labs 开发的一款轻量级、支持 DNSSEC 验证的递归 DNS 解析器。与 BIND、PowerDNS 这类权威 DNS 服务器不同,Unbound 的核心职责不是托管 DNS 区域,而是:
兼容性说明:本文的操作步骤同样适用于 Rocky Linux 10、RHEL 10 和 AlmaLinux 10。这三个发行版都通过
dnf提供相同的 unbound 软件包,配置文件路径和运行行为基本一致。
本指南使用两台 Rocky Linux 10 主机:
| 角色 | IP 地址 | 主机名 |
|---|---|---|
DNS 服务器负责运行 Unbound,客户端则通过它进行 DNS 查询。
安装之前,请确保 DNS 服务器的主机名正确且IP 地址为静态。因为客户端会持续向这台服务器发起 DNS 请求,一旦 IP 变动,所有客户端都需要手动更新 DNS 配置。
在 DNS 服务器上执行以下命令,确认主机名和 IP:
hostnamectl
ip -4 addr show
可以看到主机名为 resolver.haopythonlocal.com,网卡 IP 为 192.168.1.50。
先更新系统软件包,然后安装 Unbound 和 bind-utils:
sudo dnf update -y
sudo dnf install -y unbound bind-utils
bind-utils 包里包含了 dig 命令,这是测试 DNS 最趁手的工具。稍后我们会用它来验证 Unbound 是否正常解析和缓存。
修改配置前,建议先备份默认配置文件,万一改错了可以快速恢复:
sudo cp /etc/unbound/unbound.conf /etc/unbound/unbound.conf.orig
用vim编辑器打开配置文件:
sudo vim /etc/unbound/unbound.conf
在 server: 段中添加或修改以下配置:
server:
interface:192.168.1.50
interface:127.0.0.1
port:53
do-ip4:yes
do-udp:yes
do-tcp:yes
access-control:127.0.0.0/8allow
access-control:192.168.1.0/24allow
access-control:0.0.0.0/0refuse
hide-identity:yes
hide-version:yes
verbosity:1
logfile:"/var/log/unbound.log"
use-syslog:no
# 配置项解读
| 配置项 | 作用说明 |
|---|---|
interface | |
do-ip4 / do-udp / do-tcp | |
access-control | |
hide-identity / hide-version | |
verbosity / logfile / use-syslog | verbosity: 1 输出基本运行日志,独立日志文件便于后续排错。 |
DNSSEC 支持:Rocky Linux 10 上的 Unbound 默认开启 DNSSEC 验证,使用根信任锚自动校验签名响应,大多数情况下无需额外配置。
# 配置上游转发器
默认情况下,Unbound 会执行完整的递归查询(直接联系根 DNS 服务器)。但在大多数场景下,转发到可信的上游 DNS 提供商更简单、也更快。
在配置文件末尾追加以下内容:
forward-zone:
name:"."
forward-addr:223.5.5.5# 阿里云首选
forward-addr:223.6.6.6# 阿里云备用
# 可选:再加一个腾讯作为兜底
# forward-addr: 119.29.29.29
如果第一个服务器不可用,Unbound 会自动尝试下一个。
启动 Unbound 之前,先确认没有其他服务占用 53 端口(DNS 标准端口)。
Rocky Linux 默认启用的 systemd-resolved 通常会在 127.0.0.53:53 上监听一个本地 DNS stub。如果 53 端口已被占用,Unbound 将无法启动。
检查端口占用情况:
sudo ss -tulpn | grep :53
如果看到 systemd-resolved 占用了 53 端口,只需禁用其 DNS stub 监听器,同时保留其他系统功能:
sudo mkdir -p /etc/systemd/resolved.conf.d
echo -e "[Resolve]\nDNSStubListener=no" | sudo tee /etc/systemd/resolved.conf.d/no-stub.conf
sudo systemctl restart systemd-resolved
重启后再检查一次:
sudo ss -tulpn | grep :53
如果 53 端口已空闲,下一步就可以顺利启动 Unbound 了。
启动前先做语法检查,提前发现配置错误:
sudo unbound-checkconf
如果配置无误,会返回:
unbound-checkconf: no errors in /etc/unbound/unbound.conf
如果有报错,Unbound 通常会指出具体行号。修正后再次运行检查,直到无错误为止。
配置通过验证后,启动服务并设为开机自启:
sudo systemctl enable --now unbound
查看服务状态:
sudo systemctl status unbound
正常情况应显示 active (running):
● unbound.service - Unbound DNS server
Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled)
Active: active (running) since ...
如果启动失败,查看状态输出中的错误信息,或检查日志:
sudo journalctl -u unbound --no-pager
如果启用了 firewalld,需要允许 DNS 入站流量,否则局域网内的客户端无法访问:
sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload
验证规则是否生效:
sudo firewallctl --list-services
你应该能看到 dns 出现在允许的服务列表中,例如:
cockpit dhcpv6-client dns ssh
至此,防火墙已配置完成,允许 Unbound 配置中授权的客户端发起 DNS 请求。
现在来验证 Unbound 是否真正在缓存 DNS 响应。在 DNS 服务器上,用 dig 直接指向 Unbound 查询一个域名:
dig haopython.com @192.168.1.50
关注输出中的 Query time 字段。第一次查询通常较慢,因为 Unbound 需要向上游 DNS 发起递归解析:
;; Query time: 68 msec
;; SERVER: 192.168.1.50#53(192.168.1.50)
再执行一次同样的命令:
dig haopython.com @192.168.1.50
这次响应应该快得多,因为结果直接从缓存返回:
;; Query time: 0 msec
;; SERVER: 192.168.1.50#53(192.168.1.50)
实际查询时间因网络环境和上游 DNS 而异,但第二次查询通常明显快于第一次。从本地缓存返回时,0 ms 或 1 ms 很常见。
换几个域名再试试:
dig baidu.com @192.168.1.50
dig github.com @192.168.1.50
每个域名执行两次,对比 Query time。第一次走上游,第二次走缓存——这就是 DNS 缓存生效的最佳证明。
DNS 服务器跑起来之后,最后一步是让客户端指向它。
如果使用 NetworkManager,将 Unbound 服务器(192.168.1.50)设为首选 DNS:
先列出可用连接:
nmcli connection show
记下活跃连接的名称(例如 "Wired connection 1"),然后执行:
sudo nmcli connection modify "Wired connection 1" ipv4.dns "192.168.1.50"
sudo nmcli connection modify "Wired connection 1" ipv4.ignore-auto-dns yes
sudo nmcli connection up "Wired connection 1"
这几条命令让客户端使用你的 Unbound 服务器解析 DNS,而不再依赖路由器或 DHCP 自动分配的 DNS。
查看 /etc/resolv.conf 确认配置:
cat /etc/resolv.conf
应该能看到:
nameserver 192.168.1.50
在客户端上测试解析:
dig baidu.com
输出中的 SERVER 字段应显示你的 Unbound 服务器:
;; SERVER: 192.168.1.50#53(192.168.1.50)
再测几个域名:
dig github.com
dig haopython.com
如果查询成功且 SERVER 指向 192.168.1.50,说明客户端已成功接入 Unbound。
从此以后,重复查询同一域名时,Unbound 会优先从缓存返回结果,减少查询延迟,降低对上游 DNS 的无效请求。
以下 unbound-control 命令覆盖了日常维护的大部分场景:
| 命令 | 用途 |
|---|---|
sudo unbound-control status | |
sudo unbound-control stats_noreset | grep total | |
sudo unbound-control dump_cache > /tmp/dns_cache_backup.txt | |
sudo unbound-control lookup haopython.com | |
sudo unbound-control flush haopython.com | |
sudo unbound-control flush_zone haopythonlocal.com |
# 常见故障排查
如果客户端报告无法解析任何域名,优先执行:
sudo journalctl -u unbound -f
绝大多数问题可归因于两类原因:
(1)访问控制问题:access-control 未包含客户端所在子网
(2)上游不可达:forward-zone 指向的上游 DNS 服务器在网络中无法访问
至此,已经在 Rocky Linux 10 上成功部署了 Unbound 作为本地 DNS 缓存解析器。
