BIND
BIND (或 named) 是使用最广泛的域名系统 (DNS) 服务器。
安装
启动/启用 named.service systemd 单元。
要本地使用 DNS 服务器,请将 nameserver 设置为 127.0.0.1(这意味着 Firefox 等客户端会通过 127.0.0.1 解析),请参阅 域名解析。但这需要你 #允许递归,同时防火墙可能会阻止外部查询连接到你的本地 named。
配置
BIND 的配置文件为 /etc/named.conf。可用选项记录在 named.conf(5) 中。
重载 named.service 单元以应用配置更改。
启用 rndc 访问
为了使用 rndc(8) 控制 BIND,你需要为其设置 TSIG 密钥,并告诉 BIND 允许使用该密钥进行名称服务器控制。
首先,为此目的生成 TSIG 密钥
$ tsig-keygen console
key "console" {
algorithm hmac-sha256;
secret "secret";
};
将输出内容复制到 /etc/named.conf 和 /etc/rndc.conf 中。
在 /etc/rndc.conf 中,附加默认名称服务器连接
/etc/rndc.conf
...
options {
default-key "console";
default-server 127.0.0.1;
default-port 953;
};
在 /etc/named.conf 中允许来自 localhost 的 rndc 控制
/etc/named.conf
...
controls {
inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "console"; };
};
...
现在你可以使用 rndc 来控制本地 DNS 服务器。例如,检查服务器状态
$ rndc status
重载服务器配置也可以通过以下方式完成
# rndc reload
限制访问到 localhost
默认情况下,BIND 会在所有接口和 IP 地址的 53 端口上进行监听。要仅允许来自 localhost 的连接,请在 /etc/named.conf 的 options 部分中添加以下行
listen-on { 127.0.0.1; };
listen-on-v6 { ::1; };
设置 DNS 转发
要使 BIND 将 DNS 查询转发到另一个 DNS 服务器,请在 options 部分中添加 forwarders 子句。
例如,要使 BIND 通过 DNS over TLS 将请求转发到 Google 公共 DNS 服务器
tls google {
remote-hostname "dns.google";
};
options {
...
forward only;
forwarders port 853 tls google {
8.8.8.8; 2001:4860:4860::8888;
8.8.4.4; 2001:4860:4860::8844;
};
};
特定的区域也可以通过定义 forward zone 来进行转发。如果你想解析内部域名或在互联网上无法公开访问的域名,这很有用。
zone domain.tld {
type forward;
forwarders {
10.20.30.40;
10.20.30.45;
};
forward only;
};
forward first。这样,当解析子区域查询时,BIND 将遵循委托(执行正常的递归),而不是返回 SERVFAIL。例如,当你托管内部 TLD 时,这是必需的。通过 TLS 或 HTTPS 提供 DNS 服务
要在 BIND 中启用通过 TLS 或 HTTPS 提供 DNS 服务,请定义一个 tls 块来指定你的证书,然后添加启用 DNS over TLS 和 HTTPS 监听器(以及标准 DNS 监听器)的 listen-on 子句。
/etc/named.conf
tls mycert {
cert-file "path.crt";
key-file "path.key";
};
options {
// Standard port 53 listeners need to be re-added explicitly
listen-on { any; };
listen-on-v6 { any; };
// Add a DNS over TLS listener on standard port 853
listen-on tls mycert { any; };
listen-on-v6 tls mycert { any; };
// Add a DNS over HTTPS listener on standard HTTPS port 443
listen-on tls mycert http default { any; };
listen-on-v6 tls mycert http default { any; };
// If needed, add a cleartext HTTP listener for a reverse proxy
//listen-on port 8443 tls none http default { 127.0.0.1; };
//listen-on-v6 port 8443 tls none http default { ::1; };
};
...
请注意,tls{} 定义在顶层,而不是在 options{} 块内部。
运行域名的配置模板
下面是一个简单的家庭名称服务器设置,使用 domain.tld 作为像本维基的 archlinux.org 域名那样全球解析的域名。
更详细的示例请参考 DNS server with BIND9,而 这里展示了 如何设置内部网络名称解析。
创建区域文件
创建 /var/named/domain.tld.zone。
$ORIGIN domain.tld.
$TTL 2h
@ SOA ns1 hostmaster (
2018111111 ; Serial
8h ; Refresh
30m ; Retry
1w ; Expire
1h ) ; Negative Cache TTL
NS ns1
NS ns2
@ A 203.0.113.1
AAAA 2001:db8:113::1
MX 10 mail
TXT "v=spf1 mx"
www A 203.0.113.1
AAAA 2001:db8:113::1
ns1 A 203.0.113.4
AAAA 2001:db8:113::4
ns2 A 198.51.100.5
AAAA 2001:db8:5100::5
mail A 198.51.100.6
AAAA 2001:db8:5100::6
imap CNAME mail
smtp CNAME mail
$ORIGIN 定义了所有不以 . (点) 结尾的名称的默认后缀,例如 mail 将在各处扩展为 mail.$ORIGIN ⇒ mail.domain.tld.。
$TTL 定义了所有未指定自己 TTL 的记录的默认生存时间(即缓存过期时间)。这里是 2 小时。
每次更改区域的资源记录后,在重载 named 之前,必须手动增加序列号 (Serial)。否则辅助服务器(副本或从服务器)将不会重新传输区域:只有当序列号大于它们上次传输该区域时的序列号时,它们才会执行此操作。此示例使用了较常见的 YYYYMMDDXX 格式,但这不是必需的;序列号也可以直接从 1 开始。
配置主服务器
将你的区域添加到 /etc/named.conf 中
zone "domain.tld" IN {
type primary;
file "domain.tld.zone";
allow-update { none; };
};
重载 named.service 单元以应用配置更改。
配置辅助服务器
如果你有两台或多台服务器,可以将除其中一台以外的所有服务器设置为辅助服务器,区域将通过 AXFR 传输从主服务器获取。
在主服务器上,显式允许来自辅助服务器的区域传输
zone "domain.tld" IN {
...
allow-transfer { 198.51.100.5; 20001:db8:113::4; };
};
在辅助服务器上,将区域添加到 /etc/named.conf 中
zone "domain.tld" IN {
type secondary;
file "domain.tld.zone";
primaries { 203.0.113.4; 2001:db8:113::4; };
};
重载 named.service 或使用 rndc(8) 来重载主服务器和辅助服务器的配置。
允许递归
如果你正在运行自己的 DNS 服务器,你可能希望它代表客户端执行递归查找(即解析它不是权威域名的域名)——无论是为了你自己的机器还是为了本地网络。这需要启用 BIND 中的递归,并仔细限制哪些客户端被允许使用它。
默认情况下,为了减轻 DNS 放大攻击,Arch 的默认 /etc/named.conf 中禁用了除环回接口之外的所有客户端的递归。这通常配置为
allow-recursion { 127.0.0.1; ::1; };
要允许来自 LAN 上客户端(例如 192.168.0.0/24)的递归查询,必须明确定义一个 ACL,并将其与 allow-recursion 和 allow-query-cache 一起使用。例如
/etc/named.conf
acl "trusted" {
127.0.0.1;
::1;
192.168.0.0/24;
fd01:2345:6789::/64;
};
options {
// Allow authoritative queries from any client
allow-query { any; };
// Allow recursive lookups and cached results only for trusted clients
allow-recursion { trusted; };
allow-query-cache { trusted; };
};
此设置允许
- 任何人获取权威响应(对于本服务器负责的区域)。
- 仅本地网络和环回接口上的受信任客户端执行递归查找和使用缓存结果。
allow-recursion 或 allow-query-cache,BIND 默认允许 localhost 和 localnets 进行递归。localnets ACL 包括启动时分配给服务器网络接口的 IP 范围,但除非你的接口被分配了该子网中的 IP,否则它不会自动包含所有私有网络范围(例如 192.168.0.0/24)。请参阅 "allow-recursion" 和 "allow-query-cache" 的行为发生了什么变化?
配置 BIND 以服务于 DNSSEC 签名区域
BIND 通过密钥和签名策略 (KASP) 功能,使得服务 DNSSEC 签名区域变得简单。它使用用户定义的策略自动为你处理区域签名和密钥管理。
创建单独的目录来存储密钥,并赋予服务器写权限
# mkdir /var/named/keys # chown named:named /var/named/keys
指示 BIND 将密钥存储在上述目录中
/etc/named.conf
options {
...
key-directory "/var/named/keys";
...
};
现在可以通过应用所需的策略来对区域进行签名。在大多数情况下,你可以使用 default 策略来应用最新的 DNSSEC 最佳实践
/etc/named.conf
zone "domain.tld" IN {
...
dnssec-policy default;
};
这将使用单一的 ecdsap256sha256 组合签名密钥 (CSK) 对区域进行签名,该密钥具有无限的生命周期,通过 inline-signing 进行签名,服务器在无需设置动态 DNS 的情况下单独生成已签名的区域。
如果需要,可以使用 dnssec-policy 块定义自定义策略。例如,main 策略使用传统的密钥签名密钥 (KSK,每年轮换) 和区域签名密钥 (ZSK,每月轮换) 分离的方式,并配合计时参数和 NSEC3 不存在证明来对区域进行签名
/etc/named.conf
dnssec-policy main {
keys {
ksk lifetime P1Y algorithm ecdsap256sha256;
zsk lifetime P1M algorithm ecdsap256sha256;
};
publish-safety 1h;
retire-safety 1h;
purge-keys 1h;
signatures-refresh P3D;
signatures-validity P3W;
signatures-validity-dnskey P3W;
inline-signing yes;
nsec3param iterations 0 optout no salt-length 0;
};
...
自定义策略可以像之前应用默认策略一样应用
/etc/named.conf
zone "domain.tld" IN {
...
dnssec-policy main;
};
增加区域的序列号并重载服务器配置。
最后一步是与父区域建立信任链。首先,检查区域的 DNSSEC 状态
$ rndc dnssec -status domain.tld dnssec-policy: main current time: Tue Mar 25 08:51:53 2025 key: 58785 (ECDSAP256SHA256), KSK published: yes - since Tue Mar 25 08:47:23 2025 key signing: yes - since Tue Mar 25 08:47:23 2025 Next rollover scheduled on Wed Mar 25 06:42:23 2026 - goal: omnipresent - dnskey: rumoured - ds: hidden - key rrsig: rumoured key: 5017 (ECDSAP256SHA256), ZSK published: yes - since Tue Mar 25 08:47:23 2025 zone signing: yes - since Tue Mar 25 08:47:23 2025 Next rollover scheduled on Fri Apr 25 06:42:23 2025 - goal: omnipresent - dnskey: rumoured - zone rrsig: rumoured
此处,KSK 密钥 ID 为 58785。你的将会不同。
生成 DS 记录(根据需要替换密钥 ID)
$ dnssec-dsfromkey -2 /var/named/keys/Kdomain.tld.+013+58785 domain.tld. IN DS 58785 13 2 hash
提交 DS 给父区域(例如,通过填写注册商处的 Web 表单)。
当你确认 DS 记录已发布在父区域中时,你可以通过以下方式通知 BIND
$ rndc dnssec -checkds -key 58785 published domain.tld
自定义信任锚
如果你的 DNSSEC 签名区域是内部的,并且你需要利用 DNSSEC 验证,则需要将该区域的信任锚添加到用于解析它的解析器中。这可以通过添加 trust-anchors 块来完成
/etc/named.conf
trust-anchors {
. initial-key 257 3 8 "AwEAAa96jeuknZlaeSrvyAJj6ZHv28hhOKkx3rLGXVaC6rXTsDc449/cidltpkyGwCJNnOAlFNKF2jBosZBU5eeHspaQWOmOElZsjICMQMC3aeHbGiShvZsx4wMYSjH8e7Vrhbu6irwCzVBApESjbUdpWWmEnhathWu1jo+siFUiRAAxm9qyJNg/wOZqqzL/dL/q8PkcRU5oUKEpUge71M3ej2/7CPqpdVwuMoTvoB+ZOT4YeGyxMvHmbrxlFzGOHOijtzN+u1TQNatX2XBuzZNQ1K+s2CXkPIZo7s6JgZyvaBevYtxPvYLw4z9mR7K2vaF18UYH9Z9GNUUeayffKC73PYc=";
. initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU=";
domain.tld. initial-ds 58785 13 2 "hash";
};
initial-key 或 initial-ds 关键字会在 KSK/算法轮换期间使用 RFC 5011 机制保持信任锚为最新,而 static-key 或 static-ds 则不会,需要手动更新锚点。/etc/named.conf 中指定 dnssec-validation yes 而不是默认的 dnssec-validation auto 时,这是必需的。自动监听新接口
默认情况下,BIND 每小时扫描新接口并停止监听不再存在的接口。你可以通过添加以下内容来调整此值
/etc/named.conf
options {
interface-interval rescan-timeout-in-minutes;
};
最大值为 28 天 (40320 分钟)。你可以通过将其值设置为 0 来禁用此功能。
然后 重启 该服务。
在 chroot 环境中运行 BIND
在 chroot 环境中运行不是必需的,但可以提高安全性。
创建 jail 环境
为了做到这一点,我们首先需要创建一个放置 jail 的地方,我们将使用 /srv/named,然后将所需文件放入 jail 中。
# mkdir -p /srv/named/{dev,etc,usr/lib/engines,var/{run,log,named}}
复制所需的系统文件
# cp -av /etc/{localtime,named.conf} /srv/named/etc/
# cp -av /usr/lib/engines-1.1/* /srv/named/usr/lib/engines/
# cp -av /var/named/* /srv/named/var/named/.
在 /dev/ 中设置所需的节点
# mknod /srv/named/dev/null c 1 3 # mknod /srv/named/dev/random c 1 8
设置文件的 所有权
# chown -R named:named /srv/named
这应该为 jail 创建了所需的文件系统。
服务单元
接下来我们需要一个 替换单元文件,以便服务调用 bind,这将允许强制绑定到 chroot 中
/etc/systemd/system/named-chroot.service
ExecStart=/usr/bin/named -4 -f -u named -t "/srv/named"
现在,使用 daemon-reload 重载 systemd,并 启动 named-chroot.service。
本地服务于根区域
如果你不想依赖 第三方 DNS 服务,你可以按照 RFC:7706 在本地服务于根区域。这可以通过使用 BIND 作为 DNS 递归解析器来实现。
要管理递归解析器,通常需要配置一个 根提示文件 (root hints file)。该文件包含根区域权威名称服务器的名称和 IP 地址。
从 IANA 网站 获取该文件并将其放入 /var/named。
编辑你的服务器配置,添加相应的文件
/etc/named.conf
zone "." IN {
type hint;
file "named.root";
};
配置中也应允许递归。请参阅 #允许递归。