目录

本地网络出口DNS检测[开源]

在上一篇文章从 DNS 异常排查到使用 mosdns v5 对国外网站进行分流解析 中已经在局域网中搭建好了一个dns分流。那么,如何验证是否是否成功呢?

可以直接访问 https://nstool.zxcvx.com/ https://nstool.netease.com/进行测试,本文章主要讲实现原理。

思路

自己的域名解析NS记录,搭建 “权威 DNS 服务器”,监听 UDP/TCP 53 端口,实现 RFC 1035 标准的权威应答。

其次,在使用 nslookup 或者 dig 测试时,即使你手动指定dns服务器,那么也会被抢答, 权威dns根本收不到解析消息,所以这也间接证明上一篇文章DNS是被抢答

ps:最好不要在国内服务器搭建,毕竟有些服务商检测到你开53就会封机,不管是 权威DNS 还是 递归DNS。

原理

DNS 探测机制:前端生成随机 token,通过加载 .domain 下的 1×1 透明 PNG 触发浏览器 DNS 查询,从权威 DNS 层捕获用户的递归解析器 IP。

用户浏览器
    │
    ├─① HTTP 请求 → 服务器:8080
    │   生成随机 token,页面加载
    │
    ├─② 浏览器加载图片: http://<token>.dns.yourdomain.com/probe.png
    │   这会触发 DNS 查询
    │
    ├─③ 用户的 DNS 解析器查询 <token>.dns.yourdomain.com
    │   → 到达 权威DNS服务器:53
    │   → 记录解析器 IP + token
    │
    └─④ 浏览器轮询 /api/info?token=<token>
        → 返回用户IP + DNS解析器IP + 地理信息

https://s3.aixfan.com/img/screenshot/2026/04/03/7xxmaCogNNzC8h9ptCpkvxCF86CjNt6Y.webp

开源地址

故根据以上原理,我使用了 Cloude 生成了go语言的代码.

测试地址:https://nstool.zxcvx.com/

开源地址 https://github.com/luoye663/dns-detector

搭建教程在Github中的 README.md 中。

核心功能

  • 权威 DNS 服务器:同时监听 UDP/TCP 53 端口,实现 RFC 1035 标准的权威应答(支持 A、NS、SOA、NXDOMAIN、REFUSED 响应类型)
  • DNS 探测机制:前端生成随机 token,通过加载 <token>.domain 下的 1×1 透明 PNG 触发浏览器 DNS 查询,从权威 DNS 层捕获用户的递归解析器 IP
  • 客户端 IP 获取:HTTP 层获取用户真实出口 IP,兼容 Nginx/CDN 反代(优先读取 X-Forwarded-ForX-Real-IP
  • IP 地理归属查询:使用 GeoLite2 。
  • Web 前端:内置单页应用,实时展示客户端 IP 与 DNS 解析器 IP 及归属地,含原理说明、流程图、探测进度条

Token 机制

  • 唯一性:每次检测生成 12 位随机字母数字 token
  • 一次性消费:token 被 HTTP 端读取后立即从内存删除,不可重复消费(double-check 锁防并发竞态)
  • 自动过期:未被消费的 token 存活上限为 5 分钟,后台每 1 分钟扫描清理一次
  • 存储位置:纯进程内存(map[string]tokenEntry),重启后丢失,不依赖外部存储

配置(全部通过环境变量)

变量 默认值 说明
DNS_DOMAIN dns.example.com 权威 DNS 区域(必填)
NS_IP 1.2.3.4 服务器公网 IP(必填)
WEB_PORT :8080 HTTP 监听端口
DNS_PORT :53 DNS 监听端口
LOG_LEVEL info 日志等级(debug/info/warn/error)
DNS_ALLOW_ZONES 追加白名单区域,逗号分隔

已知局限

  • 不支持多实例:TokenStore 在进程内存,水平扩展需替换为 Redis
  • 重启丢失:进行中的探测 token 随进程重启消失
  • DoH 场景:用户开启 DNS over HTTPS 时,DNS 查询走加密通道,本工具只能捕获 DoH 提供商的出口 IP,无法得知用户真实配置的 DNS 服务器