Ubuntu 22.04 安装 BIND9 指南

Ubuntu 22.04 下 apt 安装 BIND9(named)与 systemd 托管的完整实测指南:/etc/bind 结构、最小正反向 zone 配置、named-checkconf/named-checkzone 校验、dig 本机验证、AppArmor 约定与卸载清理(实测版本 9.18.39-0ubuntu0.22.04.7,上游最新稳定版 9.20.29)。

BIND92026/10/20

Ubuntu 22.04 安装 BIND9 指南

目标:在 Ubuntu 22.04 上以 apt 安装 ISC BIND9(named 守护进程 + systemd 托管),完成 /etc/bind 结构认识、最小正反向 zone 配置、配置校验、systemctl 启停与 dig 本机验证,最后给出卸载清理流程。全部命令与回显来自 Ubuntu 22.04.4 LTS / x86_64 真机实测(2026-10-20)。

一、环境信息

项目实测值
操作系统Ubuntu 22.04.4 LTS(jammy),内核 6.8.0-138-generic,x86_64
安装方式apt 官方仓库(jammy-security / jammy-updates main 源)
实测安装版本bind9 1:9.18.39-0ubuntu0.22.04.7(apt-cache policy bind9 候选版本,2026-10-20 实查)
上游最新稳定版BIND 9.20.29(ISC 官网版本表标注 Current Stable/ESV,2026-09 发布,支持至 2028-Q2;2026-10-20 实查 isc.org/bind)
版本差异说明jammy 仓库的 9.18 属于 ISC 已 EOL 的 ESV 线(2026-06 终止),由 Ubuntu 安全团队继续打补丁;需要 9.20 线可改用 ISC 官方 PPA(launchpad.net/~isc)或源码编译,本文主线按发行版仓库实测
依赖工具bind9-dnsutils(dig/nslookup)、bind9-utils(named-checkzone 等随装)
服务形态named.service(systemd),AppArmor 配置 /etc/apparmor.d/usr.sbin.named

二、前置条件

  1. 端口 53/UDP+TCP 与 953/TCP 可用:named 监听 53(DNS)与 953(rndc 控制通道)。
  2. systemd-resolved 存根冲突认知:Ubuntu 22.04 默认 systemd-resolved 在 127.0.0.53:53 运行本地存根。实测在本机(named 默认配置)两者可共存启动成功(named 以多 socket 方式绑定本机其他地址);若启动报 address already in use,可让 named 显式 listen-on 非冲突地址,或在 resolved 中关闭 DNSStubListener(见第九节 FAQ)。
  3. 掌握软件源状态:安装前确认候选版本(实测回显):
# apt-cache policy bind9
bind9:
  已安装:(无)
  候选: 1:9.18.39-0ubuntu0.22.04.7
  版本列表:
     1:9.18.39-0ubuntu0.22.04.7 500
        500 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages
     1:9.18.39-0ubuntu0.22.04.6 500
        500 http://cn.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
     1:9.18.1-1ubuntu1 500
        500 http://cn.archive.ubuntu.com/ubuntu jammy/main amd64 Packages

三、apt 安装 bind9

# apt-get install -y bind9 bind9-utils
(正在读取数据库 ... 系统当前共安装有 225921 个文件和目录。)
准备解压 .../bind9-host_1%3a9.18.39-0ubuntu0.22.04.7_amd64.deb  ...
正在解压 bind9-host (1:9.18.39-0ubuntu0.22.04.7) 并覆盖 (1:9.18.39-0ubuntu0.22.04.6) ...
准备解压 .../bind9-dnsutils_1%3a9.18.39-0ubuntu0.22.04.7_amd64.deb  ...
正在解压 bind9-dnsutils (1:9.18.39-0ubuntu0.22.04.7) 并覆盖 (1:9.18.39-0ubuntu0.22.04.6) ...
准备解压 .../bind9-libs_1%3a9.18.39-0ubuntu0.22.04.7_amd64.deb  ...
正在解压 bind9-libs (1:9.18.39-0ubuntu0.22.04.7) 并覆盖 (1:9.18.39-0ubuntu0.22.04.6) ...
正在选中未选择的软件包 bind9-utils。
正在解压 bind9-utils (1:9.18.39-0ubuntu0.22.04.7) ...
正在选中未选择的软件包 bind9。
正在解压 bind9 (1:9.18.39-0ubuntu0.22.04.7) ...
正在设置 bind9-libs:amd64 (1:9.18.39-0ubuntu0.22.04.7) ...
正在设置 bind9-utils (1:9.18.39-0ubuntu0.22.04.7) ...
正在设置 bind9 (1:9.18.39-0ubuntu0.22.04.7) ...
Adding group `bind' (GID 143) ...
Done.
Adding system user `bind' (UID 137) ...
Adding new user `bind' (UID 137) with group `bind' ...
Not creating home directory `/var/cache/bind'.
wrote key file "/etc/bind/rndc.key"
named-resolvconf.service is a disabled or a static unit, not starting it.
Created symlink /etc/systemd/system/bind9.service → /lib/systemd/system/named.service.
Created symlink /etc/systemd/system/multi-user.target.wants/named.service → /lib/systemd/system/named.service.
正在处理用于 ufw (0.36.1-4ubuntu0.1) 的触发器 ...
正在处理用于 man-db (2.10.2-1) 的触发器 ...
正在处理用于 libc-bin (2.35-0ubuntu3.15) 的触发器 ...

三个要点:

  • 安装自动创建系统用户/组 bind,named 以该用户运行(-u bind)。
  • 自动生成 rndc 控制通道密钥 /etc/bind/rndc.key 并注册开机自启(multi-user.target.wants/named.service)。
  • 实测中装前已存在的 bind9-host/bind9-dnsutils/bind9-libs(9.18.39-0ubuntu0.22.04.6)被连带升级到 .7 同版本,属正常依赖收敛。

四、/etc/bind 目录结构

安装后的默认文件清单(ls -la /etc/bind/ 实测):

total 64
drwxr-sr-x   2 root bind   4096 /etc/bind/
-rw-r--r--   1 root root   2928 bind.keys                  # DNSSEC 根信任锚(managed-keys 备用)
-rw-r--r--   1 root root    237 db.0                        # 0.in-addr.arpa 空区
-rw-r--r--   1 root root    271 db.127                      # 127.in-addr.arpa 回环反解
-rw-r--r--   1 root root    237 db.255                      # 255.in-addr.arpa 广播区
-rw-r--r--   1 root root    353 db.empty                    # RFC1918 空模板
-rw-r--r--   1 root root    270 db.local                    # localhost 正解
-rw-r--r--   1 root bind    463 named.conf                  # 主配置:include 三个片段
-rw-r--r--   1 root bind    498 named.conf.default-zones    # 根提示与 localhost 系列默认区
-rw-r--r--   1 root bind    165 named.conf.local            # 本机 zone 定义(运维主要编辑点)
-rw-r--r--   1 root bind    846 named.conf.options          # 全局 options(运维主要编辑点)
-rw-r--r--   1 root bind    100 rndc.key                    # rndc 控制通道 TSIG 密钥(安装时生成)
-rw-r--r--   1 root root   1317 zones.rfc1918                # RFC1918 反解空区片段

主配置 named.conf 仅做 include 组织(实测原文):

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

系统目录分工(/usr/share/doc/bind9/README.Debian.gz 与 AppArmor 配置约定):

目录用途
/etc/bind静态配置与 zone 文件(AppArmor 规则 /etc/bind/** r,对 named 只读)
/var/lib/bind动态更新 zone 与 journal 文件(AppArmor 规则 /var/lib/bind/** rw)
/var/cache/bind缓存、从区传送数据与 dump/stats 产物

五、最小正反向 zone 配置

以测试域 lab.example(正解网段 192.168.88.0/24 反解)为例。

5.1 正解 zone 文件 /etc/bind/db.lab.example

$TTL    604800
@       IN      SOA     ns1.lab.example. admin.lab.example. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns1.lab.example.
ns1     IN      A       192.168.88.10
www     IN      A       192.168.88.20
api     IN      CNAME   www

5.2 反解 zone 文件 /etc/bind/db.192.168.88

$TTL    604800
@       IN      SOA     ns1.lab.example. admin.lab.example. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns1.lab.example.
10      IN      PTR     ns1.lab.example.
20      IN      PTR     www.lab.example.

5.3 在 named.conf.local 声明两个 zone

zone "lab.example" {
    type master;
    file "/etc/bind/db.lab.example";
};

zone "88.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/db.192.168.88";
};

💡 若 zone 需要接收动态更新(DDNS),zone 文件应放到 /var/lib/bind/ 并把 file 指向那里——/etc/bind 对 named 只读(AppArmor),实测把动态区留在 /etc/bind 时 named 报 /etc/bind/db.lab.example.jnl: create: permission denied,详见 《BIND9 9.18.39 配置参数详解》。

六、配置校验

6.1 named-checkconf 校验主配置

# named-checkconf
(无输出且返回 0 即通过)

语法错误时的实测报错形态(人为去掉一个分号):

/tmp/badcheck.conf:9: missing ';' before 'allow-recursion'

-p 可展开 include 打印生效配置(实测节选):

# named-checkconf -p | head -12
options {
        directory "/var/cache/bind";
        listen-on port 53 {
                127.0.0.1/32;
        };
        listen-on-v6  {
                "none";
        };
        allow-recursion {
                127.0.0.0/8;
        };
        dnssec-validation no;

6.2 named-checkzone 校验 zone 文件

# named-checkzone lab.example /etc/bind/db.lab.example
zone lab.example/IN: loaded serial 2
OK
# named-checkzone 88.168.192.in-addr.arpa /etc/bind/db.192.168.88
zone 88.168.192.in-addr.arpa/IN: loaded serial 2
OK

文件缺失时的报错形态:

# named-checkzone lab.example /etc/bind/db.notexist
zone lab.example/IN: loading from master file /etc/bind/db.notexist failed: file not found
zone lab.example/IN: not loaded due to errors.

七、systemd 启停管理

7.1 启动与状态

# systemctl start named
# systemctl is-active named
active
# systemctl status named --no-pager
● named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2026-10-20 16:01:59 CST
       Docs: man:named(8)
    Process: 1381745 ExecStart=/usr/sbin/named $OPTIONS (code=exited, status=0/SUCCESS)
   Main PID: 1381746 (named)
      Tasks: 26 (limit: 38359)
     Memory: 25.6M
        CPU: 29ms
     CGroup: /system.slice/named.service
             └─1381746 /usr/sbin/named -u bind

进程核对(防止脚本自匹配误报的规范写法):

# pgrep -x named -a
1372912 /usr/sbin/named -u bind
# systemctl show named -p MainPID
MainPID=1372912

首启 journal 关键行(journalctl -u named 实测节选):

ops systemd[1]: Started BIND Domain Name Server.
ops named[1372912]: managed-keys-zone: Initializing automatic trust anchor management for zone '.'; DNSKEY ID 20326 is now trusted, waiving the normal 30-day waiting period.
ops named[1372912]: managed-keys-zone: Initializing automatic trust anchor management for zone '.'; DNSKEY ID 38696 is now trusted, waiving the normal 30-day waiting period.
ops named[1372912]: network unreachable resolving './NS/IN': 2001:500:2f::f#53

💡 IPv6 根服务器 network unreachable 提示说明本机无 IPv6 出口,递归会自动回退 IPv4,不影响功能;介意刷屏可设 listen-on-v6 { none; };。

7.2 重启 / 停止 / 自启

# systemctl restart named
# systemctl stop named
# systemctl is-enabled named
enabled

停止时的 journal 行为(实测节选):

ops systemd[1]: Stopping BIND Domain Name Server...
ops named[1372912]: received control channel command 'stop'
ops named[1372912]: no longer listening on 127.0.0.1#53
ops named[1372912]: stopping command channel on 127.0.0.1#953
ops systemd[1]: named.service: Deactivated successfully.

八、dig 本机验证

8.1 默认 zone 基线

# dig @127.0.0.1 localhost
; <<>> DiG 9.18.39-0ubuntu0.22.04.7-Ubuntu <<>> @127.0.0.1 localhost
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27977
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

flags: qr aa rd ra 中的 aa 表明命中本机权威区(localhost)。

8.2 正解 / 别名 / 反解 / NS

# dig @127.0.0.1 www.lab.example +noall +answer
www.lab.example.        604800  IN      A       192.168.88.20

# dig @127.0.0.1 api.lab.example +noall +answer
api.lab.example.        604800  IN      CNAME   www.lab.example.
www.lab.example.        604800  IN      A       192.168.88.20

# dig @127.0.0.1 -x 192.168.88.20 +noall +answer
20.88.168.192.in-addr.arpa. 604800 IN   PTR     www.lab.example.

# dig @127.0.0.1 lab.example NS +noall +answer
lab.example.            604800  IN      NS      ns1.lab.example.

四条全绿即代表「named 运行、正反解 zone 已加载、CNAME 展开正常」。改配置后的复核流程固定为:named-checkconf → rndc reload → dig(参数级实操见 《BIND9 9.18.39 配置参数详解》)。

九、注意事项与 FAQ

  • 和 systemd-resolved 共存:两者都用 53 端口但地址不同(127.0.0.53 存根 vs named 的接口地址),实测可直接共存;若 named 启动日志报 binding TCP socket: address in use,把 options 里 listen-on 收敛到具体地址即可。
  • 公网机器必收敛:默认配置监听所有接口且递归开放,listen-on + allow-query + allow-recursion 三件套是上线的第一件事。
  • 动态更新文件放 /var/lib/bind:受 AppArmor 约束(详见第五节提示)。
  • 转发上游要配套 DNSSEC 策略:dnssec-validation auto(默认)+ 不回 DNSSEC 记录的转发器 = SERVFAIL(broken trust chain),实测复现与解法见 《BIND9 9.18.39 配置参数详解》。
  • 版本双口径:本篇实测 9.18.39-0ubuntu0.22.04.7 为 jammy 仓库线;上游当前稳定版 9.20.29(isc.org/bind 2026-10-20 实查),差异口径详见 《BIND9 9.20.29 介绍与选型指南》。

十、卸载与清理

# systemctl stop named
# apt-get purge -y bind9 bind9-utils
# apt-get autoremove -y
# rm -rf /etc/bind /var/lib/bind/db.*.jnl

purge 会连同配置目录 /etc/bind 一起删除;autoremove 清理仅为满足依赖而装入的包。若装前已存在 bind9-dnsutils 等客户端工具,它们不会被 purge(是独立包),保留即可。验证清理是否干净:dpkg -l | grep bind9 应只剩装前既有包,ss -lunp | grep :53 无 named 监听。实测回执(2026-10-20):purge 输出含 正在清除 bind9 (1:9.18.39-0ubuntu0.22.04.7) 的配置文件 ...;purge 后 /etc/bind 若因自建 zone 文件而非空(dpkg 提示 目录 /etc/bind 非空,因而不会删除该目录),需手工 rm -rf /etc/bind 并清理 /var/cache/bind、/var/lib/bind 下的自建文件;随后 systemctl status named 返回 Unit named.service could not be found。

十一、参考链接