代理 DNS 泄漏怎么检查和修复?协议、客户端与系统复测
简答:代理 DNS 泄漏的判断重点不是“网页能不能打开”,而是访问域名时谁完成了解析。最快流程是:先关闭代理建立基线,再开启代理测试同一随机域名;然后用 curl 或真实应用复测,最后检查客户端 DNS、TUN、浏览器 DoH、IPv6 和路由器是否重复或绕过接管。只把 DNS 改成公共地址,不能自动证明泄漏已经修复。
定义:代理 DNS 泄漏,是指代理已经转发网页或应用流量,但域名解析仍由本地系统、浏览器、路由器或未纳入代理链路的其他组件完成。
30 秒速查卡:先判断是哪条链路没有被接管
先记住:检测页面显示的 DNS 服务器所在地,不一定等于代理出口所在地;远端解析器、Anycast、CDN 和共享 DNS 都可能造成地域不同。因此,“DNS 所在地不同”不能单独证明泄漏。
| 场景 | 先查哪里 | 正常判读 |
|---|---|---|
| 浏览器在线检测 | 代理关闭、开启各测一次,记录 DNS 服务器列表 | 开启后结果发生符合预期的变化;若仍固定显示本地网络解析器,继续查浏览器、系统和路由器 |
| curl 或脚本 | 对照 socks5:// 与 socks5h:// | socks5:// 由本地解析;socks5h:// 把主机名交给代理端 |
| Clash/Mihomo | DNS 模块、TUN、DNS 劫持、fake-ip/redir-host | 未配置代理的应用也能进入客户端 DNS 链路;异常时检查虚拟网卡和路由 |
| v2rayN | 远程 DNS、Bootstrap DNS、代理目标解析策略 | 不要把直连 DNS、远程 DNS 和节点域名解析当成同一件事 |
| 手机或桌面应用 | 应用是否继承系统代理、是否单独启用 DoH 或私人 DNS | 浏览器正常不代表其他应用正常,必须用实际应用复测 |
DNS 泄漏只说明域名查询可能走了另一条路径,不等于 HTTPS 内容已经被解密;但查询对象仍可能暴露,所以需要继续确认真实应用的解析路径。
第一步:建立基线并做双重检测
- 保持网络不变:不要在 Wi-Fi、手机热点、浏览器和 DNS 提供商之间同时切换。
- 代理关闭测试:关闭系统代理和 TUN,打开在线 DNS 检测页,记录显示的 DNS 服务器、IPv4/IPv6 结果和异常提示。若不想依赖网页,可使用系统命令查询。
- 代理开启复测:只开启代理,再访问新的随机子域名或在线检测页。普通用户通常无法自行控制随机域名,因此应优先使用在线检测页;命令行测试时必须把示例域名替换成你确认可解析的域名。
- 避免缓存干扰:先清理系统和浏览器 DNS 缓存,再重复测试。浏览器页面正常,只能说明该浏览器当前请求正常,不能代表 Python、桌面客户端或手机应用。
Windows 可使用 nslookup 可解析域名 或 PowerShell 的 Resolve-DnsName 可解析域名;macOS/Linux 可使用 dig 可解析域名。这些命令显示的是当前解析请求的结果,不会自动证明请求已经进入代理隧道,因此仍需结合代理日志或抓包判读。
第二步:按代理协议判断谁解析主机名
curl 官方手册明确区分 HTTP、SOCKS4、SOCKS4a、SOCKS5 和 SOCKS5 hostname 模式。可参考 curl 官方手册。
| 代理写法 | 主机名由谁解析 | 排查结论 |
|---|---|---|
http://proxy:port | 普通 HTTP 请求会把完整 URL 交给 HTTP 代理,由代理处理目标主机名;HTTPS 通常使用 CONNECT,把主机名和端口交给代理建立隧道 | HTTP/HTTPS 代理本身不等于本地 DNS 泄漏;重点检查应用是否绕过代理或另行解析 |
socks4://proxy:port | 由 curl 在本地解析主机名 | 本地 DNS 查询可能暴露目标域名 |
socks4a://proxy:port | 由 SOCKS4a 代理解析主机名 | 用于对照远程解析行为 |
socks5://proxy:port | 由 curl 在本地解析主机名,再把 IP 交给 SOCKS5 代理 | 本地 DNS 可能不在代理链路内 |
socks5h://proxy:port | 由 SOCKS5 代理解析主机名 | 适合验证远程解析路径 |
使用可解析的测试域名做对照,不要直接复制保留域名作为测试目标:
curl -v --proxy socks5://127.0.0.1:端口 https://你的可解析测试域名/curl -v --proxy socks5h://127.0.0.1:端口 https://你的可解析测试域名/
判读时看 -v 输出中关于主机名解析的提示:如果出现本地解析或先连接目标 IP,说明该模式由 curl 在本地完成解析;如果显示远程解析或将主机名交给 SOCKS 代理,说明使用了远程解析模式。返回 403 也不等于 DNS 失败:若详细输出已经出现 TLS 握手完成,至少说明连接和 TLS 建连已经发生,仍需单独判断 DNS。
第三步:按客户端选择修复方案
| 你使用的场景 | 优先修改位置 | 复测方式 |
|---|---|---|
| 浏览器 | 检查 Chrome 或 Firefox 的安全 DNS/DoH;避免浏览器 DoH、系统 DNS 和客户端 DNS 同时接管 | 清缓存后,用浏览器检测页和 curl 各测一次 |
| curl、Python 或脚本 | 优先使用远程解析模式;检查代理参数和环境变量是否被程序读取 | 比较 socks5 与 socks5h,查看详细日志 |
| Clash/Mihomo | 打开 DNS 模块;需要覆盖未遵守系统代理的应用时检查 TUN、DNS 劫持和虚拟网卡;再判断 fake-ip 或 redir-host | 浏览器、桌面应用和 TUN 外应用分别测试 |
| v2rayN | 检查远程 DNS、Bootstrap DNS、直连目标解析策略和代理目标解析策略;字段含义以当前内核和界面为准 | 查看核心日志,分别测试节点域名和目标域名 |
| Android 或 iOS | 检查客户端 DNS、系统私人 DNS/加密 DNS、应用独立代理和 IPv6;避免多个 VPN 或代理配置同时运行 | 切换 Wi-Fi 与移动网络各测一次 |
Clash/Mihomo 文档说明,DNS 配置中的 enable、enhanced-mode、fake-ip、redir-host 和 proxy-server-nameserver 作用不同;TUN 文档还说明,DNS 劫持会把匹配到的连接转交内部 DNS 模块,但 Windows/macOS 对发往局域网的 DNS 请求不能自动全部劫持,Android 开启私人 DNS 时也可能影响自动劫持。可参考 mihomo DNS 配置文档 和 mihomo TUN 文档。
v2rayN 官方 Wiki 将直连 DNS、远程 DNS、Bootstrap DNS、直连目标解析策略和代理目标解析策略分别说明;Xray 与 sing-box 的实际用途也可能不同。可参考 v2rayN 官方界面与 DNS 说明。
第四步:检查浏览器 DoH、环境变量与系统缓存
Chrome 官方说明,安全 DNS 默认可以处于自动模式;出现解析问题时,自动模式可能回到未加密解析。设置路径以当前界面为准,可在“设置→隐私和安全→安全→使用安全 DNS”检查,详见 Chrome 官方安全 DNS 说明。
Firefox 官方文档列出默认保护、增强保护、最大保护、自定义保护和关闭等设置;自定义提供商属于保护设置中的选项,不应与其他保护级别混写。详见 Mozilla 官方 DoH 说明。
- Windows:管理员命令提示符运行
ipconfig /flushdns。Microsoft 的 ipconfig 文档说明该命令用于显示或刷新 DNS 客户端缓存。 - macOS:可运行
sudo dscacheutil -flushcache,再运行sudo killall -HUP mDNSResponder。命令是否适用于当前系统,以本机终端帮助和系统版本为准;可参考 macOS dscacheutil 命令说明。 - Linux:使用 systemd-resolved 时运行
resolvectl flush-caches;该命令会清理服务维护的 DNS 资源记录缓存,详见 systemd resolvectl 文档。 - Chrome:清理系统缓存后,再关闭并重新打开浏览器;若只是浏览器异常,可检查浏览器安全 DNS是否独立于系统代理运行。
开发者还应检查代理环境变量。curl 支持 http_proxy、HTTPS_PROXY、ALL_PROXY 和 NO_PROXY 等变量;Windows PowerShell 可运行 Get-ChildItem Env: | Where-Object Name -match 'proxy',macOS/Linux 可运行 env | grep -i proxy。
Python Requests 安装 SOCKS 依赖后支持 SOCKS 代理;使用 socks5 时由客户端解析,使用 socks5h 时由代理服务器解析。Requests 也会读取标准代理环境变量,具体见 Requests 官方高级用法文档。
第五步:检查路由器、IPv6 与 DNS 污染
- 路由器强制 DNS:检查路由器是否启用了 DNS 重定向、家长控制、安全 DNS 或自定义劫持规则。然后让同一设备分别连接家用宽带和手机热点;只有某个网络出现本地 DNS 时,问题更可能在路由器或运营商侧。
- IPv6:分别检查 A 和 AAAA 查询,以及客户端 TUN 是否接管 IPv6。若 IPv4 已进入代理而 IPv6 仍直连,应修复 TUN 路由、客户端 IPv6 设置或应用的地址选择策略。
- DNS 污染:如果查询已经发出,但返回固定错误地址、异常记录或不同网络下结果明显不一致,先用同一随机域名对比多个解析器、A/AAAA/CNAME 和不同网络,不要直接把错误结果称为 DNS 泄漏。
- WebRTC:浏览器 WebRTC 暴露候选地址属于另一类问题,不是 DNS 查询本身;需要单独检查浏览器实时通信设置。
把 DNS 改成公共 DNS 只改变了“使用哪个解析器”,没有自动改变“请求通过哪条链路发送”。如果应用仍直接访问该 DNS,查询仍可能绕过代理;应先确认 DNS 接管、TUN、DoH 和路由器规则。
第六步:Windows 抓包与最终验收
一般用户先完成浏览器、curl 和真实应用三种测试即可;只有结果互相矛盾时,再使用抓包确认本机是否直接发出 DNS 请求。
- 以管理员身份打开 PowerShell 或命令提示符。
- 开始采集:
pktmon start --capture --file-name dns-check.etl。 - 在采集期间,只访问一个可复现的测试域名,完成浏览器或应用请求。
- 停止采集:
pktmon stop。 - 转换为 Wireshark 可读取的 pcapng:
pktmon etl2pcap dns-check.etl --out dns-check.pcapng。
Microsoft Learn 当前文档列出 pktmon start、pktmon stop 和 pktmon etl2pcap 的语法,并说明 Pktmon 可用于数据包捕获和事件收集,详见 pktmon start 文档、Pktmon 命令格式说明 和 pktmon etl2pcap 文档。
验收时重点观察:代理关闭和开启的结果是否可解释;浏览器、curl、实际应用是否一致;A 与 AAAA 是否都被纳入处理;抓包中是否出现本机直接向路由器或运营商 DNS 发出的请求。若使用 DoH,不能只搜索 UDP 53,还要检查对应的 HTTPS 连接。
常见误判与边界
如果在线检测显示的 DNS 服务器与代理节点地区不同,不能单独证明泄漏;代理服务端可能使用远端解析器、Anycast 或共享 DNS。若服务端解析位置没有客户端日志或服务端证据,本地设置无法证明它在哪里解析。
如果浏览器检测正常但 Python 或桌面应用异常,优先检查应用是否继承系统代理、是否读取 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY,以及代码是否使用了 socks5 而不是 socks5h。如果只有家用宽带出现问题,则对比手机热点,并检查路由器 DNS 重定向。
常见问题
代理能正常打开网页,为什么还可能 DNS 泄漏?
网页流量和域名解析可以走不同路径。系统代理可能只转发 HTTP/HTTPS,应用或浏览器仍可使用系统 DNS、独立 DoH、IPv6 或路由器提供的解析服务。
把 DNS 改成公共 DNS 能解决泄漏吗?
不一定。它只改变解析器,不一定改变 DNS 请求的传输路径。如果应用仍直接向该解析器发送查询,查询仍可能绕过代理。
curl 中 socks5:// 和 socks5h:// 有什么区别?
在 curl 中,socks5://由 curl 在本地解析主机名,再把 IP 交给代理;socks5h://由 SOCKS5 代理解析主机名。应通过 -v 输出、日志或抓包复核。
HTTP 代理会不会自动造成 DNS 泄漏?
不会因为使用 HTTP 代理就直接判定泄漏。普通 HTTP 请求通常把完整 URL 交给代理,HTTPS 通常通过 CONNECT 把主机名和端口交给代理;更常见的风险是应用绕过代理或另行解析。
为什么在线检测正常,但 Python 或桌面应用仍然泄漏?
浏览器可能单独使用 DoH,而应用没有继承系统代理或环境变量。应检查 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY、应用自身代理参数,以及 socks5 与 socks5h 的解析模式。
Clash/Mihomo 开启 TUN 后还要检查 DNS 劫持吗?
要检查。TUN、DNS 劫持和 DNS 模式分别负责流量接管、DNS 请求转交和解析结果处理;在 Windows、macOS 或 Android 的特定网络设置下,自动劫持可能存在边界。
DNS 泄漏和 DNS 污染、IPv6 泄漏、WebRTC 暴露是一回事吗?
不是。DNS 泄漏是查询走了不希望使用的解析器;DNS 污染是返回结果异常;IPv6 泄漏是 IPv6 流量绕过预期路径;WebRTC 暴露是浏览器实时通信候选地址问题,需要分别排查。
相关阅读
参考资料
- curl 官方手册:代理协议、CONNECT、SOCKS4、SOCKS5 与环境变量
- Requests 官方文档:代理、环境变量与 socks5h
- mihomo 官方文档:DNS 配置
- mihomo 官方文档:TUN 与 DNS 劫持
- v2rayN 官方 Wiki:界面与 DNS 设置说明
- Chrome 官方帮助:安全 DNS
- Mozilla 官方帮助:Firefox DoH 保护级别
- Microsoft Learn:ipconfig 命令
- macOS dscacheutil 与 mDNSResponder 清缓存命令说明
- Microsoft Learn:pktmon start
- Microsoft Learn:Pktmon 命令格式与停止采集
- Microsoft Learn:pktmon etl2pcap
