ARTICLE DETAIL

资讯详情

深耕网站SEO优化与搜索引擎排名提升的一线实战洞察。

DNS 劫持检测 API 的最小可运行示例:curl 与 Python 双版本

DNS 劫持检测 API 的最小可运行示例:curl 与 Python 双版本 为什么要给接口准备一个最小可运行版本面对一个新的 HTTP 接口最常见的困境并不是读不懂文档而是不知道从哪里开始需要先鉴权、再拼 URL、再处理响应往往要花上数分钟才能看到第一条真实返回。而「最小可运行示例」的目的就是把这个链路压缩到一次复制、一次粘贴、一次回车。本文以 DNS 劫持检测接口为对象提供一个不含业务代码的最小版本先用 curl 验证连通性再用一段 Python 验证结构化处理最后补充字段解读和工程化注意点。你可以在本地直接执行。适用场景这个接口适合以下三类快速验证场景域名资产巡检将自有域名列表批量提交对比多个 DoH 服务商的解析结果识别异常。攻击排查怀疑域名被污染时手工跑一次检测快速获取多源 DoH 的一致性结论。开发环境自检在写自动化脚本之前先用单条请求确认接口返回结构避免盲写解析逻辑。注意接口返回的是「多源 DoH 一致性结论」不是本地递归 DNS 服务器的解析结果两者含义不同不能互相替代。接口能力边界与检测原理接口的检测原理是通过对比 5 大公共 DoHCloudflare、Google、AliDNS、DNSPod、OpenDNS对同一个域名的解析结果判断是否存在劫持、污染或篡改。多源结果一致时判定为安全多源结果不一致时判定为高风险。接口输出的是risk_level字段而不是直接丢出各个 DoH 的原始 JSON。需要明确的能力边界只接受 GET 请求没有批量提交入口批量场景需在调用方自行循环。QPS 为 5 / s超过后需要等待或退避。覆盖范围是 5 家 DoH 服务商不包含本地运营商缓存节点因此它对「某一台机器被劫持」无能为力。接口不返回 DoH 原始响应只返回统一排版后的判断结果。请求参数与鉴权接口地址GET https://v1.apizero.cn/api/dns-hijackQuery 参数只有一个参数类型必填说明示例domainstring是域名不要带协议前缀和路径baidu.com鉴权方式请求头携带X-API-Key。Key 的申请方式以官方文档为准。这里给出的 curl 示例中$APIZERO_API_KEY为环境变量你也可以把它替换成自己的真实 Key 字符串。两个容易踩的细节domain 里不要出现https://或http://也不要带路径例如baidu.com而不是https://baidu.com/。域名建议只使用 ASCII 字符IDN 域名是否需要转义以文档为准。可复制的最小 curl 示例示例代码curl -sS \ -X GET \ -H X-API-Key: $APIZERO_API_KEY \ https://v1.apizero.cn/api/dns-hijack?domainbaidu.com返回内容示例{ code: 0, data: { domain: baidu.com, is_hijacked: false, risk_level: low, summary: 5 个 DoH 服务商解析结果一致未检测到劫持迹象, unique_ips: [ 110.242.68.3, 110.242.68.4 ] }, msg: 成功 }实际响应以接口返回为准。这里可以看到data.unique_ips中出现了两个 IP并不意味着被劫持同一域名通过不同 DoH 返回多个 IP可能是多线路或负载均衡的常态只有当结果不一致时才需要警惕。一个最小 Python 版本curl 只解决「能不能调通」的问题。接下来用更短的 Python 代码把「调用 判断 输出」做成一个可复用的最小函数。import sys import requests API_URL https://v1.apizero.cn/api/dns-hijack API_KEY YOUR_API_KEY_HERE def check_dns_hijack(domain: str) - dict: resp requests.get( API_URL, params{domain: domain}, headers{X-API-Key: API_KEY}, timeout10, ) resp.raise_for_status() body resp.json() if body.get(code) ! 0: raise RuntimeError(f接口返回业务错误: {body}) return body[data] if __name__ __main__: domain sys.argv[1] if len(sys.argv) 1 else baidu.com data check_dns_hijack(domain) if data[is_hijacked]: print(f[高风险] {domain} 疑似被劫持) else: print(f[安全] {domain} 风险等级: {data[risk_level]}) print(data[summary])运行方式python3 dns_hijack_demo.py baidu.com如果你的环境还没有安装requests先执行pip install requests。这个脚本做了三件事拼接参数、发送请求、按code判断业务是否成功。整个过程没有引入额外的类库适合作为接入的骨架。返回字段逐项解读接口返回体最外层是code和msg业务数据放在data中。字段含义如下字段类型含义codeint业务状态码0表示成功msgstring状态描述data.domainstring本次查询的域名echo 回显data.is_hijackedboolean是否判定为劫持data.risk_levelstring风险等级low/medium/highdata.summarystring人类可读的结论摘要data.unique_ipsstring[]各 DoH 返回结果中出现的去重 IP 列表与单一 DNS 查询不同这里的关键不是 IP 的具体值而是「多源结果是否一致」。unique_ips中只有一个 IP代表各家 DoH 都返回同一地址有多个 IP 时要结合summary判断是「多线路正常解析」还是「结果不一致」。常见错误与排查思路这里整理请求过程中最可能遇到的几类情况以及对应的排查路径返回 401 或 403检查X-API-Key请求头是否拼写正确Key 是否有效。环境变量未设置时换成字符串字面量直接测试。返回 400多半是 domain 参数缺失或格式非法。确认域名没有http://、/或空格。返回 429表示请求频率超出 QPS5 / s限制需要退避重试或加本地缓存减少重复请求。返回 5xx服务端临时异常可以做指数退避重试连续失败时以官方文档的状态说明为准。JSON 解析失败用curl -i或 Pythonresponse.text先看原始内容确认返回的 Content-Type 是否为application/json。工程化注意事项把最小示例放大到生产环境之前有几个细节值得先想清楚限速与调度QPS 5 / s 意味着 1 秒最多 5 次请求。巡检 1000 个域名时至少需要 200 秒程序里要主动做 sleep 或令牌桶限速。超时控制网络请求一定要设置超时时间避免 DNS 连接挂死拖住整个巡检任务。缓存策略同一域名在短时间内的检测结果基本不变建议加内存缓存或 Redis 缓存按分钟级设置过期时间降低上游压力。告警阈值is_hijacked为 true 时再触发告警risk_level为 low 时只记录避免频繁打扰。数据留存把每次检测的summary落库方便事后回溯是何时出现异常。另外不要把「多源 DoH 一致」当作绝对安全的证明。DoH 本身可能受制于网络环境比如服务商节点被防火墙策略影响。合理的使用方式是把它当作例行巡检中的一个信号再结合其他监控手段一起判断。参考文档文档页https://apizero.cn/aidocs/dns-hijack原始文档https://apizero.cn/aidocs/dns-hijack/raw.md
返回列表