域名解析
通常,域名代表一个 IP 地址,并在域名系统 (DNS) 中与之关联。本文解释了如何配置域名解析和解析域名。
名称服务切换
名称服务切换 (NSS) 工具是 GNU C 库 (glibc) 的一部分,并支持 getaddrinfo(3) API,用于解析域名。NSS 允许系统数据库由单独的服务提供,管理员可以在 nsswitch.conf(5) 中配置其搜索顺序。负责域名解析的数据库是 hosts 数据库,glibc 为其提供以下服务
- files: 读取
/etc/hosts
文件,参见 hosts(5) - dns: glibc 解析器,读取
/etc/resolv.conf
,参见 resolv.conf(5)
systemd 提供了三个用于主机名解析的 NSS 服务
- nss-resolve(8) — 缓存 DNS 桩解析器,在 systemd-resolved 中描述
- nss-myhostname(8) — 提供本地主机名解析,无需编辑
/etc/hosts
- nss-mymachines(8) — 为本地 systemd-machined(8) 容器的名称提供主机名解析
使用 NSS 解析域名
NSS 数据库可以使用 getent(1) 查询。可以使用 NSS 解析域名,方法是
$ getent ahosts domain_name
/etc/resolv.conf
和/或 /etc/hosts
。参见 Network configuration#localhost is resolved over the network。Glibc 解析器
glibc 解析器在每次解析时都会读取 /etc/resolv.conf
,以确定要使用的名称服务器和选项。
resolv.conf(5) 列出了名称服务器以及一些配置选项。首先尝试列在最前面的名称服务器,最多可以列出三个名称服务器。以数字符号 (#
) 开头的行将被忽略。
覆盖 /etc/resolv.conf
网络管理器 倾向于覆盖 /etc/resolv.conf
,具体信息请参见相应章节
- dhcpcd#/etc/resolv.conf
- Netctl#/etc/resolv.conf
- NetworkManager#/etc/resolv.conf
- ConnMan#/etc/resolv.conf
为了防止程序覆盖 /etc/resolv.conf
,也可以通过设置不可变的 文件属性 来写保护它
# chattr +i /etc/resolv.conf
/etc/resolv.conf
,可以使用 resolvconf。使用 nmcli 的替代方案
如果您使用 NetworkManager,可以使用 nmcli(1) 为 /etc/resolv.conf
设置持久选项。将 "Wired" 更改为您的连接名称。示例
# nmcli con mod Wired +ipv4.dns-options 'rotate,single-request,timeout:1'
有关更多选项,请参阅 nmcli(1)、nm-settings-nmcli(5) 和 resolv.conf(5) 的手册页。
限制查找时间
如果您遇到非常长的主机名查找时间(可能在 pacman 中或浏览时),通常有助于定义一个小的超时时间,之后将使用备用名称服务器。为此,请将以下内容放入 /etc/resolv.conf
中。
/etc/resolv.conf
options timeout:1
IPv6 导致主机名查找延迟
如果您在解析主机名时遇到 5 秒延迟,可能是由于 DNS 服务器/防火墙行为不当,并且只对并行 A 和 AAAA 请求给出一次回复。[1] 您可以通过在 /etc/resolv.conf
中设置以下选项来解决此问题
/etc/resolv.conf
options single-request
本地域名
为了能够使用本地机器名称的主机名而无需完全限定域名,请在 /etc/resolv.conf
中添加一行,其中包含本地域名,例如
/etc/resolv.conf
search example.org
这样,当使用 ssh 命令时,您可以将本地主机(例如 mainmachine1.example.org
)简称为 mainmachine1
,但是 drill 命令仍然需要完全限定域名才能执行查找。
查找工具
要查询特定的 DNS 服务器和 DNS/DNSSEC 记录,您可以使用专用的 DNS 查找工具。这些工具自己实现 DNS,而不使用 NSS。
ldns 提供了 drill(1),它是一个旨在从 DNS 中检索信息的工具。
例如,要使用 drill 查询特定名称服务器的域的 TXT 记录
$ drill @nameserver TXT domain
除非指定了 DNS 服务器,否则 drill 将使用 /etc/resolv.conf
中定义的名称服务器。
- knot 提供了 khost(1) 和 kdig(1)。
- Unbound 具有 unbound-host(1)。
- BIND 具有 dig(1)、host(1)、nslookup(1) 和一堆
dnssec-
工具。 - systemd-resolved 具有 resolvectl(1),它为 DNS 查找提供了一个
query
子命令。
解析器性能
Glibc 解析器不缓存查询。要实现本地缓存,请使用 systemd-resolved 或设置本地缓存 DNS 服务器,并通过在 /etc/resolv.conf
或 /etc/resolvconf.conf
(如果使用 openresolv)中将 127.0.0.1 和 ::1 设置为名称服务器,将其用作名称服务器。
隐私与安全
DNS 协议是未加密的,并且不考虑机密性、完整性或身份验证,因此,如果您使用不受信任的网络或恶意 ISP,您的 DNS 查询可能会被窃听,响应可能会被 篡改。此外,DNS 服务器可能会进行 DNS 劫持。
您需要信任您的 DNS 服务器以对您的查询进行保密处理。DNS 服务器由 ISP 和 第三方 提供。或者,您可以运行自己的 递归名称服务器,但这需要更多的工作。如果您在不受信任的网络中使用 DHCP 客户端,请务必设置静态名称服务器,以避免使用并受到任意 DNS 服务器的影响。为了保护您与远程 DNS 服务器的通信安全,您可以使用加密协议,例如 DNS over TLS (RFC 7858)、DNS over HTTPS (RFC 8484) 或 DNSCrypt,前提是上游服务器和您的 解析器 都支持该协议。另一种替代方案是使用专用软件来加密和解密通信,例如 stunnel。要验证响应是否确实来自 权威名称服务器,您可以验证 DNSSEC,前提是上游服务器和您的 解析器 都支持它。
即使使用加密的 DNS 解析器,浏览器在请求网站证书时仍然会在服务器名称指示 (Server Name Indication) 中泄露域名。可以使用 Wireshark 过滤器 tls.handshake.extensions_server_name_len > 0
或下面的命令行来检查此泄露。一个提议的解决方案是使用加密客户端问候 (Encrypted Client Hello, ECH),这是一种 TLS 1.3 协议扩展。
# tshark -p -Tfields -e tls.handshake.extensions_server_name -Y 'tls.handshake.extensions_server_name_len>0'
应用层 DNS
请注意,一些客户端软件,例如主要的网络浏览器[2][3],正在开始实现 DNS over HTTPS。虽然查询加密通常被视为一项额外的好处,但这也意味着该软件绕过了系统解析器配置来处理查询。[4]
Firefox 提供了配置选项来启用或禁用 DNS over HTTPS 并选择 DNS 服务器。Mozilla 设立了一个可信递归解析器 (Trusted Recursive Resolver, TRR) 计划,其中包含关于其默认提供商的透明度信息。值得注意的是,Firefox 支持并为 TRR 提供商自动启用加密客户端问候 (ECH),请参阅 Firefox/Privacy#Encrypted Client Hello。
Chromium 将检查用户的系统解析器,如果已知系统解析器地址也提供 DNS over HTTPS,则会启用 DNS over HTTPS。请参阅这篇博文了解更多信息以及如何禁用 DNS over HTTPS。
Mozilla 已提议,如果系统解析器无法解析域名 use-application-dns.net
,则普遍禁用应用层 DNS。目前,这仅在 Firefox 中实现。
盲 DNS
盲 DNS (RFC:9230) 是一个解决许多 DNS 隐私问题的系统。请参阅 Cloudflare 的文章了解更多信息。
第三方 DNS 服务
有各种可用的第三方 DNS 服务,其中一些还具有专用软件
- cloudflared — 用于 Cloudflare DNS over HTTPS 的 DNS 客户端
- opennic-up — 自动续订具有最响应速度的 OpenNIC 服务器的 DNS 服务器
- nextdns — 用于 NextDNS 的 DNS-over-HTTPS 命令行客户端
您可以使用 dnsperftest 来测试您所在位置最流行的 DNS 解析器的性能。dnsperf.com 提供了提供商之间的全球基准。
DNS 服务器
DNS 服务器可以是权威的 (authoritative) 和递归的 (recursive)。如果两者都不是,则称为存根解析器 (stub resolver),它们只是将所有查询转发到另一个递归名称服务器。存根解析器通常用于在本地主机或网络上引入 DNS 缓存。请注意,使用功能齐全的名称服务器也可以实现相同的目的。本节比较了可用的 DNS 服务器,更详细的比较请参阅 Wikipedia:Comparison of DNS server software。
名称 | 软件包 | 功能 | resolvconf | 支持的协议 | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
权威 | 递归 | 缓存 | 验证 DNSSEC |
DNS | DNSCrypt | DNS 基于 TLS |
DNS 基于 HTTPS |
DNS 基于 QUIC | |||
BIND | bind | 是 | 是 | 是 | 是 | 是 | 是 | 否 | 服务器1 | 服务器 | 否 |
CoreDNS | corednsAUR | 是 | 否 | 是 | 否 | 否 | 是 | 否 | 是 | 是 | 否 |
DNS-over-HTTPS | dns-over-https | 否 | 否 | 否 | 否 | ? | ? | 否 | 否 | 是 | 否 |
Deadwood (MaraDNS 递归器) | maradnsAUR | 否 | 是 | 是 | 否 | 否 | 是 | 否 | 否 | 否 | 否 |
dnscrypt-proxy | dnscrypt-proxy | 否 | 否 | 是 | 否 | 否 | 服务器 | 解析器 | 否 | 是 | ? |
dnsmasq | dnsmasq | 部分2 | 否 | 是 | 是 | 是 | 是 | 否 | 否 | 否 | 否 |
dnsproxy | dnsproxyAUR | 否 | 否 | 是 | 否 | 否 | 是 | 是 | 是 | 是 | 是 |
Knot Resolver | knot-resolver | 否 | 是 | 是 | 是 | 否 | 是 | 否 | 是 | 服务器 | 否 |
pdnsd | pdnsd | 部分2 | 是 | 永久 | 否 | 是 | 是 | 否 | 否 | 否 | 否 |
PowerDNS Recursor | powerdns-recursor | 否 | 是 | 是 | 是 | 是 | 是 | 否 | 部分 | 否 | ? |
Rescached | rescached-gitAUR | 否 | 否 | 是 | 否 | 是 | 是 | 否 | 是 | 是 | 否 |
RouteDNS | routedns-gitAUR | 否 | 否 | 是3 | 否 | 否 | 是 | 否 | 是 | 是 | 是 |
SmartDNS | smartdns | 否 | 否 | 是 | 否 | ? | 是 | 否 | 解析器 | 解析器 | 否 |
Stubby | stubby | 否 | 否 | 否 | 是 | 否 | 服务器 | 否 | 解析器 | 否 | 否 |
systemd-resolved | systemd | 否 | 否 | 是 | 是 | 是 | 解析器和有限的服务器 | 否 | 解析器 | 否 | 否 |
Unbound | unbound | 部分 | 是 | 是3 | 是 | 是 | 是 | 服务器 | 是 | 服务器 | 否 |
- BIND 可以同时提供 DNS over TLS 和 DNS over HTTPS 服务(参见 tls{} 和 listen-on),但尚无法将查询转发到 DNS over TLS/DNS over HTTPS 上游。dig 工具可以通过 DNS over TLS 和 DNS over HTTPS 发出查询(使用
+tls
和+https
选项),但没有任何证书检查。 - 来自 Wikipedia:有限的权威支持,旨在用于内部网络而非公共互联网。
- 支持使用 Redis 后端的持久缓存。
仅权威服务器
名称 | 软件包 | DNSSEC | 地理 负载均衡 |
---|---|---|---|
gdnsd | gdnsd | 否 | 是 |
Knot DNS | knot | 是 | 是 |
MaraDNS | maradnsAUR | 否 | ? |
NSD | nsd | 是 | 否 |
PowerDNS | powerdns | 是 | 是 |
条件转发
可以在查询特定域名时使用特定的 DNS 解析器。这在连接到 VPN 时特别有用,这样对 VPN 网络的查询将由 VPN 的 DNS 解析,而对互联网的查询仍将由您的标准 DNS 解析器解析。它也可以在本地网络中使用。
要实现它,您需要使用本地解析器,因为 glibc 不支持它。
在动态环境(笔记本电脑和一定程度上的台式机)中,您需要根据您连接的网络配置解析器。最好的方法是使用 openresolv,因为它支持多个订阅者。一些网络管理器支持它,可以通过 openresolv,也可以直接配置解析器。NetworkManager 支持在没有 openresolv 的情况下进行条件转发。