SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

DNS 是什么?域名为何无法访问 VPS

DNS 决定域名能否到达您的 VPS。了解 A、NS 记录、权威名称服务器、TTL 与缓存,定位修改后仍返回旧结果的原因。

什么是 DNS,以及您的域名为什么还无法访问 VPS

DNS(域名系统)会将类似 example.com 的名称转换为类似 203.0.113.10 的 IP(互联网协议)地址。浏览器无法直接连接名称,而是连接地址。因此,每次加载页面时,都会先发起 DNS 查询并获取响应。如果您刚购买了一个域名和自己的 VPS,但页面无法加载,通常有两种原因:尚未创建将域名指向服务器地址的记录;或者记录已经存在,但链路中的某个环节仍在返回较旧的结果。

这两种情况都很常见,也不表示系统出现故障。下面将按您实际遇到的顺序介绍相关内容,先从最容易浪费时间的问题开始:您的 DNS 记录究竟由哪个控制面板管理。

本节中的所有检查都使用 dig。在全新安装的 Ubuntu 或 Debian 系统上,默认不会安装该工具。

sudo apt update && sudo apt install -y bind9-dnsutils

注册商、权威名称服务器和 DNS 托管商:应该在哪里修改

这三个名称代表不同的职责。混淆它们,是修改后没有任何变化的最常见原因。

  • 注册商是您购买域名的公司。它的关键职责是委派:告诉负责管理您的 TLD(顶级域名,即 .com 部分)的注册局,哪些名称服务器对您的域名具有权威性。
  • 权威名称服务器保存您区域的实际记录。区域就是您的域名及其下的名称。
  • DNS 托管商负责运营这些名称服务器。它可以是注册商、独立的服务提供商,也可以是运行在您自有服务器上的 bind9

您在注册商处购买域名,在 DNS 托管商处修改记录。如果您已将域名迁移到其他服务提供商的名称服务器,注册商自己的 DNS 控制面板仍会显示一个区域,也仍会保存您的修改,但互联网上没有任何设备会向该区域查询。记录确实存在,只是从未被使用。

请先确认互联网实际查询的是哪里:

dig example.com NS +short
dig +trace example.com

第一条命令会显示当前为该域名提供响应的名称服务器。第二条命令从根服务器开始遍历查询链,并显示 TLD 服务器返回的委派信息;这就是由您的注册商控制的委派。如果这些名称服务器属于您不认识的服务提供商,那么您需要使用的控制面板就在该服务提供商处。

一次查询的传递过程

整个过程涉及四方,每一方都会保留自己获知信息的副本。

  1. 您计算机上的存根解析器。它不负责搜索,只会向一个已配置的服务器发起请求,并信任对方的回复。在 Ubuntu 上,/etc/resolv.conf 通常是指向 /run/systemd/resolve/stub-resolv.conf 的符号链接,而 /run/systemd/resolve/stub-resolv.conf 会指向本地运行的 systemd-resolved,其名称为 127.0.0.53,并带有自己的缓存。
  2. 递归解析器。它可能由您的 ISP(互联网服务提供商)运行,也可能是 1.1.1.1 这样的公共解析器,或者由您自行运行。它负责实际查找答案。
  3. 根服务器和 TLD 服务器。递归解析器先向根服务器发起请求。根服务器不知道您的地址,但会回复一条指向 .com 服务器的委派信息。后者再回复一条指向您的权威名称服务器的委派信息。
  4. 权威名称服务器。它不向任何其他服务器查询,而是直接从您的区域文件中返回答案,并将其标记为权威答案。

dig +trace example.com 会展示这一过程,因为它从根服务器本身开始,并打印每次委派,而不是向缓存发起请求。这是检查委派信息与区域文件是否一致的最快方法。

运行服务器时需要关注的 DNS 记录

  • A:将名称指向 IPv4 地址。example.com. A 203.0.113.10。该记录用于将域名指向您的 VPS。
  • AAAA:将名称指向 IPv6 地址,例如 2001:db8::10。只有当服务确实监听该地址时,才发布此记录。IPv6 网络中的客户端会优先尝试 AAAA 记录的响应,因此,如果该地址没有服务响应,每次访问都会增加等待时间。
  • CNAME:将一个名称别名指向另一个名称。www.example.com. CNAME example.com.会将访问 www 的用户引导到裸域名解析到的目标。CNAME 不能位于顶级域(裸 example.com),因为顶级域必须包含自己的 SOA(权威起始)和 NS 记录,而 CNAME 不能与其他任何记录共享同一个名称。服务商通常会提供 ALIAS、ANAME 或 CNAME flattening 等名称的替代方案。
  • MX:指定域名的邮件投递位置。它包含一个主机名和一个优先级数值,数值越小越先尝试。MX 必须指向包含地址记录的名称。将 MX 指向 CNAME 是无效配置,某些发件服务器会拒绝此类配置。
  • TXT:自由文本,用于验证和策略配置。邮件身份验证记录(SPF、DKIM、DMARC)位于此处,签发通配符证书所需的 ACME(自动证书管理环境)令牌也位于此处。
  • NS:指定哪些名称服务器为该区域提供服务。决定互联网应向哪里查询的副本位于父区域中,由注册商的委派配置提供,而不是位于您自己的区域内。

有两个细节比记录类型本身更容易引起混淆。名称末尾的点表示绝对名称,因此 www.example.com. 只表示该名称本身,不包含其他内容。大多数控制面板要求填写相对名称,并会自动为您追加域名,因此在名称框中输入 www.example.com 会得到 www.example.com.example.com,该名称不会解析到任何对象。另一个细节是 @,在几乎所有控制面板中都表示顶级域:不带子域名的域名本身。

将 A 记录指向您的 VPS

首先获取互联网看到的服务器地址:

curl -4 https://ifconfig.me
ip -brief -4 address show

然后在 DNS 服务商处创建一条记录:类型为 A,名称为 @,值为该地址,TTL(生存时间)设为 300。再为 www 添加第二条记录,可以使用指向同一地址的另一个 A,也可以使用指向顶级域的 CNAME

现在验证解析结果。最好从您的笔记本电脑执行,而不是直接在服务器上执行:

dig example.com A +short
dig @1.1.1.1 example.com A +short
dig @ns1.your-dns-host.net example.com A +short

第一个命令使用计算机的正常解析路径,包括缓存。第二个命令跳过本地缓存,并向公共递归解析器发起查询。第三个命令直接查询您的权威 nameserver,因此返回的是当前真实结果,查询路径中没有缓存。当第三个命令返回您的地址,而第一个命令没有返回时,说明 DNS 配置正确,您正在等待旧结果的缓存副本过期。

解析成功但无法加载

名称解析成功只能证明 DNS 正常,无法证明 Web 服务器正常。dig 返回正确地址后,测试连接:

curl -I http://example.com

curl: (6) Could not resolve host: example.com 是 DNS 问题。curl: (7) Failed to connect to example.com port 80 after 21 ms: Connection refused 不是 DNS 问题:名称已解析,数据包也已到达,因此问题在于该端口没有进程监听。请求一直挂起,最终超时,通常表示防火墙静默丢弃了数据包,而不是拒绝连接。此时 DNS 已不再是排查重点,应检查端口和监听套接字以及VPS 上的 ufw 防火墙规则。连接建立后,页面加载的其余过程就是HTTP 在处理请求

浏览器为什么仍显示旧主机

不会自动传播。没有任何服务器会主动将你的更改推送给其他人。你保存更改后,权威名称服务器会立即保存新值;而每个旧答案的缓存副本都会继续有效,直到自身计时器到期。这个计时器就是 TTL,单位为秒,记录下发时会携带该值。

缓存副本存在于比大多数人预期更多的位置:浏览器自己的短期缓存、计算机上的存根解析器、该网络使用的递归解析器,以及 VPN 在客户端上安装的任何解析器。每个位置都会将副本保留不超过收到的 TTL 时间。两个使用不同网络的人可能在数小时内看到不同的答案,但两台计算机的行为都符合预期。

通过缓存解析器观察倒计时:

dig @1.1.1.1 example.com +noall +answer

间隔几秒运行两次。答案中的 TTL 会逐渐减少。当 TTL 变为 0 时,解析器会丢弃该记录,并再次向你的名称服务器发起查询。

还有一种几乎没人考虑的缓存:否定答案。当解析器得知某个名称不存在时,也会缓存该 NXDOMAIN,缓存时间由区域 SOA 记录最后一个字段设置。

dig example.com SOA +short

该行的最后一个数字就是否定 TTL,通常为 3600。因此,在创建 staging.example.com 之前查询它,可能会导致该记录在创建后整整 1 小时内仍不可见。先创建记录,再查询它。

更换名称服务器比修改记录慢,原因在于委派机制。.com 区域中的委派记录以 172800 秒的 TTL 提供,也就是 2 天。因此,已缓存旧名称服务器的解析器可能会在这段时间内继续向旧名称服务器发起查询。“最多等待 48 小时”的建议就源于此。它适用于名称服务器变更,不适用于普通记录修改。

根据 TTL 规划迁移,不要与缓存机制对抗:

  1. 将记录的 TTL 降低到 300 并保存。
  2. 等待超过旧 TTL 的时间,确保所有包含旧值的缓存副本都已过期。
  3. 修改地址。
  4. 流量迁移完成后,将 TTL 恢复为 3600 或更高,因为较低的 TTL 会导致每个解析器更频繁地向你的名称服务器发起查询。

要清除本机当前保存的内容:

resolvectl flush-caches
resolvectl statistics

resolvectl statistics 会输出包含命中和未命中计数器的缓存部分,因此清空缓存后立即进行的下一次查询会显示为未命中。浏览器使用独立缓存,因此系统缓存为空后,Chrome 仍可能使用旧答案。在 chrome://net-internals/#dns 清除浏览器缓存。还要检查 /etc/hosts,因为其中残留的一行配置会在该计算机上覆盖 DNS,且只影响该计算机。getent hosts example.com 会显示系统实际使用的答案,其中包括 /etc/hosts

通配符证书通过 TXT 记录完成验证

CA(证书颁发机构)会在签发证书前验证您是否控制相应域名。HTTP-01 挑战会通过端口 80 在指定主机名上提供文件,适用于单个域名。通配符证书覆盖 *.example.com,对应一组开放范围的主机名,CA 无法从这些主机名获取文件。因此,Let's Encrypt 只通过 DNS-01 挑战签发通配符证书。您需要在 _acme-challenge.example.com 发布 TXT 记录,并写入 CA 提供的令牌。对该 DNS 区域的控制权就是验证依据。

这意味着您的 DNS 托管商会参与证书续期。Certbot 必须在每次续期时自动创建和删除该 TXT 记录,因此需要您的 DNS 提供商提供 API,以及与该提供商匹配的插件。验证失败时,常见错误消息是 DNS problem: NXDOMAIN looking up TXT for _acme-challenge.example.com。这表示 CA 发起查询时,该记录还不可见:要么记录从未保存成功,要么否定响应仍在缓存中。完整流程请参阅使用 DNS-01 挑战申请通配符证书的指南

VPN 接管解析器时

VPN(虚拟专用网络)客户端通常会在连接期间替换系统解析器,因为将查询发送到本地网络会使该网络知道您访问的每个站点的名称。这是正确的行为,但可能出现两个方向的问题。

如果隧道建立后名称停止解析,但地址仍可访问,说明客户端安装的解析器无法从隧道内部访问。ping 1.1.1.1 成功,而 curl https://example.com 返回 curl: (6) Could not resolve host: example.com。如果隧道建立后,查询仍发送到您当前连接的网络,则网络流量已通过隧道传输,但本地解析器仍会看到您查询的每个名称。

resolvectl status

该命令会显示每个链路正在使用的解析器,因此您可以确认隧道安装了哪个解析器,以及它是否是您预期的解析器。WireGuard 隧道通过客户端配置中的 DNS = 行设置该解析器;修复 WireGuard 接管解析器时的 DNS 问题详细介绍了 systemd-resolved 和 resolvconf 的处理方式。

回复代码及其含义

  • NXDOMAIN:权威服务器表示该名称不存在。检查拼写,确认域名后缀没有重复,并确认您编辑的是委派所指向的区域。
  • NOERRORANSWER SECTION 为空:该名称存在,但没有您所查询类型的记录。例如,仅存在 A 时查询 AAAA,就会得到此结果。
  • SERVFAIL:解析器尝试过解析,但无法生成答案。最常见的两个原因是权威服务器始终不响应,以及 DNSSEC(域名系统安全扩展)验证失败。使用 dig @1.1.1.1 example.com A +cd 进行测试,该选项会禁用验证。如果不使用该选项时返回 +cdSERVFAIL,则表示问题出在签名上。这种情况通常发生在更换名称服务器后,而父区域仍发布旧的 DS(委派签名)记录。
  • REFUSED:您查询的服务器不会回答该问题。通常是因为您将 dig 指向了某个域的权威服务器,但该服务器并不负责提供该域。
  • ;; connection timed out; no servers could be reached:dig 从未连接到解析器。这是您所在网络或解析器的问题,与该域本身无关。

ping: example.com: Temporary failure in name resolution 表示 glibc 报告的同类故障,而不是 dig 报告的故障。

是否应在自己的 VPS 上运行权威 DNS 服务器?

可以。bind9knotnsd 可以从服务器提供您的区域数据,这比使用任何控制面板都更能帮助您理解 DNS。反对这样做的理由主要是实际运维风险。一个域名至少应配置位于不同网络中的两个权威 DNS 服务器,因此单台 VPS 会成为该域名上所有服务的单一故障点,邮件服务也不例外。在所服务的域名内部命名的 DNS 服务器,需要在注册商处配置 glue 记录。glue 记录是存储在父区域中的 ns1.example.com 地址,否则 DNS 查询无法开始。当解析器无法访问您的 DNS 服务器时,它不会回退到您的网站:对该用户而言,整个域名都会消失。对大多数人来说,带 API 的托管 DNS 风险更低。在 VPS 上为自己的机器运行缓存解析器属于另一类工作,投入和维护负担也小得多。

FAQ

为什么我的 DNS 更改还没有生效?

没有什么内容在“传播”。您保存新值后,权威名称服务器会立即持有该值;已经查询过的每个解析器会继续使用缓存副本,直到收到的 TTL 到期。使用 dig @ns1.your-dns-host.net example.com A +short 直接查询权威服务器。如果返回新地址,说明更改已经生效,剩下的只是缓存问题。如果您更改的是名称服务器而不是记录,预计等待时间会长得多,因为 TLD 委派信息使用 two day TTL 下发。

如何查找我的域名实际使用的是哪些名称服务器?

dig example.com NS +short 会显示当前为该域名提供应答的名称服务器,dig +trace example.com 会显示从根开始的委派链,其中包括 TLD 服务器下发的委派信息。如果这些名称服务器不是您一直在其控制面板中编辑记录的服务商,那么问题就在这里。请在委派信息指定的服务商处编辑记录,或者在注册商处修改委派信息,使其指向您需要的位置。

我的域名可以解析,但网站仍然无法加载。现在该怎么办?

只要 dig example.com A +short 返回您服务器的地址,DNS 部分就已经完成。之后的问题属于连接问题。curl -I http://example.com 返回 Connection refused,表示该端口没有进程监听。请求一直等待直到超时,表示防火墙丢弃了数据包。请确认 Web 服务器正在运行并绑定到公网地址,然后检查服务器上的防火墙,以及服务商控制面板中的独立网络防火墙。

为什么不能在根域名上设置 CNAME?

CNAME 表示一个名称是另一个名称的别名,而包含 CNAME 的名称不能同时包含任何其他记录。根域名必须包含 SOA 和 NS 记录,才能作为区域存在,因此不能同时设置为 CNAME。请在根域名上使用包含地址的 A 记录,或者使用服务商提供的 ALIAS、ANAME 或 CNAME flattening 功能。该功能会保存一个名称,并使用该名称当前解析到的地址来应答查询。