Ubuntu 24.04 搭建内网 DNS 服务器 (BIND9)
适用场景:企业内网域名解析、服务器命名规范、高可用主从架构
系统版本:Ubuntu 24.04 LTS
DNS 软件:BIND 9.18(Ubuntu 24.04 官方源)
DNS(Domain Name System)是互联网的"电话簿",而在内网环境中,拥有一套自己的 DNS 服务器意味着:
- 你可以用
ssh web.lan.example.com而不是ssh 172.16.2.20来登录服务器 - 当一台服务器 IP 变更时,只改 DNS 记录,不需要通知所有人更新 hosts 文件
- 通过主从架构实现高可用,一台挂了另一台顶上
本文将完整记录如何从零开始在 Ubuntu 24.04 LTS 上搭建一套生产级别的 BIND9 主从 DNS 服务器。
一、整体架构规划
二、安装软件
以下操作在两台服务器上都要执行。
1、系统更新与软件安装
# 系统更新sudoaptupdate&&sudoaptupgrade-y# 安装时区工具sudotimedatectl set-timezone Asia/Shanghai# 安装 BIND9sudoaptinstall-ybind9 bind9-utils bind9-doc安装完成后检查版本:
named-v#输出类似:BIND 9.18.39-0ubuntu0.24.04.5-Ubuntu (Extended Support Version) <id:>三、设置主机名
# dns-master 上sudohostnamectl set-hostname dns-master# dns-slave 上sudohostnamectl set-hostname dns-slave然后在两台机器的/etc/hosts里把短名和 FQDN 的映射写清楚:
172.16.2.38dns-master.lan.example.com dns-master172.16.3.228dns-slave.lan.example.com dns-slave四、解决 systemd-resolved 端口冲突(两台都执行)
BIND9 要监听 53 端口,但 Ubuntu(无论 Desktop 还是 Server)默认的systemd-resolved已经占着53端口。一山不容二虎,BIND9 起不来,我们需要停止systemd-resolved,把 53 端口腾出来给 BIND9。
# 停掉 systemd-resolvedsudosystemctl stop systemd-resolvedsudosystemctl disable systemd-resolved# 禁止它再监听 53sudosed-i's/^#DNSStubListener=.*/DNSStubListener=no/'/etc/systemd/resolved.confsudosystemctl restart systemd-resolved# resolv.conf 指向本机 BIND9,并锁定防覆盖sudorm-f/etc/resolv.confecho"nameserver 127.0.0.1"|sudotee/etc/resolv.confsudochattr +i /etc/resolv.conf五、创建规范目录(两台都执行)
区域文件不放默认位置,独立日志目录便于审计。两台都执行:
# 创建目录sudomkdir-p/data/bind/zonessudomkdir-p/data/bind/log/named# 日志目录归属 bind 用户sudochownbind:bind /data/bind/log/named# 区域文件目录允许 bind 组读取sudochownroot:bind /data/bind/zonessudochmod750/data/bind/zones六、生成 TSIG 密钥
在 dns-master 上生成:
sudotsig-keygen-ahmac-sha256 lan-zone-key|sudotee/etc/bind/keys.confsudochmod640/etc/bind/keys.confsudochownroot:bind /etc/bind/keys.conf复制到 dns-slave:
# 在 dns-master 上查看cat/etc/bind/keys.conf把输出完整复制,在 dns-slave 上创建:
sudovim/etc/bind/keys.conf# 粘贴sudochmod640/etc/bind/keys.confsudochownroot:bind /etc/bind/keys.conf七、主DNS服务器配置(dns-master)
配置文件总览
/etc/bind/ ├── named.conf ← 主入口,汇总所有配置 ├── named.conf.options ← 全局选项(监听、权限、转发、安全) ├── named.conf.local ← 区域定义(声明管理哪些域名) ├── named.conf.logging ← 日志配置 ├── keys.conf ← TSIG 密钥(主从认证凭证) /data/bind/zones/ ├── db.lan.example.com ← 正向区域文件(域名 → IP) └── db.172.16 ← 反向区域文件(IP → 域名)1、主入口/etc/bind/named.conf
include"/etc/bind/keys.conf";include"/etc/bind/named.conf.options";include"/etc/bind/named.conf.local";include"/etc/bind/named.conf.logging";2、全局选项/etc/bind/named.conf.options
acl"internal"{127.0.0.0/8;172.16.0.0/16;};options{directory"/var/cache/bind";listen-on port53{any;};listen-on-v6{none;};allow-query{"internal";};allow-recursion{"internal";};allow-transfer{none;};forwarders{8.8.8.8;1.1.1.1;};forward only;version none;hostnamenone;server-id none;recursionyes;max-cache-size 128M;dnssec-validation auto;allow-update{none;};};3、区域定义/etc/bind/named.conf.local
zone"lan.hyz.com"{typemaster;file"/data/bind/zones/db.lan.example.com";allow-transfer{key"lan-zone-key";};also-notify{172.16.3.228;};notifyyes;};zone"16.172.in-addr.arpa"{typemaster;file"/data/bind/zones/db.172.16";allow-transfer{key"lan-zone-key";};also-notify{172.16.3.228;};notifyyes;};4、正向区域文件/data/bind/zones/db.lan.example.com
$ORIGINlan.hyz.com.$TTL86400@ IN SOA dns-master.lan.hyz.com. admin.lan.hyz.com.(2024080401360090012096003600)@ IN NS dns-master.lan.hyz.com. @ IN NS dns-slave.lan.hyz.com. dns-master IN A172.16.2.38 dns-slave IN A172.16.3.2285、反向区域文件/data/bind/zones/db.172.16
$ORIGIN16.172.in-addr.arpa.$TTL86400@ IN SOA dns-master.lan.hyz.com. admin.lan.hyz.com.(2024080401360090012096003600)@ IN NS dns-master.lan.hyz.com. @ IN NS dns-slave.lan.hyz.com.38.2IN PTR dns-master.lan.hyz.com.228.3IN PTR dns-slave.lan.hyz.com.八、从DNS服务器配置(dns-slave)
从服务器不需要手动维护区域文件,全部自动从主服务器同步。
1、主入口/etc/bind/named.conf
include"/etc/bind/keys.conf";include"/etc/bind/named.conf.options";include"/etc/bind/named.conf.local";include"/etc/bind/named.conf.logging";2、全局选项/etc/bind/named.conf.options
与主服务器完全相同,直接复制:
acl"internal"{127.0.0.0/8;172.16.0.0/16;};options{directory"/var/cache/bind";listen-on port53{any;};listen-on-v6{none;};allow-query{"internal";};allow-recursion{"internal";};allow-transfer{none;};forwarders{8.8.8.8;1.1.1.1;};forward only;version none;hostnamenone;server-id none;recursionyes;max-cache-size 128M;dnssec-validation auto;allow-update{none;};};3、区域定义/etc/bind/named.conf.local
zone"lan.hyz.com"{typeslave;file"/var/cache/bind/db.lan.example.com";masters{172.16.2.38 key"lan-zone-key";};allow-transfer{none;};};zone"16.172.in-addr.arpa"{typeslave;file"/var/cache/bind/db.172.16";masters{172.16.2.38 key"lan-zone-key";};allow-transfer{none;};};九、日志配置
两台服务器都执行。生产环境必须有独立日志,出问题时才能追溯。
1、创建日志配置文件
sudovim/etc/bind/named.conf.logging写入
logging{channel"default_log"{file"/data/bind/log/named/default.log"versions10size 50m;severity info;print-timeyes;print-categoryyes;};channel"query_log"{file"/data/bind/log/named/queries.log"versions5size 100m;severity info;print-timeyes;};channel"security_log"{file"/data/bind/log/named/security.log"versions10size 20m;severity warning;print-timeyes;print-categoryyes;};channel"xfer_log"{file"/data/bind/log/named/zone-transfers.log"versions5size 20m;severity info;print-timeyes;};category default{default_log;};category queries{query_log;};category security{security_log;};category xfer-in{xfer_log;};category xfer-out{xfer_log;};category notify{xfer_log;};};四类日志各司其职:
| 日志 | 内容 | 用途 |
|---|---|---|
default.log | 启动、重载、常规事件 | 日常巡检 |
queries.log | 每一条 DNS 查询 | 审计、排错 |
security.log | 拒绝访问、可疑请求 | 安全告警 |
zone-transfers.log | 区域传输成功/失败 | 主从同步监控 |
2、配置日志轮转
sudovim/etc/logrotate.d/bind9防止磁盘被日志吃满:
rotate 30表示保留最近 30 天的日志,超出自动删除。compress把旧日志压缩成.gz,节省磁盘。
/data/bind/log/named/*.log{daily missingok rotate30compress delaycompress notifempty create 0640bindbindpostrotate /usr/sbin/invoke-rc.d bind9 reload>/dev/null endscript}十、AppArmor 白名单配置
两台服务器都执行
vim/etc/apparmor.d/local/usr.sbin.named写入:
/data/bind/zones/** r, /data/bind/log/named/** rw,重载策略:
sudoapparmor_parser-r/etc/apparmor.d/usr.sbin.named验证:
sudoaa-status|grepnamed# 应该看到 named 在 enforce 模式十一、配置校验更新与功能验证
1、语法检查
#dns-master执行sudonamed-checkconfsudonamed-checkzone lan.example.com /data/bind/zones/db.lan.example.comsudonamed-checkzone16.172.in-addr.arpa /data/bind/zones/db.172.16#dns-slave执行sudonamed-checkconf全部应输出OK
2、重载配置(在线热更新,不中断服务)
两台都执行:
sudorndc reload用reload而不是restart。reload只重新读取变更的配置文件,内存中的 DNS 缓存保留,查询不中断。restart会停掉再起,有几秒的服务空窗期,缓存也丢了。
3、验证区域传输
在dns-slave上查看传输日志:
sudotail/data/bind/log/named/zone-transfers.log看到类似内容说明同步成功:
4、查询测试
# 从主服务器查询 dns-slave 的 IPdig@172.16.2.38 dns-slave.lan.hyz.com +short# 期望输出:172.16.3.228# 从从服务器查询 dns-master 的 IPdig@172.16.3.228 dns-master.lan.hyz.com +short# 期望输出:172.16.2.38# 测试外网转发(确认能正常上网解析)dig@172.16.2.38 www.baidu.com +short# 期望输出:公网 IP十二、如何添加 DNS 解析记录
操作只在 dns-master 上进行,dns-slave 会自动同步。
1、编辑正向区域文件
sudovim/data/bind/zones/db.lan.example.com修改内容:
- 递增 serial:
2024080401→2024080402 - 末尾添加 A 记录:
2、编辑反向区域文件
sudovim/data/bind/zones/db.172.16修改内容:
- 递增 serial:与正向一致(
2024080402) - 末尾添加 PTR 记录。IP
172.16.2.14→ octet 逆序14.2
3、语法检查
sudonamed-checkzone lan.hyz.com /data/bind/zones/db.lan.example.comsudonamed-checkzone16.172.in-addr.arpa /data/bind/zones/db.172.16期望输出均为OK
4、重载服务
sudorndc reload5、验证解析
# 正向:域名 → IPdig@127.0.0.1 test.lan.hyz.com# 反向:IP → 域名dig@127.0.0.1-x172.16.2.14# 从服务器同步验证dig@172.16.3.228 test.lan.hyz.com十三、客户端接入内网 DNS
接入方式选择
| 方式 | 适用场景 | 推荐度 |
|---|---|---|
| 路由器 DHCP 下发 | 所有设备自动获取 | ⭐⭐⭐ 最推荐 |
| 手动设置 DNS | 单台设备测试/特殊需求 | ⭐⭐ 临时用 |
方式一:路由器 DHCP 下发(推荐)
所有客户端零配置,连上网络自动获取内网 DNS。
登录路由器管理后台——找到DHCP 服务器设置——修改 DNS:
首选 DNS(Primary DNS): 172.16.2.38 备用 DNS(Secondary DNS): 172.16.3.228关闭 DNS 代理/劫持/重定向(有些路由器会强制把所有 DNS 请求劫持到自身)
| 路由器品牌 | 相关设置名称 |
|---|---|
| 爱快/iKuai | DNS 加速服务 → 关闭 |
| 华为/华三 | DNS 透明代理 → 关闭 |
| OpenWrt | DHCP/DNS → 禁止重定向 |
| 锐捷/Ruijie | DNS 代理 → 关闭 |
| TP-Link 企业级 | DNS 代理 → 关闭 |
保存设置,路由器会自动重启 DHCP 服务。
方式二:客户端手动设置DNS
适用场景:临时测试、单台设备不通过 DHCP。
以Windows11系统为例子将DNS服务器地址改成:主172.16.2.38 和 备172.16.3.228
验证客户端 DNS 是否生效:打开CMD控制台输入以下指令
# 查看当前 DNS:预期:DNS 服务器显示 172.16.2.38 / 172.16.3.228ipconfig /all# 测试解析:返回 172.16.2.14,服务器显示 dns-master.lan.hyz.comnslookuptest.lan.hyz.com#预期:可正常解析公网域名nslookupbaidu.com