BIND
BIND (或 named) 是最广泛使用的域名系统 (DNS) 服务器。
安装
安装 bind 包。
启动/启用 named.service systemd 单元。
要在本地使用 DNS 服务器,请使用 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 服务器,请将 forwarders 子句添加到 options 部分。
例如,要让 BIND 通过 DNS over TLS 转发到 Google Public 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;
};
};
也可以通过定义一个转发区域来转发特定区域。如果您想解析内部域或在 Internet 上不可公开访问的域,这会很有用
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 中的 DNS over TLS 或 HTTPS 服务,请定义一个 tls 块来指定您的证书,然后添加 listen-on 子句来启用 DNS over TLS 和 HTTPS 侦听器(以及标准的 DNS 侦听器)。
/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 作为向全世界提供的域,就像本 wiki 的 archlinux.org 域一样。
一个更详尽的例子是 BIND9 的 DNS 服务器,而 本篇展示了 如何设置内部网络名称解析。
创建区域文件
创建 /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。否则,辅助服务器(副本或从服务器)将不会重新传输区域:只有当序列号*大于*上次传输区域时的序列号时,它们才会重新传输。此示例使用相对常见的 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 地址范围,但它不会自动包含所有私有网络范围(例如 192.168.0.0/24),除非您的接口被分配了该子网中的 IP。请参阅 “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 提交给父区域(例如,通过填写注册商的网页表单)。
当您确认 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 关键字通过 RFC 5011 机制在 KSK/算法轮换期间保持信任锚最新,而 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,这将允许强制 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 递归解析器来实现。
要管理递归解析器,您通常需要配置一个*根提示文件*。此文件包含根区域的权威名称服务器的名称和 IP 地址。
从 IANA 网站获取文件,并将其放入 /var/named。
编辑您的服务器配置,添加相应的文件
/etc/named.conf
zone "." IN {
type hint;
file "named.root";
};
在配置中也应该允许递归。请参阅 #允许递归。
参见
- BIND 9 管理员参考手册 (ARM)
- BIND ARM 在 readthedocs 上
- BIND 知识库
- Internet Systems Consortium, Inc. (ISC)
- Pro DNS and BIND 附带 在线摘要版
- DNS 术语表
- 关于 BIND 未来的邮件列表存档讨论
- 简化的根区域传输 - 在家运行根服务 复制
/etc/named.conf,重启 BIND 并尽情享用! - DNSSEC