DNS 记录查询接口接入教程:参数、请求示例与结构化返回解读
排查域名解析问题或做域名资产盘点时,经常需要查 A、MX、CAA 等各类 DNS 记录。DNS 记录查询接口支持 8 种标准类型和 ANY 模式,并把结果做结构化解析。本文从第一次调用讲起:要准备什么、最小请求怎么发、返回值怎么看。
一、适用场景
- 解析排查:检查域名的 A / AAAA 记录是否按预期配置。
- 邮件配置核对:查看 MX 记录的优先级与目标主机。
- 安全策略检查:查看 CAA 记录限制哪些 CA 可签发证书。
- 域名资产盘点:用 ANY 模式一次拉取域名的全部 DNS 配置。
- 监控告警:定时查询关键记录,发现变更时告警。
二、接口能力边界
| 项目 | 说明 |
|---|---|
| 请求方法 | GET |
| 参数 | host、type |
| 支持类型 | A、AAAA、NS、CNAME、MX、TXT、CAA、SOA |
| 特殊类型 | ANY,一次返回所有类型 |
| 兼容写法 | 数字 qtype,如 1=A、15=MX、257=CAA |
| 数据来源 | 3 家国内 DoH 并发查询后合并去重 |
| 来源标注 | 每条记录通过sources标注来自哪些 DoH |
需要理解两点能力边界:第一,结果是多家 DoH 合并去重后的集合,不是权威服务器单点返回;第二,ANY 能一次拿到全部配置,但请求与响应体积更大,只查单一类型时没必要用 ANY。
三、请求参数与鉴权
参数共两个:
| 参数 | 说明 |
|---|---|
host | 待查询的域名 |
type | 记录类型,可用 8 种标准类型或 ANY,也可传数字 qtype |
鉴权方式与请求头字段,素材未给出,以文档为准。因为这是GET请求,参数放在查询字符串中,接入前请先在文档里确认是否需要携带 Key 以及域名是否支持子域名。
四、最小请求示例
下面是一个可复制的 curl 模板,查询某域名的 MX 记录:
curl -X GET 'https://v1.apizero.cn/api/dns-query?host=example.com&type=MX'用数字 qtype 查询 CAA 记录,效果等价:
curl -X GET 'https://v1.apizero.cn/api/dns-query?host=example.com&type=257'用 ANY 一次拉取全部类型:
curl -X GET 'https://v1.apizero.cn/api/dns-query?host=example.com&type=ANY'对应的 Python 调用示例:
import requests def query_dns(host: str, record_type: str, api_key: str | None = None) -> dict: headers = {} if api_key: headers["Authorization"] = f"Bearer {api_key}" resp = requests.get( "https://v1.apizero.cn/api/dns-query", params={"host": host, "type": record_type}, headers=headers, timeout=10, ) resp.raise_for_status() return resp.json()调用前先对host做基础校验:去掉协议前缀与路径,只保留域名本身,避免把https://example.com/a这类内容直接传进去。
五、返回值解读
素材明确的结构化要点如下,完整字段名以文档为准:
- MX 记录:拆成
priority(优先级)与exchange(目标主机),不用再自己拆字符串。 - CAA 记录:拆成
flags、tag、value三个字段。 - SOA 记录:拆成
mname、serial等字段。 - 来源标注:每条记录带
sources字段,说明该记录来自哪些 DoH。
一个防御式解析示例(字段名请按文档实际返回替换):
def parse_mx(payload: dict) -> list: records = payload.get("records") or [] # 数组字段名以文档为准 result = [] for item in records: if item.get("type") != "MX": continue priority = item.get("priority") exchange = item.get("exchange") if exchange is None: continue result.append({ "priority": priority, "exchange": exchange, "sources": item.get("sources", []), }) result.sort(key=lambda x: (x["priority"] is None, x["priority"])) return result排序时把优先级为空的记录放到末尾,避免None参与比较报错。sources可以用来判断某条记录是否只在单一 DoH 中出现,这对排查“解析结果不一致”很有帮助。
六、常见错误与排查
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 参数错误 | host为空或type不在支持范围 | 核对类型列表与数字 qtype 映射 |
| 无记录 | 域名未配置该类型记录 | 换 ANY 模式确认其他类型是否存在 |
| 结果与本地不一致 | 缓存或不同 DoH 数据差异 | 查看sources,结合 TTL 判断 |
| 超时 | 网络抖动或域名解析慢 | 设置超时,做有限次重试 |
| 鉴权失败 | 需要 Key 但未携带 | 以文档为准补充请求头 |
“无记录”不等于调用失败,要按空结果处理,不要无限重试。
七、工程化注意事项
- 输入清洗:统一去掉协议头、路径与末尾点,只保留域名。
- 类型映射:本地维护
1=A、15=MX、257=CAA这类数字映射,兼容旧调用。 - 结果缓存:DNS 有 TTL,按 TTL 做短时缓存,避免高频重复查询。
- 来源判断:多来源一致的记录可信度更高,单一来源的记录在告警中标注出来。
- 监控策略:只对关键类型(如 A、MX、CAA)做定时比对,ANY 模式不宜高频调用。
- 字段容错:结构化字段可能缺失,解析时逐项判空,不要假设一定存在。
参考文档
- 接口文档