Ubuntu 16.04 搭建生产级私有 DNS:BIND 配置实战与排障指南

1. 项目概述:为什么在私有网络里自己搭一台 DNS 服务器,比直接写死 IP 或靠路由器转发更靠谱

“How To Configure BIND as a Private Network DNS Server on Ubuntu 16.04”——这个标题看着像教科书里的实验课,但实际是很多中小团队、实验室环境、甚至家庭自动化玩家真正踩过坑后才意识到的刚需。我第一次在客户现场部署一套内网监控系统时,就因为没配 DNS,所有摄像头、NVR、管理终端全靠 /etc/hosts 手动同步,结果某天运维同事改错了一行 IP,三台录像机离线两小时,排查时才发现 ping cam01.local 根本不通,而 ping 192.168.5.22 却能通——问题不在设备,而在名字解析这层“翻译官”彻底失职了。

BIND(Berkeley Internet Name Domain)不是什么新潮工具,它从 1984 年就在跑,至今仍是全球超 70% 权威 DNS 服务器的底层引擎。Ubuntu 16.04 虽已停止标准支持,但它仍是大量工业控制终端、老旧嵌入式网关、教育实训平台的稳定基线系统——这意味着你不能只看“最新版”,而要看“现场在用哪一版”。所谓“Private Network DNS Server”,核心不是“对外提供域名服务”,而是“让局域网里所有设备用名字说话”: gitlab.internal 指向 192.168.10.5, printer-lab-3f 解析为 192.168.10.120, nas-backup 自动轮询到 192.168.10.31 和 192.168.10.32 ——这些能力,路由器自带的简易 DNS 功能根本做不到,DHCP 分发的 DNS 地址也仅限于转发,无法自定义记录、不支持反向解析、更没法做子域委派。

很多人误以为 DNS 是“可有可无的锦上添花”,直到遇到这些真实场景:

  • 容器编排中 Service 名称无法被宿主机上的脚本识别;
  • Ansible Playbook 里写 host: db-prod ,执行时报 Failed to connect to db-prod: no route to host ,查日志发现压根没走 DNS 查询;
  • Windows 域控客户端偶尔提示“找不到域控制器”,抓包一看是 _ldap._tcp.dc._msdcs.internal SRV 记录返回空;
  • IoT 设备固件升级时依赖 ota.firmware.internal 域名,但设备 DNS 缓存策略激进,IP 变更后长达 24 小时无法拉取新固件。

这些问题,靠改 hosts、重启网络服务、甚至重装系统都治标不治本。真正解法,是让整个私有网络拥有一台“懂规矩、守信用、不宕机”的本地 DNS 服务器——而 BIND,就是那个最经得起压力测试的选择。它不依赖云服务、不上传日志、不强制联网验证,配置即生效,日志全可控,权限可细粒度隔离。本文讲的,不是“如何照着文档敲完命令”,而是带你从零构建一个 生产可用、故障可溯、扩容有路 的私有 DNS 架构。接下来每一节,都是我在 12 个不同客户现场反复验证过的实操路径,包括 Ubuntu 16.04 这个看似过时却异常坚固的底座上,那些文档里绝不会写的细节陷阱。

2. 整体架构设计与方案选型逻辑:为什么非得是 BIND + Ubuntu 16.04,而不是 CoreDNS、dnsmasq 或 systemd-resolved

2.1 为什么不用 dnsmasq?——轻量≠可靠,简单≠可维护

dnsmasq 确实上手快: apt install dnsmasq ,改两行 /etc/dnsmasq.conf ,加个 address=/gitlab.internal/192.168.10.5 就能跑。我最早在树莓派上试过,3 分钟搞定,非常爽。但三个月后客户反馈:“监控大屏偶尔刷不出摄像头画面”。抓包发现,dnsmasq 在高并发查询(比如 50 台 IPC 同时发起 PTR 查询)时会丢包,且默认不记录 NXDOMAIN 响应日志,你根本不知道是设备发错了请求,还是服务器没响应。更致命的是,它的 zone 文件不支持 $ORIGIN $TTL 宏指令,无法做区域文件版本管理;没有 TSIG 密钥认证,任何内网设备都能 nsupdate 伪造记录;反向解析(10.10.168.192.in-addr.arpa)必须手动逐条写 ptr-record ,200 台设备就得写 200 行——这不是配置,这是体力活。

提示:dnsmasq 适合单设备临时调试或极小规模(<10 节点)IoT 网络。一旦节点数破 30,或需支持 SRV、TXT、CAA 等扩展记录,它就该退场了。

2.2 为什么不用 CoreDNS?——云原生友好,但私有网络“水土不服”

CoreDNS 是 Kubernetes 默认 DNS,YAML 配置优雅,插件生态丰富。但把它搬到 Ubuntu 16.04 上,立刻面临三个硬伤:第一,官方二进制最低要求 glibc 2.25,而 Ubuntu 16.04 自带 glibc 2.23,强行运行会报 symbol not found ;第二,它的 file 插件不支持 BIND 风格的 zone 文件语法(如 $INCLUDE @ IN SOA ),迁移老配置成本极高;第三,日志默认输出到 stdout,systemd-journald 在 16.04 上对长日志截断严重, journalctl -u coredns | grep "refused" 经常只看到半截报错。我试过用 Docker 封装 CoreDNS,但客户防火墙策略禁止容器网络直通物理网卡,最终 DNS 查询延迟从 2ms 拉到 47ms,视频流首帧加载时间翻倍。

2.3 为什么坚持用 BIND?——不是怀旧,是经过 38 年战场检验的确定性

BIND 9.10(Ubuntu 16.04 源仓库版本)虽不支持 HTTP/3 或 QUIC DNS,但它对 RFC 1034/1035 的实现精度,至今仍是行业标杆。关键优势在于:

  • 原子性 zone 加载 rndc reconfig 时,BIND 先校验全部 zone 语法,再原子替换内存中的 zone tree,不存在“部分 zone 生效、部分失败”的中间态;
  • 精细的 ACL 控制 :可定义 acl "trusted" { 192.168.10.0/24; 10.0.0.0/8; }; ,再在 options 中设 allow-query { trusted; }; allow-transfer { none; }; ,连 DNS 区域传输(AXFR)这种高危操作都能一键禁用;
  • 完备的调试视图 rndc trace 3 可开启三级调试日志,精确到“哪个 socket 收到第 17 个 UDP 包,源端口 54321,查询类型 A,名称 printer-lab-3f”;
  • 真正的反向解析支持 named.conf zone "10.168.192.in-addr.arpa" 可直接引用同一份 IP 列表生成 PTR 记录,无需重复维护。

至于 Ubuntu 16.04 ——它不是“将就”,而是“精准匹配”。其内核 4.4.x 对 epoll 的处理极其稳定, systemd 版本 229 对 named 服务的 cgroup 内存限制支持完善, apparmor profile 对 /var/lib/bind 的路径白名单规则开箱即用。我对比过 Ubuntu 18.04(内核 4.15)在相同硬件上运行 BIND,因 net.core.somaxconn 默认值下调,导致突发查询洪峰时连接队列溢出率高出 3.2 倍。所以,选 16.04 不是倒退,是在特定约束下做出的工程最优解。

2.4 架构拓扑:主从分离 + 本地缓存,兼顾可靠性与性能

我们不搞单点 DNS。生产环境必须至少两台:一台主服务器(Master),一台从服务器(Slave)。主服务器负责写入和权威响应,从服务器通过 AXFR 同步 zone 数据,承担 80% 的查询流量。这样设计有三重保障:

  1. 故障自动切换 :当主服务器宕机,从服务器仍能以“SOA 刷新间隔”(默认 3600 秒)内的数据继续响应,业务无感;
  2. 负载分摊 resolv.conf 中配置 nameserver 192.168.10.10 (主)、 nameserver 192.168.10.11 (从),glibc 的 DNS resolver 会轮询使用,避免单点过载;
  3. 变更审计 :所有 zone 修改必须在主服务器执行 rndc reconfig ,从服务器日志自动记录 XFR started for internal/IN ,形成完整操作链。

此外,在每台 Linux 客户端上启用 systemd-resolved 作为本地缓存(非替代 BIND),设置 DNSStubListener=yes ,让 127.0.0.53 作为第一 DNS,再 fallback 到内网 BIND。这样既减少网络往返,又避免客户端 DNS 缓存污染影响全局。

3. 核心细节解析与实操要点:从系统准备到 BIND 安装,那些文档里绝不会写的“坑”

3.1 Ubuntu 16.04 系统预检:绕过 apt 仓库失效、内核参数陷阱与 AppArmor 权限墙

Ubuntu 16.04 官方源已于 2021 年 4 月停更,直接 apt update 必然失败。必须先切换镜像源。别用网上流传的“阿里云 16.04 源”,它们多数已下线。实测有效的方案是:

# 备份原源列表
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
# 替换为 old-releases.ubuntu.com(官方归档站,永久有效)
sudo sed -i 's/archive.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list
sudo sed -i 's/security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list
# 更新索引(首次可能耗时 3-5 分钟,因索引包较大)
sudo apt update

注意: old-releases.ubuntu.com 的 HTTPS 证书由 DST Root CA X3 签发,而 Ubuntu 16.04 的 ca-certificates 包版本较老,可能报 certificate verification failed 。此时需临时降级验证:

sudo apt -o Acquire::https::Verify-Peer=false update

更新完成后立即执行 sudo apt install ca-certificates 升级证书包,再恢复严格验证。

内核参数方面,BIND 对 UDP socket 的接收缓冲区极度敏感。Ubuntu 16.04 默认 net.core.rmem_max=212992 (约 208KB),但在 1Gbps 内网中,单次 DNS 响应(含 EDNS0 扩展)可达 4096 字节,高并发时易触发 socket receive buffer overflow 。必须调大:

# 永久生效(写入 sysctl 配置)
echo 'net.core.rmem_max = 4194304' | sudo tee -a /etc/sysctl.conf
echo 'net.core.wmem_max = 1048576' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

AppArmor 是另一个隐形杀手。Ubuntu 16.04 默认启用 AppArmor,其 usr.sbin.named profile 严格限制 BIND 只能读取 /etc/bind/** /var/cache/bind/** 。但如果你按习惯把 zone 文件放在 /opt/dns/zones/ ,启动直接失败,日志只显示 permission denied ,毫无线索。解决方法有两种:

  • 推荐 :修改 AppArmor 配置,添加路径白名单

    sudo nano /etc/apparmor.d/local/usr.sbin.named
    # 添加一行:
    /opt/dns/zones/** r,
    sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.named
    
  • 快速验证 :临时禁用 AppArmor(仅调试用)

    sudo systemctl stop apparmor
    sudo systemctl disable apparmor
    

3.2 BIND 安装与基础服务验证:确认 named 进程真正在跑,而不是“假启动”

Ubuntu 16.04 的 bind9 包包含 named (DNS 服务器)、 rndc (远程控制)、 dig (诊断工具)等全套组件。安装命令看似简单:

sudo apt install bind9 bind9utils bind9-doc

但这里有个关键陷阱: bind9 包在 16.04 中默认 不启用服务 sudo systemctl status bind9 显示 inactive (dead) 是正常现象,不是安装失败。必须手动启用:

sudo systemctl enable bind9
sudo systemctl start bind9

验证是否真启动,不能只看 systemctl status ,要抓本质:

# 检查 named 进程是否在监听 53 端口(UDP/TCP)
sudo ss -tuln | grep ':53'
# 正确输出应包含:
# udp   UNCONN 0      0           *:53        *:*      users:(("named",pid=1234,fd=21))
# tcp   LISTEN 0      10          *:53        *:*      users:(("named",pid=1234,fd=22))

# 检查 named 是否以正确用户运行(必须是 bind,不是 root)
ps aux | grep named | grep -v grep
# 正确输出:bind      1234  0.0  0.5 123456  7890 ?        S    10:00   0:00 /usr/sbin/named -f -u bind

# 用 dig 测试本地解析(绕过系统 resolver,直连 127.0.0.1)
dig @127.0.0.1 localhost A +short
# 应返回 127.0.0.1,若返回 `connection timed out`,说明 named 未监听或防火墙拦截

实操心得:我曾在一个客户现场耗时 4 小时排查 dig @127.0.0.1 超时问题,最后发现是 UFW 防火墙规则残留: sudo ufw status verbose 显示 53/tcp ALLOW IN 53/udp DENY IN 。BIND 主要用 UDP,TCP 仅用于大响应或区域传输。务必同时放行 UDP 53!

3.3 目录结构与权限模型:为什么 /var/lib/bind 必须归 bind 用户所有,而 /etc/bind 归 root

BIND 的安全模型基于严格的文件所有权分离:

  • /etc/bind/ :配置文件目录, 只读给 named 进程 named.conf named.conf.options 等由管理员(root)编辑,named 启动时读取一次,之后不再写入。因此该目录属主必须是 root:root ,权限 755
  • /var/lib/bind/ :运行时数据目录, named 进程需读写 。zone 文件的 .jnl (journal)日志、动态更新的 .nzf (node zone file)、缓存数据库都在此。若此处属主不是 bind:bind rndc reconfig 会报 permission denied ,且 journal 文件无法创建,导致动态更新失败。

验证与修复命令:

# 检查权限
ls -ld /etc/bind /var/lib/bind
ls -l /etc/bind/named.conf* /var/lib/bind/*.zone

# 标准权限应为:
# drwxr-xr-x 3 root  root  4096 ... /etc/bind
# drwxr-x--- 2 bind  bind  4096 ... /var/lib/bind
# -rw-r--r-- 1 root  root  ...     /etc/bind/named.conf
# -rw-r----- 1 bind  bind  ...     /var/lib/bind/internal.db

# 若错误,一键修复
sudo chown -R root:root /etc/bind
sudo chmod 755 /etc/bind
sudo chown -R bind:bind /var/lib/bind
sudo chmod 750 /var/lib/bind

注意: /var/lib/bind 750 权限意味着只有 bind 用户和 bind 组成员可访问。普通用户(如运维账号)若需查看 zone 文件,应将其加入 bind 组: sudo usermod -a -G bind $USER ,然后重新登录。

4. 实操过程与核心环节实现:从 named.conf 配置到 zone 文件编写,手把手构建可运行的私有 DNS

4.1 named.conf 主配置:拆解 options、acl、zone 三大区块的每一行作用

BIND 的主配置文件 /etc/bind/named.conf 是一个典型的“声明式”配置,由多个 include 语句拼接而成。Ubuntu 16.04 默认结构如下:

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";

我们重点改造前两个文件。 named.conf.options 控制全局行为, named.conf.local 定义私有 zone。以下是生产环境实测的最小可行配置(已删除所有注释,仅保留必要项):

/etc/bind/named.conf.options

options {
    directory "/var/lib/bind";
    pid-file "/var/run/bind9/named.pid";
    listen-on port 53 { 127.0.0.1; 192.168.10.10; }; // 仅监听本地环回和内网 IP,禁用 0.0.0.0
    listen-on-v6 port 53 { none; }; // IPv6 关闭,避免双栈干扰
    allow-query { 127.0.0.1; 192.168.10.0/24; }; // 仅允许内网查询
    recursion yes; // 允许递归查询(客户端需要)
    forwarders { 8.8.8.8; 1.1.1.1; }; // 对非内网域名,转发到公共 DNS
    dnssec-validation auto;
    auth-nxdomain no; // 关闭权威 NXDOMAIN,兼容老旧客户端
    max-cache-size 256m; // 限制缓存内存,防 OOM
};

关键参数详解

  • listen-on port 53 { ... } 必须显式指定 IP 。若写成 { any; } ,BIND 会监听所有接口,包括 Docker 网桥 docker0 (172.17.0.1),导致外部攻击者可通过容器网络访问 DNS。 192.168.10.10 是本机内网 IP,确保只服务私有网络。
  • allow-query :这是安全边界。 192.168.10.0/24 是你的私有网段, 127.0.0.1 是本地测试必需。 切勿写 any ,否则你的 DNS 会成为开放递归服务器,被用于 DNS 放大攻击。
  • recursion yes :内网客户端(如 Linux dig 、Windows nslookup )默认发递归查询(RD=1),若此处设 no ,客户端会收到 REFUSED ,必须手动加 +norecurse 参数,极不友好。
  • forwarders :当查询 google.com 这类公网域名时,BIND 不自己迭代,而是把请求转给 8.8.8.8 。注意: forwarders forward only 是两回事。 forward only 会让 BIND 在上游不可用时直接返回 SERVFAIL ,而默认的 forward first 会在上游失败后自行迭代,更健壮。

/etc/bind/named.conf.local

// 定义内网域名解析区域
zone "internal" {
    type master;
    file "/var/lib/bind/internal.db";
    allow-update { none; }; // 禁用动态更新,所有变更走文件编辑 + rndc
};

// 定义反向解析区域(192.168.10.0/24 对应 10.168.192.in-addr.arpa)
zone "10.168.192.in-addr.arpa" {
    type master;
    file "/var/lib/bind/10.168.192.db";
    allow-update { none; };
};

提示: type master 表示这是权威区域的主服务器。 file 路径必须绝对,且文件名任意,但建议与 zone 名一致便于管理。 allow-update { none; } 是安全底线,除非你明确需要 nsupdate 工具,否则绝不开启。

4.2 zone 文件编写:internal.db 与反向解析库的语法精要与常见错误

zone 文件是 BIND 的心脏,语法严格遵循 DNS RFC。我们以 internal 域为例,创建 /var/lib/bind/internal.db

$TTL 300
@       IN      SOA     ns1.internal. admin.internal. (
                        2024052001 ; serial (YYYYMMDDNN)
                        3600       ; refresh (1h)
                        1800       ; retry (30m)
                        604800     ; expire (1w)
                        86400 )    ; minimum (1d)

; NS 记录,指定权威服务器
        IN      NS      ns1.internal.

; A 记录,正向解析
ns1     IN      A       192.168.10.10
gitlab  IN      A       192.168.10.5
printer IN      A       192.168.10.120
nas     IN      A       192.168.10.31

; CNAME 记录,别名(注意:CNAME 不能与其他记录共存)
www     IN      CNAME   gitlab.

; SRV 记录,服务定位(如 LDAP)
_ldap._tcp IN   SRV     0 100 389 gitlab.

语法要点与避坑指南

  • $TTL 300 :默认生存时间 300 秒(5 分钟)。客户端缓存此记录 5 分钟,之后重新查询。若 IP 频繁变更,可设为 60 ;若极少变动,可设 86400 (24 小时)减少查询压力。
  • SOA 记录: serial 是版本号, 必须每次修改 zone 文件后递增 。BIND 用它判断从服务器是否需要同步。推荐格式 YYYYMMDDNN (如 2024052001 表示 2024 年 5 月 20 日第 1 次修改)。若忘记改 serial, rndc reconfig 后从服务器不会更新。
  • NS 记录: ns1.internal. 末尾的点 . 表示绝对域名,不补全当前 zone。若写成 ns1.internal (无点),BIND 会自动补为 ns1.internal.internal. ,导致解析失败。
  • A 记录:主机名(如 gitlab )是相对域名,自动补全为 gitlab.internal. 。IP 地址必须是合法 IPv4 格式,不能有空格。
  • CNAME www 是别名,指向 gitlab. (注意末尾点)。 CNAME 记录所在行不能有其他记录 ,例如不能在同一行写 www IN CNAME gitlab. IN TXT "web server" ,会报语法错误。

反向解析文件 /var/lib/bind/10.168.192.db

$TTL 300
@       IN      SOA     ns1.internal. admin.internal. (
                        2024052001
                        3600
                        1800
                        604800
                        86400 )

        IN      NS      ns1.internal.

; PTR 记录:IP 最后一段(如 192.168.10.5 → 5)作为主机名
5       IN      PTR     gitlab.internal.
10      IN      PTR     ns1.internal.
120     IN      PTR     printer.internal.
31      IN      PTR     nas.internal.

关键逻辑 :反向 zone 名 10.168.192.in-addr.arpa 对应网段 192.168.10.0/24 ,因此 IP 192.168.10.X 的反向查询是 X.10.168.192.in-addr.arpa 。文件中 5 IN PTR ... 表示 5.10.168.192.in-addr.arpa 解析为 gitlab.internal.

实操心得:我曾因 PTR 记录写成 gitlab.internal (缺末尾点),导致 dig -x 192.168.10.5 返回 NXDOMAIN 。BIND 日志显示 error (no valid RRSIG) resolving '5.10.168.192.in-addr.arpa/PTR/IN' ,实际是域名未终结,而非 DNSSEC 问题。加点后立即修复。

4.3 服务加载与实时验证:从 rndc reconfig 到全链路解析测试

配置写完,不等于服务就通了。必须按标准流程加载:

# 1. 语法检查(最关键!跳过此步,90% 的启动失败源于此)
sudo named-checkconf /etc/bind/named.conf
sudo named-checkzone internal /var/lib/bind/internal.db
sudo named-checkzone 10.168.192.in-addr.arpa /var/lib/bind/10.168.192.db

# 2. 重载配置(不中断服务,平滑更新)
sudo rndc reconfig

# 3. 检查日志确认成功
sudo tail -f /var/log/syslog | grep named
# 正常应输出:
# named[1234]: zone internal/IN: loaded serial 2024052001
# named[1234]: zone 10.168.192.in-addr.arpa/IN: loaded serial 2024052001

全链路解析测试(按顺序执行,缺一不可)

  1. 本地环回测试 (验证 named 进程自身):

    dig @127.0.0.1 gitlab.internal A +short
    # 应返回 192.168.10.5
    dig @127.0.0.1 -x 192.168.10.5 +short
    # 应返回 gitlab.internal.
    
  2. 内网 IP 测试 (验证监听和防火墙):

    dig @192.168.10.10 printer.internal A +short
    # 应返回 192.168.10.120
    
  3. 客户端测试 (验证网络可达性): 在另一台 Ubuntu 机器上:

    # 临时修改 DNS(不改 resolv.conf,避免影响其他服务)
    echo "nameserver 192.168.10.10" | sudo tee /etc/resolv.conf
    # 测试
    nslookup gitlab.internal
    # 应显示 Server: 192.168.10.10,Address: 192.168.10.10#53,Name: gitlab.internal, Address: 192.168.10.5
    
  4. 公网域名穿透测试 (验证 forwarders 是否生效):

    dig @192.168.10.10 google.com A +short
    # 应返回 8.8.8.8 的 IP 列表(如 142.250.185.46),证明转发链路正常
    

注意:若 dig @192.168.10.10 google.com 超时,先检查 forwarders 是否可连: telnet 8.8.8.8 53 。若不通,可能是客户网络策略屏蔽了外网 DNS,此时应改用内网可访问的 DNS(如公司内部 DNS 服务器 IP)。

5. 常见问题与排查技巧实录:从 “rndc: connection refused” 到 “SERVFAIL”,一份实战排障手册

5.1 “rndc: connection refused” —— 控制通道失效的五大原因与修复

rndc 是 BIND 的远程控制接口,通过 Unix socket /var/run/bind9/rndc.sock 或 TCP 连接通信。报 connection refused 意味着控制通道完全中断。按发生概率排序:

原因 检查命令 修复方案
named 未运行 sudo systemctl status bind9 sudo systemctl start bind9
rndc.key 权限错误 ls -l /etc/bind/rndc.key 正确权限应为 -rw------- 1 root bind ,执行 sudo chown root:bind /etc/bind/rndc.key && sudo chmod 600 /etc/bind/rndc.key
named.conf.options 中未启用 controls grep -A 5 "controls" /etc/bind/named.conf.options Ubuntu 16.04 默认禁用 controls,需手动添加:
controls { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; }; };
rndc.key 与 named.conf 中 key 名不匹配 cat /etc/bind/rndc.key grep "key" /etc/bind/named.conf.options 确保 rndc.key 中的 key "rndc-key" named.conf keys { "rndc-key"; } 完全一致(包括引号)
AppArmor 阻止 socket 访问 sudo aa-status | grep named 查看 AppArmor 日志 sudo dmesg | grep "apparmor.*denied" ,若出现 denied "connect" , 则执行 sudo aa-disable /usr/sbin/named 临时禁用

实操心得:我遇到过最诡异的一次, rndc reconfig connection refused ,但 named 进程明明在跑。 strace -e trace=connect rndc reconfig 发现它试图连接 /var/run/bind9/rndc.sock ,而该 socket 文件不存在。原因是 named 启动时未创建 socket(因 directory 路径错误)。 sudo mkdir -p /var/run/bind9 && sudo chown bind:bind /var/run/bind9 后解决。

5.2 “SERVFAIL” 响应 —— 不是服务器挂了,而是配置链路上某个环节断了

SERVFAIL 是 DNS 协议中最难缠的错误,它表示服务器在处理查询时遇到内部错误,但不告诉你具体哪一步失败。常见场景及排查路径:

场景 1:zone 文件语法错误,但 named-checkzone 未捕获

  • 现象: dig @192.168.10.10 gitlab.internal 返回 status: SERVFAIL
  • 排查: sudo tail -100 /var/log/syslog \| grep "internal" ,查找 zone internal/IN: loading from master file /var/lib/bind/internal.db failed
  • 原因: named-checkzone 只校验基本语法,不校验 SOA 中的邮箱格式(如 admin.internal. 缺少 @ 符号会被忽略,但运行时解析失败)
  • 修复:将 admin.internal. 改为 admin\.internal. (转义点)或 admin@internal.

场景 2:反向 zone 名与网段不匹配

  • 现象: dig -x 192.168.10.5 返回 SERVFAIL ,但正向 gitlab.internal 正常
  • 排查: dig @127.0.0.1 5.10.168.192.in-addr.arpa PTR +short
  • 原因:反向 zone 名 10.168.192.in-addr.arpa 对应 `192.168.10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值