我给自己写了一个本地 DNS 查询工具:域名到底解析到了哪里

举报
yd_294377644 发表于 2026/11/13 10:10:01 2026/11/13
【摘要】 排查网站打不开、接口连错环境或证书指向异常时,我常常需要确认域名到底返回了哪些地址。浏览器开发者工具只能看到请求结果,在线 DNS 网站又不一定使用我当前的解析器,于是我用 Python 写了一个本地 DNS 查询工具,支持 A、AAAA、CNAME、TXT 记录、解析耗时和多服务器对比。这篇博客记录查询流程、缓存判断与错误展示中的实践经验。

目录

  1. 缘起:域名打不开时,先别急着怪浏览器
  2. 需求拆解:查询结果需要带上上下文
  3. 技术选型:直接向指定解析器发请求
  4. 核心实现一:按记录类型执行查询
  5. 核心实现二:比较解析器与记录变化
  6. UI 定制:让成功、失败和缓存一眼可见
  7. 三个 DNS 查询中容易误判的地方
  8. 结尾:网络诊断的第一步是确认事实

1. 缘起:域名打不开时,先别急着怪浏览器

遇到网站打不开或接口访问异常时,我以前通常先刷新浏览器、重启服务,最后才想到检查 DNS。等真正执行查询时,又会发现问题不止是“有没有 IP”:

  • 本机解析器返回了旧地址,公共解析器已经更新;
  • 域名有 IPv6 地址,但当前网络只能访问 IPv4;
  • CNAME 链指向了意料之外的服务商域名;
  • TXT 记录未生效,验证服务一直等待;
  • 同一个域名在不同地区或不同解析器上结果不一致。

系统自带的 nslookup 和 Resolve-DnsName 都能完成基础查询,但我需要反复输入参数、比较多台 DNS 服务器时,命令行输出就不够直观了。

于是我写了一个本地工具:输入域名、记录类型和解析器,直接看到完整回答、权威信息、TTL 和查询耗时。所有查询从本机发出,不把域名列表交给第三方网站处理。

2. 需求拆解:查询结果需要带上上下文

DNS 结果如果只有几行 IP,往往不足以解释问题。工具需要同时保存查询条件和返回状态。

诉求(人话) 拆解后(可验收)
查询常见记录 支持 A、AAAA、CNAME、MX、TXT、NS
看清使用谁解析 支持系统 DNS 和手动指定服务器
判断是不是缓存 展示 TTL、响应标志和查询时间
发现解析差异 同时查询多台服务器并排比较
失败时知道原因 区分超时、NXDOMAIN、SERVFAIL 和拒绝
不泄露查询历史 默认只在内存中保存当前结果

第一版不做持续监控和全球节点探测。网络诊断工具可以显示本机能观察到的事实,但不能把一次本地查询包装成“全网解析结果”。

心得:任何网络诊断结果都必须和查询地点、时间、服务器一起展示。

3. 技术选型:直接向指定解析器发请求

程序使用 Python 和 dnspython,界面使用 tkinter:

能力 方案
DNS 查询 dns.resolver.Resolver
记录解析 dns.rdatatype
超时控制 Resolver lifetime 与 timeout
多服务器比较 多个 Resolver 实例
桌面界面 tkinter
结果导出 JSON 和文本报告

我没有解析命令行输出,而是直接使用 DNS 协议库。这样可以拿到 TTL、权威回答、别名链和明确的异常类型,不需要根据不同系统语言解析文本。

每次查询使用独立的 resolver 配置,避免上一次指定的 DNS 服务器偷偷影响下一次。默认服务器来自系统配置,但界面会把最终使用的地址明确显示出来。

4. 核心实现一:按记录类型执行查询

查询函数只接受规范化后的域名、记录类型和服务器地址:

import dns.resolver

def query_record(name, record_type, server=None):
    resolver = dns.resolver.Resolver(configure=server is None)

    if server is not None:
        resolver.nameservers = [server]

    resolver.timeout = 2.0
    resolver.lifetime = 5.0
    answer = resolver.resolve(name, record_type)

    return {
        "name": answer.qname.to_text(),
        "type": record_type,
        "ttl": answer.rrset.ttl,
        "values": [item.to_text() for item in answer],
    }

域名末尾是否带点在协议层面有明确含义,但普通用户输入时常常忽略。程序内部统一处理为绝对域名,结果展示则去掉末尾点,避免同一域名在界面上看起来像两个不同目标。

A 和 AAAA 记录分别表示 IPv4 与 IPv6 地址;CNAME 返回别名,不应被直接当成最终 IP;MX 和 NS 记录还包含优先级或委派关系,界面需要保留这些结构,而不是简单拼成字符串。

5. 核心实现二:比较解析器与记录变化

多解析器对比时,工具为每台服务器创建独立任务,同时记录请求开始时间和完成时间:

from concurrent.futures import ThreadPoolExecutor
from time import perf_counter

def query_with_timing(name, record_type, server):
    started = perf_counter()
    try:
        result = query_record(name, record_type, server)
        result["status"] = "ok"
        return result | {"elapsed_ms": round((perf_counter() - started) * 1000, 1)}
    except Exception as error:
        return {
            "status": type(error).__name__,
            "error": str(error),
            "elapsed_ms": round((perf_counter() - started) * 1000, 1),
        }

比较时先把记录值规范化:域名统一小写,IPv6 使用标准压缩表示,MX 和 NS 保留优先级。只有规范化后的集合不同,才标记为结果差异。

TTL 只表示当前回答还可能被缓存多久,并不表示记录会在 TTL 到期后一定改变。界面把 TTL 展示为缓存提示,而不是“距离下一次更新的倒计时”。

结果可以导出为 JSON,包含查询时间、服务器、记录类型、原始值和状态。导出报告用于排查和复现,不把查询历史自动上传到任何服务。

6. UI 定制:让成功、失败和缓存一眼可见

窗口顶部是域名、记录类型、解析服务器和查询按钮。中间采用表格展示不同解析器的结果,底部显示 TTL、耗时和响应状态。

状态颜色保持克制:成功是正常色,结果不一致使用黄色,超时或服务失败使用红色,NXDOMAIN 单独显示为“域名不存在”,避免和网络不可达混为一谈。

记录值支持复制,但复制的是当前单元格内容,不会把整个查询报告和服务器信息一起塞进剪贴板。历史区域默认只保留最近查询的域名和类型,不保存完整 TXT 内容。

点击 CNAME 或 MX 记录中的域名,可以把它放入新的查询框;这只是填充输入,不会自动连续查询,防止一条记录链路触发大量请求。

工具还提供“只看差异”筛选。用户可以先同时查询系统 DNS、公共 DNS 和指定权威服务器,再隐藏完全相同的结果,快速发现真正有变化的部分。

7. 三个 DNS 查询中容易误判的地方

坑一:本机查到的结果不一定是权威结果。 系统 DNS 可能来自路由器、公司网关或本地缓存。查询公共解析器能帮助对比,但也不能直接代表权威服务器的最终状态。工具必须显示服务器地址和查询时间。

坑二:TTL 不是“记录剩余寿命”的绝对证明。 中间缓存、预取和不同解析器策略都会影响实际刷新时间。TTL 只能作为解释缓存差异的线索,不能用来精确预测传播完成时间。

坑三:有 IPv6 记录不代表当前网络能用 IPv6。 DNS 只回答地址是否存在,连通性还受路由、防火墙和应用协议栈影响。A 与 AAAA 的结果应该并列显示,不能因为 AAAA 存在就判定服务可访问。

此外,CNAME、DNSSEC、分片响应和企业内部 split-horizon DNS 都可能让查询结果依赖来源网络。工具可以展示响应信息,但不会把一次查询结果过度解释成网络全貌。

8. 结尾:网络诊断的第一步是确认事实

做完这个 DNS 查询工具后,我排查域名问题时不再先猜“是不是浏览器缓存”。输入域名、选择记录类型,再对比不同解析器,当前地址、TTL 和异常状态会同时出现在屏幕上。

一个可靠的本地 DNS 工具应该做到:

  1. 说明实际使用的解析器;
  2. 区分记录不存在、服务器失败和请求超时;
  3. 同时展示 IPv4、IPv6 和别名链;
  4. 把 TTL 当作线索,而不是承诺;
  5. 保存足够的查询上下文,方便复现问题。

如果你也想做类似工具,可以先支持 A、AAAA 和 CNAME,再加入多服务器对比与 TTL 展示。网络问题很容易被一句“我这里能打开”掩盖,而一次带上下文的 DNS 查询,至少能把第一层事实确认下来。

当域名解析发生了什么能够被准确看见,后续的网络排查才有真正的起点。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。