OneUptime DNS Monitor 实战指南:从 DNS 解析探测到 DNSSEC 校验的完整实现解析
2026/9/17 15:52:21 网站建设 项目流程

OneUptime DNS Monitor 实战指南:从 DNS 解析探测到 DNSSEC 校验的完整实现解析

【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime

本篇基于 OneUptime 官方文档(de/monitor/dns-monitor.md)展开,系统讲解 DNS 监控器的创建流程、全部配置项与监控标准(Criteria)体系,并结合仓库中 Probe 探针服务与公共类型层的真实源码,深入剖析 DNS 查询、重试、超时、记录值提取与 DNSSEC 校验的底层实现原理,帮助你在理解"文档上怎么配"的同时掌握"代码里怎么跑"。

一、DNS Monitor 能做什么

DNS Monitor(DNS 监控器)用于持续监测你域名的 DNS 解析健康度与正确性。OneUptime 会定期发起 DNS 查询,并将返回结果与你配置好的校验标准逐一比对。官方文档将其定位的适用场景概括为:

  • 监测 DNS 服务的可用性(服务是否在线、能否响应查询);
  • 校验 DNS 记录是否返回预期的值(例如 A 记录是否仍指向正确的 IP);
  • 追踪 DNS 解析的响应时间趋势;
  • 验证 DNSSEC 配置是否有效;
  • 发现 DNS 传播异常或被劫持(Hijacking)的迹象。

从源码结构看,这套能力分布在三层:前端表单负责收集配置(DnsMonitorStepForm.tsx),共享类型层定义数据结构与默认值(MonitorStepDnsMonitor.ts),Probe 探针服务执行真实的网络探测(DnsMonitor.ts),监控判定则由服务端标准评估器完成(DnsMonitorCriteria.ts)。

二、创建一个 DNS Monitor

按官方文档,创建流程为:

  1. 进入 OneUptime 控制台的Monitors(监控器)页面;
  2. 点击Create Monitor(创建监控器)
  3. 在监控器类型中选择DNS
  4. 填入要查询的域名(Domain Name)和要查询的记录类型(Record Type);
  5. 按需配置监控标准(Monitoring Criteria),决定"在线 / 降级 / 离线"的判定条件。

对应到前端实现,DnsMonitorStepForm.tsx 提供了三个基础输入项(Domain Name、Record Type、DNS Server),并通过一个 "Advanced: Port, Timeout and Retries" 折叠按钮展开高级选项(Port、Timeout (ms)、Retries),与文档中的"基本设置 + 高级设置"两层结构完全对应。

三、配置项详解

3.1 基本设置

字段说明是否必填
Domain Name(域名)要查询的域名,例如example.com,映射到配置中的queryName
Record Type(记录类型)要查询的 DNS 记录类型,例如AMX
DNS Server(DNS 服务器)自定义 DNS 服务器,例如8.8.8.8;留空则使用系统默认,映射到配置中的hostname

这些字段在 MonitorStepDnsMonitor.ts 中被定义为MonitorStepDnsMonitor接口,并附带一套默认值(getDefault(),见该文件 L14-L23):

{ queryName: "", // 域名 recordType: DnsRecordType.A, // 默认记录类型 A hostname: "", // 默认使用系统 DNS port: 53, // 默认端口 53 timeout: 5000, // 默认 5000 ms retries: 3 // 默认重试 3 次 }

3.2 支持的记录类型

文档声明支持 10 种记录类型,与源码枚举 DnsRecordType.ts 一一对应:

记录类型说明
AIPv4 地址记录
AAAAIPv6 地址记录
CNAME规范名(别名)记录
MX邮件交换记录
NS权威名称服务器记录
TXT文本记录(SPF、DKIM 等)
SOAStart of Authority 记录
PTR反向解析记录
SRV服务定位记录
CAA证书颁发机构授权记录

值得注意的细节是:不同记录类型在探针中被归一化为统一的{type, value, ttl?}结构(DnsMonitorResponse.ts),但复合记录会被"压平"成字符串,例如:

  • MX优先级 交换主机(如10 mail.example.com),源码 DnsMonitor.ts L249-L259;
  • SRV优先级 权重 端口 主机名,L300-L310;
  • SOA→ 七字段空格拼接nsname hostmaster serial refresh retry expire minttl,L281-L289,TTL 取minttl
  • CAAcritical issue,L311-L323。且由于dns.promises.Resolver类型上未暴露resolveCaa,源码直接调用独立的dns.promises.resolveCaa(queryName)(见 L312 注释)。

如果你要用"DNS 记录值"标准做精确匹配,需要按上述压平格式书写期望值。

3.3 高级设置

字段说明默认值
Port(端口)DNS 查询使用的端口号53
Timeout (ms)(超时)等待响应的时间5000
Retries(重试次数)失败后的重试次数3

这三个参数在探针查询逻辑中的作用(DnsMonitor.ts):

  • Timeoutoptions.timeout || config.timeout || 5000(L53)。代码注释明确指出调用方显式传入的超时优先于配置默认值——这是为了避免"步骤级设置被配置默认值静默覆盖"的 bug。超时会直接作用于dns.promises.Resolver的构造参数。
  • Port:仅当配置了自定义 DNS 服务器且端口非 53 时,才会以hostname:port的形式调用resolver.setServers([server])(L59-L65);未配置自定义服务器时,Resolver 使用系统默认解析器。
  • Retries:失败后按options.retry ?? config.retries ?? 3递归重试,每轮之间固定Sleep.sleep(1000)间隔 1 秒(L154-L158)。注释特别说明这里用??而非||——调用方显式要求 0 次重试就是 0 次,不会被配置默认值"救活"。

每次尝试(无论成功或失败)都会被记入probeAttempts数组,记录尝试序号、发起时间、响应时间与失败原因,最终随totalAttempts一起返回给上层,为面板上的"探测明细"提供数据。

3.4 超时与其他失败如何区分

探针捕获异常后会做二次分类(L170-L199):若错误信息包含timeouttimed outetimeout,响应中标记isTimeout: truefailureCause为 "Request was tried N times and it timed out.";否则isTimeout: falsefailureCause记录原始错误信息。这种区分让上层监控面板能够把"网络不可达"和"响应慢"两种故障呈现为不同的语义。

四、监控标准(Criteria):在线、降级与离线的判定

文档定义的 5 类检查项,全部由服务端 DnsMonitorCriteria.ts 中的isMonitorInstanceCriteriaFilterMet方法实现,检查项常量定义在 CriteriaFilter.ts 的CheckOn枚举中(L97-L102):

检查项(CheckOn)说明源码判定逻辑
DNS Is Online(DNS 在线)DNS 服务器是否响应查询读取dataToProcess.isOnline,做布尔比较(L62-L71)
DNS Response Time (in ms)(响应时间)单次查询耗时读取dnsResponse.responseTimeInMs,做数值比较(L74-L95)
DNS Record Exists(记录存在)查询是否返回了记录records.length > 0(L98-L117)
DNS Record Value(记录值)记录返回值的字符串/数值匹配遍历所有记录逐条比较,数值阈值优先尝试数值比较(L142-L184)
DNSSEC Is Valid(DNSSEC 有效)DNSSEC 校验是否通过isDnssecValid === undefined时返回 null(无法判定)(L120-L139)

各检查项可用的过滤类型(FilterType枚举,CriteriaFilter.ts L297-L326):

  • 布尔型(DNS Is Online、DNS Record Exists、DNSSEC Is Valid):True/False
  • 数值型(DNS Response Time):GreaterThanLessThanGreaterThanOrEqualToLessThanOrEqualTo
  • 记录值ContainsNotContainsStartsWithEndsWithEqualToNotEqualTo。其中数值型阈值还会先尝试按数字比较(例如把端口号类的记录值与数字阈值对比),失败再回退到字符串比较(DnsMonitorCriteria.ts L151-L171)。

两个容易踩坑的实现细节:

  1. 记录存在性检查不依赖记录值匹配DNS Record Exists只看records数组是否为空。也就是说,查询返回了记录但值不符合预期时,"存在"标准仍会判定为真;要约束具体值必须使用DNS Record Value
  2. DNSSEC 的三态处理。响应字段isDnssecValid可以是truefalseundefined(见 3.6 节,探针环境没有dig时即为 undefined)。标准评估器对undefined一律返回 null(不触发标准),避免把"无法检测"误判为"校验失败"。

4.1 文档给出的示例标准

  • 检查 DNS 是否可解析:检查项 = DNS Is Online,过滤类型 = True;
  • 检查 A 记录是否指向正确 IP:检查项 = DNS Record Value,过滤类型 = EqualTo,值 =93.184.216.34
  • DNS 响应缓慢时告警:检查项 = DNS Response Time (in ms),过滤类型 = GreaterThan,值 =500
  • 检查 DNSSEC 是否有效:检查项 = DNSSEC Is Valid,过滤类型 = True。

五、DNSSEC 校验的底层实现

探针端checkDnssec方法(DnsMonitor.ts L350-L404)的完整链路值得细看:

  1. 入参安全校验:先经isValidHostnameOrIP校验queryNamednsServer(IPv4/IPv6/主机名正则,长度 ≤ 253),防止参数注入——因为这两个值最终会被拼进命令行参数。
  2. 调用 dig 命令行execFile("dig", ["+dnssec", queryName, recordType, "@" + (dnsServer || "8.8.8.8")])。代码注释解释了为什么这样做:Docker 内置 DNS 和许多默认解析器不做 DNSSEC 验证,AD(Authenticated Data)标志永远不会被置位;因此校验固定走一个"会验证 DNSSEC 的解析器"——用户指定了自定义 DNS 就用它,否则回落到 Google Public DNS(8.8.8.8)。
  3. 解析 AD 标志:用正则/flags:.*\bad\b/i在 dig 输出中匹配AD标志,匹配到即认为签名链验证成功。
  4. 降级策略:如果环境里没有dig,回调收到 error 后返回undefined(而不是抛异常),主查询流程捕获后把isDnssecValid置为undefined(L80-L93),即"未知"状态。
  5. 超时约束:DNSSEC 检查复用主查询的timeoutInMs,注释说明这是刻意设计——避免慢解析之上再叠加一段更长的等待。

六、一次查询的完整数据流

把上述片段串起来,一次 DNS 监控的完整生命周期是:

  1. 配置落库:前端表单提交后,配置序列化为MonitorStepDnsMonitorfromJSON/toJSON,MonitorStepDnsMonitor.ts L25-L45);
  2. Probe 执行查询DnsMonitorUtil.query(config, options)创建dns.promises.Resolver、按记录类型分派到resolve4 / resolve6 / resolveCname / resolveMx / resolveNs / resolveTxt / resolveSoa / resolvePtr / resolveSrv / resolveCaa(DnsMonitor.ts L203-L327);用process.hrtime高精度计时(L44、L74-L77);随后执行 DNSSEC 检查;
  3. 返回统一响应DnsMonitorResponse(DnsMonitorResponse.ts)包含isOnlineresponseTimeInMsfailureCauserecords[]isDnssecValid?isTimeout?probeAttempts[]totalAttempts
  4. 服务端评估标准DnsMonitorCriteria将上述响应与每条CriteriaFilter比对,输出满足/不满足的判定,再交由监控系统聚合为在线/降级/离线状态并触发通知。

七、实践建议

  • DNS 服务器选择:默认留空(走系统解析器)适合大多数场景;要排查"特定区域解析异常"时,可显式指定某区域公共 DNS,但注意此时 DNSSEC 检查也改用该服务器——只有会做验证的解析器才能给出可靠的 AD 标志。
  • 记录值匹配格式:对 MX/SRV/SOA 使用EqualTo前,先按 3.2 节的压平格式确认期望值;用Contains通常更稳健(例如 MX 记录只校验mail.example.com而不关心优先级)。
  • 超时与重试的组合效应:单次查询超时 5000ms、重试 3 次、间隔 1 秒时,最坏情况单次探测会耗时约 5s×4 + 3s ≈ 23 秒,设置监控间隔时应把这一上界考虑在内。
  • 环境依赖:DNSSEC 校验依赖探测节点安装dig(bind-utils/dnsutils)。无dig时该检查静默降级为"未知",不会让监控器本身报错。

八、相关源码与文档索引

  • 官方文档(德语):App/FeatureSet/Docs/Content/de/monitor/dns-monitor.md(同目录结构下另有 en、zh-CN 等 16 个语言版本)
  • 探针查询实现:Probe/Utils/Monitors/MonitorTypes/DnsMonitor.ts
  • 监控器配置类型与默认值:Common/Types/Monitor/MonitorStepDnsMonitor.ts
  • 记录类型枚举:Common/Types/Monitor/DnsMonitor/DnsRecordType.ts
  • 响应数据结构:Common/Types/Monitor/DnsMonitor/DnsMonitorResponse.ts
  • 标准评估器:Common/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.ts
  • 检查项与过滤类型枚举:Common/Types/Monitor/CriteriaFilter.ts
  • 前端配置表单:App/FeatureSet/Dashboard/src/Components/Form/Monitor/DnsMonitor/DnsMonitorStepForm.tsx
  • 单元测试:Common/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts、Common/Tests/Types/Monitor/MonitorStepDnsMonitor.test.ts

【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询