DNS 泄漏:流量如何绕过代理,以及如何在系统层面关闭 DNS 泄漏
前言:为什么代理明明没问题,你依然被人看得一清二楚
想象这样一个场景。你买了一个高质量的移动代理,配置好了指纹浏览器,在三个不同的服务上检查了 IP——显示的地址都是目标地区的移动运营商。你启动广告账户、养号、跑数据采集。几天后,你收到一封封号通知,理由是「可疑活动」。是不是很熟悉?这类故事最被低估的原因之一,就是 DNS 泄漏,也就是 DNS 请求绕过了代理。
矛盾之处在于,IP 地址确实被替换了。网站看到的流量来自移动运营商。但在每次连接之前,你的电脑都会悄悄问自己的运营商:「某某服务器在哪里?」而这个问题是直接发出去的,完全没走代理。结果,观察方就看到了两幅对不上的画面:连接来自某个地区的移动网络,而域名解析却通过另一个城市的家庭宽带运营商的递归解析器完成。对 2026 年的风控系统来说,这种不一致不是小事,而是最可靠的信号之一。
根据我们处理用户咨询的经验,很多「代理不能用、地理位置识别错误、账号无缘无故被封」的抱怨,深入排查后发现根本不是代理本身的问题。这是客户端的 DNS 层问题。而且,在开始工作前专门检查 DNS 的人仍然是少数——大多数人只检查 IP。
本指南将全面拆解这个话题。你将了解域名解析的运作方式,以及它在哪个环节绕过了代理。你会明白 HTTP 代理和 SOCKS 代理在 DNS 处理上的区别,为什么连接字符串里多一个字母就能决定成败,以及开启了加密 DNS 的浏览器如何制造出一类新的泄漏。我们会提供四种实用方法——诊断、客户端软件配置、浏览器与指纹浏览器、系统层面——每种方法都配有分步说明和检查清单。我们还会分析常见错误、带数据的案例,并回答一些复杂问题。
一个重要的边界说明:本文讨论的是 DNS 层。通过 WebRTC、浏览器指纹、时间特征和其他去匿名化渠道的泄漏是另外的话题,已在博客的其他文章中详细拆解。这里我们只聚焦一个但却是基础性的渠道,因为如果不理解它,其他所有配置都建立在沙滩之上。
基础知识:DNS 如何工作,什么是 DNS 泄漏
互联网的电话簿
每当浏览器或脚本想要连接一个网站时,它需要的不是域名,而是 IP 地址。域名是给人看的名字。地址是给网络看的坐标。把前者翻译成后者的服务叫做 DNS(域名系统)。最简单的类比就是电话簿:你知道名字,电话簿给你号码。只不过这本电话簿分布在成千上万台服务器上,响应时间以毫秒计。
域名解析在实际中是这样的:
- 应用程序调用系统函数(在 Unix 世界里通常是 getaddrinfo),把域名传给它。
- 操作系统检查本地缓存和 hosts 文件。
- 如果没有答案,操作系统的存根解析器(stub resolver)会把请求发到网络设置里配置的 DNS 服务器地址。通常是 DHCP 自动下发的运营商服务器,或者你手动指定的公共解析器。
- 运营商的递归解析器沿着根服务器、顶级域服务器和域名的权威服务器这条链路走一圈,找到答案并返回给你。
- 应用程序拿到 IP,然后才建立连接。
注意这个顺序。先 DNS,后连接。代理是干预连接的工具。至于它是否会干预 DNS——取决于代理类型、协议,以及应用程序具体如何使用它。
什么叫泄漏
DNS 泄漏是指应用程序的流量走了代理,但域名解析请求没有走。它们从你真实的网络接口直接发到了系统配置的解析器。结果是:你连接的网站看到的是代理 IP,但你的运营商和解析器所有者看到了你访问过的所有域名列表。而目标服务在特定条件下还能把连接来源和 DNS 请求来源进行比对。
为什么这对移动代理用户尤为重要?因为移动 IP 的全部价值就在于它的可信度。地址属于移动运营商,背后有成千上万的真实用户,它会变化,信誉良好。但真实的移动网络用户是通过同一运营商的 DNS 服务器解析域名的。如果你的流量从移动网络出去,而域名却通过另一个地区的固网运营商解析,你就不再像一个真实用户了。你像的是一个在用代理的人。事实也确实如此——而且是你自己说出去的。
看到你泄漏的三个角色
- 你的互联网运营商。它看到发往自己解析器的请求,知道你在访问哪些域名,即使内容本身走了代理。
- 解析器所有者。如果你配置了公共 DNS,那么你的完整域名列表和真实 IP 就会被它的运营方看到。
- 目标网站及其风控。它不会直接收到 DNS 请求,但有间接渠道:权威服务器的地理位置、EDNS 客户端子网机制、CDN 路由,以及专门为特定会话生成的测试域名。下一节会详细说明。
深入剖析:通过代理工作时 DNS 泄漏的解剖学
HTTP 代理:为什么通常不漏,但也有例外
通过 HTTP 代理工作时,浏览器向它发送的请求里域名是以文本形式出现的。对于未加密的 HTTP,这是请求第一行的完整 URL。对于 HTTPS,浏览器发送 CONNECT 命令,带上主机名和端口,代理自己解析这个名字并建立隧道。两种情况下,客户端都不需要知道目标服务器的 IP。解析由代理完成,使用它自己的解析器。如果是移动代理——则在调制解调器或手机那一侧完成,通过运营商的 DNS 服务器。这本来就该是这样。
那 HTTP 代理的泄漏从哪来?它们的来源是间接的:
- PAC 脚本。代理自动配置文件可能包含 dnsResolve 函数,它会本地解析域名来判断是否把请求发送给代理。决定是在本地 DNS 查询之后才做出的。
- 域名预解析。有些应用程序在连接前会检查主机可达性:先 ping、先解析,然后再走代理。使用 InetAddress 的 Java 应用、某些采集器、链接检查插件。
- 浏览器后台服务。页面预加载、DNS 预取、安全浏览检查和更新检查可能按自己的规则运行,并不总是遵守代理设置。
SOCKS:一个字母之差,干净会话还是泄漏
有趣的地方从这里开始。SOCKS4 原始版本只能向代理传递目标 IP 地址。这意味着客户端必须自己解析域名,在连接之前。泄漏就内建在协议里。SOCKS4a 扩展增加了传递主机名的能力。SOCKS5 支持三种目标地址类型:IPv4、IPv6 和域名。
看起来 SOCKS5 解决了问题。但协议支持域名并不意味着客户端会用它。很多库和程序默认本地解析域名,然后把现成的 IP 发给代理。协议允许这样做——泄漏只是发生得更早一步。
于是就出现了那个著名的字母 h。在 curl 和遵循其约定的库中,socks5:// 表示本地解析域名,而 socks5h:// 表示把主机名交给代理服务器远程解析。一个字母。区别在于:一边是干净会话,所有东西包括 DNS 都从运营商的移动网络出去;另一边是每个域名都先泄漏给你的运营商。
为什么代理服务器自己解析更好
这里有一个很多人忽略的不明显之处。不仅仅是隐私问题。当移动代理的远端解析域名时,DNS 响应会考虑运营商的所在地理位置。大型服务使用 CDN 和地理 DNS:同一个域名对不同客户端返回不同的 IP,离谁近就给谁。如果你的家庭宽带运营商解析,你会得到离你真实位置近的 CDN 节点地址。然后你通过另一个地区的移动代理连接这个节点。对服务来说这很奇怪:来自 A 地区移动网络的客户端居然连到了为 B 地区准备的节点。这就是检测 DNS 泄漏的间接渠道,完全不需要访问你的 DNS 请求。
EDNS 客户端子网:解析器如何分发你的子网
EDNS 客户端子网(ECS)机制的设计初衷是让公共解析器能向权威服务器传递客户端地址的一部分——IPv4 通常是前 24 位。这样 CDN 就知道真实用户来自哪里,返回最近的节点。这对速度有好处。但从泄漏角度看,这意味着当本地解析经过支持 ECS 的公共 DNS 时,目标域名的权威服务器会收到你真实连接的子网。不是完整地址,但足以判断运营商和城市。而连接随后又来自移动 IP。两个子网,两个运营商,一个用户。
加密 DNS:一类新的泄漏
从 2020 年代起,浏览器和操作系统大规模转向 DNS over HTTPS(DoH)和 DNS over TLS(DoT),到 2026 年还加入了 DNS over QUIC。初衷是好的:运营商不再看到你的请求。但对于通过代理工作的人来说,产生了一个副作用。开启了「安全 DNS」的浏览器用自己的客户端访问选定的 DoH 服务器,而这个流量远不总是遵循代理设置。也就是说,域名不是由移动运营商解析,而是由大型公共解析器解析,而且是从你的真实 IP 发出的。加密能防运营商,但防不了 DNS 侧和连接侧之间的不一致。
Encrypted Client Hello(ECH)又增加了一层复杂性。为了让它工作,浏览器需要在 DNS 中查询特殊的 HTTPS 记录。使用 ECH 的网站越多,浏览器发出的 DNS 请求就越多——如果 DNS 不走正确的路径,泄漏的机会也就越多。
IPv6 和 Happy Eyeballs
现代系统会同时查询 A 记录(IPv4)和 AAAA 记录(IPv6),并尝试连接响应更快的那个——这就是 Happy Eyeballs 算法。如果你的真实网络支持 IPv6,而代理只走 IPv4,一些应用程序就能通过 IPv6 直连,完全绕过代理。严格来说这不是 DNS 泄漏,而是连接泄漏,但触发它的正是带 AAAA 记录的 DNS 响应。所以在 DNS 卫生的语境下,IPv6 必须放在心里。
缓存和 hosts:来自过去的泄漏
操作系统会缓存 DNS 响应。如果你之前没走代理工作过,然后才开了代理,部分域名已经在缓存里,带着通过家庭解析器获得的地址。不会产生新请求,但连接会走向「家庭」CDN 节点。同理,hosts 文件:里面的记录会完全覆盖域名解析,代理对此一无所知。
方法一:诊断——如何亲手检测 DNS 泄漏
在配置任何东西之前,需要先看到问题。好消息是:检查 DNS 泄漏只需五分钟,而且应该变成每次工作会话前的固定仪式。
在线测试的原理
任何 DNS 泄漏检测服务的原理都一样。页面生成几个唯一子域名,形如「随机字符串.测试域名」,然后让浏览器解析它们,通常是通过加载不可见的图片或脚本。由于子域名是唯一的,它们肯定不在任何缓存里。请求必然到达测试域名的权威服务器,而该服务器属于服务提供商。它记录请求来自哪个 IP——这就是你使用的递归解析器的地址。然后页面展示两列:HTTP 连接的来源地址和解析器地址。如果连接来自移动运营商,而解析器属于家庭宽带运营商或公共 DNS 服务——就有泄漏。
重要的是要理解:任何网站都可以做同样的事。这个机制不需要特殊权限。大型平台的风控系统把类似技术作为会话风险评估的一部分。这不是阴谋论,而是标准工程实践。
分步检测流程
- 记录基线。关闭代理,打开 DNS 泄漏测试,记下显示的解析器。这是你的「家庭」指纹。你应该一眼就能认出来。
- 清除 DNS 缓存。Windows 上用 ipconfig /flushdns,macOS 上重启 mDNSResponder 服务,Linux 上取决于解析器(比如 systemd-resolved 用 resolvectl flush-caches)。重启浏览器——它有自己的缓存。
- 开启代理,用你实际工作的方式:通过指纹浏览器配置文件、扩展、系统设置或代码。
- 运行扩展测试,不是一次而是几十次检查。泄漏可能是部分的:十次请求有九次走代理,第十次直连。单次测试会漏掉。
- 对比。所有解析器都应该属于代理所使用的移动运营商,或者代理服务的基础设施。基线里一个地址都不应该出现。你没刻意选择的公共解析器也不应该出现。
- 单独检查 IPv6。如果测试显示任何不属于代理的 IPv6 地址——就是泄漏。
- 工作十分钟后再重复。有些后台进程会延迟启动。
不依赖第三方服务的检测:自建测试域名
对于运营账号农场或大规模数据采集的人来说,拥有自己的工具是明智的。方案是这样的:注册一个便宜的域名,在自己的 VPS 上为它搭建一个开启查询日志的权威 DNS 服务器。然后在任何项目中、任何会话启动时,访问形如「会话标识.你的域名」的唯一子域名。DNS 服务器日志里就会出现一条记录:请求了哪个子域名,来自哪个解析器 IP。把它和会话标识对比,立刻就能看出哪个会话、哪个配置文件、哪个工作进程泄漏了。这把一次性检查变成了持续监控。
底层检测:看网络
最诚实的方法是看网络接口上实际发出去了什么。在机器的物理接口上启动流量分析器(Wireshark 或 tcpdump),过滤 UDP 和 TCP 的 53 端口,以及 DoT 的 853 端口。然后通过代理工作五分钟。在理想世界里,过滤器应该是空的:所有域名都在代理侧解析,本地没有任何 DNS 数据包。如果有数据包,你立刻就能看到哪些域名、去了哪里。对于 DoH 过滤更复杂,因为它是普通的 443 端口 HTTPS,但线索是出现连向已知公共 DoH 提供商地址的连接,且不经过代理。
诊断检查清单
- 无代理时的基线已记录。
- 测试前已清除操作系统和浏览器缓存。
- 已运行几十次请求的扩展测试。
- 所有解析器都对应代理侧。
- 没有其他网络的 IPv6 地址。
- 工作十分钟后的重复测试已通过。
- 对关键项目:53 端口上的流量分析器显示零数据包。
方法二:正确配置客户端软件和代码
你找到了泄漏。现在需要找出应用程序究竟在哪里决定本地解析域名,并把它切换到远程解析。我们来分析投放和开发实践中常见的几种环境。
原则:主机名必须到达代理
规则只有一条,而且是通用的。代理应该从你这里拿到域名,而不是 IP。对 HTTP 代理来说这是自然而然发生的。对 SOCKS5 需要明确选择远程 DNS 模式。对不支持 a 扩展的 SOCKS4 来说这根本不可能——这种代理不适合干净工作。现代服务的移动代理同时支持 HTTP 和带远程解析的 SOCKS5,所以限制只在客户端这一侧。
curl 和命令行
对于 SOCKS5,永远使用带字母 h 的方案。正确的调用示例:
curl -x socks5h://user:pass@host:port https://example.com/没有字母 h,curl 会本地解析域名。这也适用于所有基于 libcurl 构建的工具。对于 HTTP 代理,在 -x 参数里用 http:// 方案就够了:域名会出现在 CONNECT 请求里。
Python:requests、httpx、aiohttp
在安装了 SOCKS 支持包的 requests 库里,规则相同:socks5:// 表示本地解析,socks5h:// 表示远程解析。这是采集器里最常见的错误:开发者从文档里复制了带 socks5 的示例,然后年复一年地带着 DNS 泄漏跑流量,甚至都没意识到。在 httpx 和 aiohttp 中,SOCKS 支持通过第三方传输层实现,远程解析模式需要查阅具体传输层的文档——有的参数叫 rdns,有的也用带 h 的方案。不要只看文档,要实际验证:用脚本访问自己的测试域名,看日志里请求从哪里来。
另一个陷阱是低层 socket 库,它们会猴子补丁标准 socket 模块,把所有流量包进 SOCKS。它们有远程解析开关,但默认往往是不开的。而且你代码或依赖里任何一次 socket.gethostbyname 调用都会绕过它,通过系统解析器解析域名。
Node.js 和无头浏览器
在 Node.js 生态中,SOCKS 代理通常会把主机名传给代理,但这取决于具体包和版本。对于 Puppeteer 和 Playwright,代理在浏览器启动层面设置,行为继承自 Chromium 引擎——关于它在 SOCKS5 上的特性,我们下一节讨论。如果你用移动代理的 HTTP 模式,问题就不存在了:Chromium 会发送带主机名的 CONNECT。
Go、Java 和其他语言
在 Go 中,标准包 golang.org/x/net/proxy 的 SOCKS5 会远程传递主机名,但前提是你直接使用它的 Dialer,而不是提前解析。在 Java 中,SOCKS 代理的系统属性是有效的,但很多 HTTP 客户端会创建预先解析的 InetSocketAddress 对象,这就造成了泄漏。解决办法是创建未解析的地址(类似 createUnresolved 的方法),并确保客户端支持传递主机名。对任何语言的通用建议:在代码和依赖中找到所有把域名变成 IP 的地方,确保这发生在与代理建立连接之后,而不是之前。
项目分步审计
- 在代码中找到所有代理连接字符串。检查方案:没有 h 的 socks5 是红旗。
- 找到所有显式的域名解析调用:gethostbyname、getaddrinfo、dns.lookup、InetAddress.getByName。每一个都是潜在泄漏。
- 检查依赖:可达性检查库、health-check、带预 ping 的重试。
- 用自建测试域名运行项目,每个工作进程用唯一子域名。DNS 服务器日志会告诉你谁在泄漏。
- 添加自动化测试:DNS 检查未确认解析器属于代理侧之前,会话不算有效。
- 把结果记录在项目文档里:哪个库、哪个版本、哪种模式。
开发者检查清单
- 所有 SOCKS5 连接都使用远程解析。
- 连接前没有预解析。
- 库不是按文档验证的,而是按测试域名日志验证的。
- 会话启动时内置自动 DNS 检查。
- 对于 HTTP 代理模式,已验证使用的是 CONNECT 而非替换成 IP。
方法三:浏览器和指纹浏览器无 DNS 泄漏
移动代理的大部分用户不是在代码里工作,而是在浏览器里:广告账户、社交媒体、电商平台、多账号运营。这里有各自的规则,而且不同引擎不一样。
Firefox 及其衍生版本
Firefox 历来提供最透明的控制。about:config 里的关键参数是 network.proxy.socks_remote_dns。值为 true 时域名传给 SOCKS 代理远程解析。为 false 时本地解析。在很多旧版本和配置文件中它是关闭的。第二个参数是 network.trr.mode,控制加密 DNS:值 5 完全关闭它,这对通过代理工作更可取,否则浏览器可能用自己的客户端访问 DoH 服务器。第三块是预加载:network.dns.disablePrefetch 设为 true,network.predictor.enabled 设为 false,关闭页面上链接的投机性域名解析,否则它可能在真正点击之前就绕过代理。基于 Firefox 引擎的指纹浏览器通常会正确设置这些参数,但每次更新后都应该检查。
Chrome、Chromium 及其衍生的指纹浏览器
Chromium 的情况更复杂。通过 HTTP 代理工作时,它发送带域名的 CONNECT——没有泄漏。但通过启动标志使用 SOCKS5 代理时,引擎在某些配置下会本地解析域名,而界面里没有标准的「远程 DNS」设置。一个已知的工程技巧是使用 --host-resolver-rules 标志,制定一条规则把所有域名映射为「未找到」,但排除代理自身的地址。结果本地解析器什么都解析不了,浏览器只能把域名传给代理。看起来像权宜之计,但效果可靠。第二个要点是隐私设置里的安全 DNS:开启时 Chromium 会使用 DoH 访问选定的提供商,而这个流量并不总是遵循代理。通过移动代理工作时应该关闭它,或者用测试确认它能被正确隧道。第三点是页面预加载:性能设置里有一个预加载选项,它会为尚未点击的链接发起 DNS 请求。
指纹浏览器应该具备什么
好的指纹浏览器会替你处理所有这些琐事。但实现质量差别很大。选择和每次更新后需要检查的要点:
- SOCKS5 的远程 DNS 模式默认为每个配置文件开启,而不是全局开启。
- 配置文件之间的 DNS 隔离。已解析域名的缓存不应共享:否则一个地区的移动代理配置文件会拿到另一个地区代理配置文件缓存的 IP。
- 关闭或可隧道的加密 DNS。直接问客服:通过代理工作时内置 DoH 行为如何。
- 关闭预取。投机性解析不应存在于伪装成普通移动用户的配置文件里。
- 内置检查:配置文件启动时的 DNS 泄漏检测,或至少提供便捷的测试入口。
- 代理断开时的行为。代理不可用时浏览器怎么做:阻止连接还是直连?后者不仅对 DNS 是灾难。
代理扩展:薄冰
切换代理的浏览器扩展通过浏览器 API 工作。它们能设置连接的代理,但对 DNS 的控制受限于引擎能力。如果引擎本身在特定配置下不为 SOCKS5 使用远程 DNS,扩展无法强制它这样做。而且扩展不管理浏览器的后台服务。所以扩展对移动代理的 HTTP 模式来说是可以接受的方案,也适合快速检查,但不适合严肃处理敏感账号。
配置文件分步设置
- 创建配置文件并填入移动代理。如果指纹浏览器不能保证 SOCKS5 的远程 DNS,优先选择 HTTP 模式。
- 在引擎或配置文件设置里关闭加密 DNS。
- 关闭页面预加载和 DNS 预取。
- 如果是 Firefox 类引擎——手动检查 socks_remote_dns。
- 启动配置文件,清除缓存,运行扩展 DNS 泄漏测试。
- 浏览几个带活跃分析的网站,再重复测试:有没有出现新的解析器。
- 把结果保存为该配置文件的基准。
方法四:系统层面和基础设施——强制关闭泄漏
前面所有方法都基于信任:我们配置应用程序,指望它行为正确。工程思维不同:让泄漏在技术上不可能发生。即使应用程序试图直接发送 DNS 请求,它也不应该发出去。
「除代理外一切禁止」的原则
在工作机器或农场的服务器上配置防火墙,阻止所有进程发往 53 端口(UDP 和 TCP)和 853 端口的出站流量,但明确允许的除外。Windows 里是防火墙的出站规则,Linux 里是 nftables 或 iptables,macOS 里是 pf。意义在于:如果浏览器或脚本尝试本地解析域名,它会得到一个错误,而不是悄无声息的泄漏。错误是立刻可见的——你会看到并修复应用配置。悄无声息的泄漏可能存活数月。
DoH 的微妙之处:它走 443 端口,不能整体封锁。解决方案不是封端口,而是为那些只能通过代理的进程封锁已知公共 DoH 解析器的地址。这需要维护列表,但列表很少变化。
通过容器和网络命名空间隔离
对于 Linux 上的开发者和农场主来说,最强大的工具是网络命名空间(network namespaces)和容器。思路:每个工作进程、每个浏览器配置文件或一组配置文件生活在自己的网络空间里,里面对互联网完全没有任何默认路由。唯一的出口是代理地址。应用程序无论想做什么——解析域名、走 IPv6、开直连——它物理上没有路由。这是大规模保证无 DNS 泄漏最可靠的方法。在 Docker 里,通过没有外部网关的自定义网络加上只允许访问代理地址来实现。另外,容器解析器配置里可以指定一个不可达的地址,让任何本地解析尝试立刻失败,而不是挂到超时。
系统层面的 IPv6
如果你的移动代理走 IPv4,而机器有 IPv6 连接,最简单可靠的方案是禁用代理配置文件所在接口的 IPv6,或者用防火墙禁止 IPv6 出站。是的,这很粗暴。但它排除了整整一类问题:DNS 响应里的 AAAA 记录把连接引向直连。
系统解析器及其特性
现代操作系统有多层解析器。Windows 11 在系统层面支持 DoH,如果为你的网卡开启了,所有本地解析都会走选定的 DoH 服务器。对于使用代理的工作机器,需要意识到这一点:开启的系统 DoH 改变了泄漏的画面,但没有消除它。Android 使用 Private DNS 功能——对在移动设备或模拟器上用代理的人来说情况类似。在 systemd-resolved 的 Linux 上,值得检查每个接口配置了哪些 DNS 服务器,因为解析器能根据域名后缀在接口之间路由请求,这会制造意外的路径。
监控作为流程
在基础设施层面,DNS 泄漏检查从一次性变成持续性。值得引入的:
- 记录被防火墙阻止的 DNS 尝试。日志里的每一条都是试图本地解析的应用程序。这是你的待修复清单。
- 自建测试域名,每次会话用唯一子域名,出现异常解析器时自动告警。
- 定期抓取物理接口 53 端口网络流量——每天自动一次,计数非零时告警。
- 每次更新后检查浏览器、指纹浏览器、库。更新是回归的主要来源:开发者改默认值、开启新的预加载功能、添加加密 DNS。
系统层面检查清单
- 工作进程的出站 53 和 853 端口流量已封锁。
- 同一批进程的已知公共 DoH 地址已封锁。
- 工作接口的 IPv6 已关闭或封锁。
- 关键工作进程隔离在没有直连路由的网络空间里。
- 防火墙的 DNS 日志被收集和查看。
- 测试域名和告警已配置。
常见错误:不该做的事
错误 1:只检查 IP
最普遍的。看到 IP 检查页面显示移动运营商地址,就认为任务完成。但 IP 检查只回答「连接从哪里来」,不回答「DNS 请求从哪里来」。这是两个不同的问题,有不同的答案。
错误 2:配置公共 DNS 就放心了
逻辑可以理解:既然运营商看到我的请求,那就指定公共解析器。但对于通过代理工作,这不是解决方案,而是用一种泄漏替换另一种。请求仍然从你的真实 IP 发出,只是换了一个观察者。而且公共解析器积极使用 ECS,把你的子网传给权威服务器。DNS 侧和连接侧的不一致依然存在。
错误 3:使用不带远程 DNS 的 SOCKS5
代码里写 socks5 而不是 socks5h,浏览器里关掉了 socks_remote_dns,指纹浏览器默认本地解析。成千上万的项目带着这个错误活了多年。
错误 4:认为加密 DNS 能解决问题
DoH 保护请求内容不被运营商看到。但在通过代理工作时,它制造了一条不走代理的独立通道。加密不等于正确路由。
错误 5:忽视预加载和后台服务
浏览器解析你还没打开的链接域名。杀毒软件检查 URL。更新器查找更新服务器。这些都是可能绕道的 DNS 请求。单次测试抓不到这些东西。
错误 6:配置文件之间共享 DNS 缓存
如果两个不同地区的代理配置文件共享缓存,第二个配置文件会连接到为第一个地区选择的 CDN 节点。配置文件隔离必须包括 DNS。
错误 7:更新后不测试
新版本浏览器默认开启了安全 DNS。更新后的库改变了 SOCKS 行为。指纹浏览器更新重置了引擎设置。这些都是真实场景,只有重复检查才能发现。
错误 8:允许代理不可用时直连
「如果代理不响应就直连」这类设置会把任何故障变成完整会话去匿名化,从 DNS 开始。正确的行为是封锁连接直到代理恢复。
错误 9:为了「提速」手动解析
有些采集器解析一次域名然后就按 IP 访问,以节省 DNS。除了请求本身泄漏,它们还会拿到地理 DNS 为其真实地区选择的 IP,然后通过移动代理把流量发到「别人的」CDN 节点。省下的几毫秒换来的是不一致的配置文件。
工具和资源
在线泄漏测试
DNS 泄漏检测服务分为基础版和扩展版。基础版做一两次查询,适合快速判断。扩展版生成几十个唯一子域名,能发现部分泄漏。工作用的话选那些不仅显示解析器 IP,还显示其归属的:组织、自治系统、国家。好的测试还会单独显示 IPv4 和 IPv6,并能检查重复请求时的行为。
流量分析器
Wireshark——图形化分析器,支持 dns 或 udp.port == 53 这样的过滤器。tcpdump——服务器和 Linux 机器上的命令行替代品。两者都能让你看到真相:网络接口上实际发出了什么。对于 DoH,还要看连向公共解析器地址的 TLS 连接。
自建权威 DNS
用于大规模监控:任何带查询日志的轻量 DNS 服务器(CoreDNS、权威模式的 Unbound、BIND、Go 或 Python 写的紧凑服务器)加上自己的域名。成本极低,换来的是对所有工作进程和配置文件的持续监督。
命令行工具
dig 和 nslookup 显示系统访问哪个解析器以及它返回什么。Linux 上 systemd-resolved 的 resolvectl 显示各接口的 DNS 配置。curl 加详细输出标志显示它是把域名传给代理还是自己解析。Windows 上 ipconfig /displaydns 显示缓存内容,PowerShell 的 Get-DnsClientServerAddress 显示各网卡配置的服务器。
防火墙
Windows 内置防火墙支持按程序设置规则,Linux 用 nftables 和 iptables,macOS 用 pf。按应用程序管理规则有图形化工具。关键要求是能为特定进程封锁端口并记录阻止日志。
容器化
Docker 和 Podman 的自定义网络、通过 ip netns 的 Linux 网络命名空间,以及面向浏览器农场的配置文件编排器,支持配置文件级别的网络隔离。它们把「只有通过代理」这条规则从设置变成架构保证。
代理服务侧的能力
注意移动代理提供商提供什么:支持远程域名解析的 SOCKS5、正确处理 CONNECT 的 HTTP 模式、运营商侧 DNS 的稳定性、基础设施侧没有 DNS 响应篡改。向客服确认远程解析时域名通过哪些解析器——正确答案是:通过调制解调器所连接的移动运营商的解析器。
案例和结果
案例 1:广告账号农场和看不见的封号原因
一个投放团队通过流行的指纹浏览器在移动代理上运营约 120 个广告账号。账号平均存活 9–12 天就被封,而表面上配置无可挑剔:目标地区的移动 IP、精细的指纹、养号。审计发现,在一次指纹浏览器更新后,引擎里开启了加密 DNS,所有配置文件都通过同一个公共 DoH 解析器从办公室真实 IP 解析域名。120 个来自不同城市的「独立」用户从同一个点解析域名。关闭 DoH、开启远程 DNS 并用防火墙封锁 53 端口后,账号平均存活时间增长到 30 天以上,第一周的早期封号比例下降约三分之二。修复成本——一个专家两小时的工作。
案例 2:电商平台采集器和奇怪的地区价格
开发者通过不同城市的移动代理采集大型电商平台的价格。数据与这些地区真实用户看到的不一致:部分价格和库存对应的是完全不同的城市。原因出在连接字符串:requests 库用了不带 h 的 socks5 方案。域名在开发者所在城市本地解析,电商平台的地理 DNS 返回了他所在地区的节点,然后通过另一个城市的移动代理发来的请求到达了「别人的」节点,该节点按自己的逻辑返回地区结果。改一个字母并添加每个工作进程启动时的自动 DNS 检查后,数据恢复了正确性。副作用:平台返回验证码的请求比例下降了——会话变得更一致。
案例 3:面向地区受众的广告测试
一家营销机构通过移动代理和 SOCKS5 连接的 Chromium 浏览器检查广告和落地页在不同地区用户面前的展示效果。部分检查显示了错误地区的内容。在机构自建测试域名的日志里,解析器属于办公室的宽带运营商。切换到同样移动代理的 HTTP 模式(Chromium 通过 CONNECT 传递域名)并关闭页面预加载后,差异消失了。额外的好处——稳定的检查结果免去了重复运行,为团队在定期审计中节省了约 15% 的时间。
案例 4:社交媒体多账号和共享缓存
几十个社交媒体账号的运营者注意到,同一天工作的账号开始成组被封。排查发现 DNS 层有两个因素:指纹浏览器在配置文件之间使用共享 DNS 缓存,部分配置文件使用不带远程解析的 SOCKS5。结果,不同地区代理的配置文件连接到相同的 CDN 节点,其中一部分还从同一个真实 IP 解析域名。开启配置文件间缓存隔离并把所有连接切换到远程 DNS 后,成组封号停止了;接下来两个月,账号损失回到精细手工操作的水平。
案例的共同结论
四个故事里代理都是好的。问题出在客户端,代价是数周的工作、预算和账号。每次修复都只需几小时。这种比例正是 DNS 泄漏的典型特征:没有专门检查就看不见问题,但只要知道往哪看,解决起来很简单。
FAQ:关于 DNS 泄漏的复杂问题
如果网站收不到我的 DNS 请求,它怎么知道泄漏?
三条间接路径。第一——唯一测试子域名:网站可以迫使你的浏览器解析它自己控制的域名,然后看请求来自哪个解析器。第二——地理 DNS 和 CDN:如果你连到了为另一个地区准备的节点,这个与 IP 的不一致在基础设施侧就能看到。第三——EDNS 客户端子网:公共解析器把客户端子网传给权威服务器,而它与连接的子网不匹配。这些路径都不需要访问你的运营商。
移动代理通过运营商解析域名。这是好是坏?
对可信度来说完美。真实的移动网络用户通过运营商解析器解析域名,他的连接也来自同一运营商的地址。当你的代理做同样的事时,DNS 侧和连接侧属于同一个网络。这正是你在测试中应该看到的:运营商解析器、运营商 IP、同一个地区。
从 DNS 角度看,移动代理的 HTTP 模式比 SOCKS5 好在哪里?
好在 HTTP 模式下主机名按协议定义传给代理——HTTPS 在 CONNECT 里,HTTP 在 URL 里。客户端不可能意外本地解析域名,除了 PAC 脚本这类特殊情况。在 SOCKS5 里远程解析是客户端必须明确选择的选项,而很多客户端默认不这么做。如果你不确定特定浏览器或库的行为,HTTP 模式更安全。SOCKS5 对非 HTTP 协议更方便,但需要控制。
仅仅在浏览器里关闭安全 DNS 就够了吗?
不够。这只关闭了一条通道——浏览器的 DoH。仍然存在 SOCKS5 的本地解析、预加载、后台服务、操作系统里的系统 DoH 和 IPv6。关闭安全 DNS 是必要但不充分的步骤。只有扩展测试确认,最好再加上系统层面的直连 DNS 封锁,才算充分。
如果测试里出现既不属于我也不属于运营商的解析器怎么办?
沿着链条排查。先按 IP 确定组织:如果是公共 DNS 服务,去找浏览器或系统里开启的 DoH。如果是未知主机,可能代理基础设施使用自己的解析器而非运营商的——向提供商确认。如果是你的运营商,但不是基线里看到的那个解析器——可能是 IPv6 或另一个网卡。每个意外解析器都有解释,必须找到它,而不是忽视。
DNS 泄漏会影响通过代理工作的速度吗?
会,而且往往是出乎意料的方向。本地解析时,地理 DNS 选择你真实位置附近的 CDN 节点,然后流量通过另一个地区的移动网络到达这个节点——路径比最优的长。远程解析时,节点选在代理出口附近,从代理到服务器的路径更短。所以正确的 DNS 设置通常不会变慢,在某些情况下还会加快加载。
如何在无浏览器的自动化场景中测试 DNS 泄漏?
最可靠的方法是自建测试域名。每个工作进程启动时,脚本通过代理访问唯一子域名,你的权威 DNS 服务器记录请求来自哪个解析器。脚本然后通过 API 读取日志,把解析器地址与预期的运营商范围比较。如果不匹配,会话不启动。这把检查从手动变成契约:工作进程在证明 DNS 干净之前无权工作。
随着 ECH 和加密 DNS 在 2026 年的普及,情况会怎样变化?
趋势是「DNS 变得更重要」。ECH 依赖 HTTPS 类型的 DNS 记录,浏览器默认开启加密 DNS,操作系统添加系统 DoH 和 DoQ。对普通用户来说这是隐私加分。对通过代理工作的人来说,这意味着更多 DNS 流量、系统内更多独立的 DNS 客户端,以及更多请求可能绕过代理的点。而风控系统越来越积极地利用 DNS 侧和连接侧之间的一致性作为信号。结论:DNS 操作的纪律从「最好做」变成「必须做」。
能信任声称防 DNS 泄漏的指纹浏览器吗?
信任——可以,检查——必须。营销宣传不能抵消更新后的回归、引擎之间的差异和你代理配置的特殊性。每个配置文件创建后和每次浏览器更新后都要检查。一次扩展测试只需一分钟,而恢复烧掉的农场需要数周。
结语:DNS 是干净会话的基础
我们来总结一下。代理改变连接来源的地址,但不保证域名解析走同一条路。DNS 请求在连接之前执行,正是这个间隙里诞生了 DNS 泄漏。对移动代理用户来说这尤其关键:移动 IP 的全部价值在于它像一个真实用户,而真实用户通过自己的运营商解析域名。DNS 侧和连接侧的不一致暴露代理使用,比其他许多特征更可靠。
我们分析了 DNS 在不同场景下如何泄漏:不带远程解析的 SOCKS、浏览器和系统里的加密 DNS、预加载、共享缓存、IPv6、PAC 脚本和代码里的预解析。我们给出了四种协同工作的方法:带基线和扩展测试的诊断、客户端和库的正确配置、浏览器和指纹浏览器的设置,最后是防火墙和网络隔离层面的强制保护。每种方法单独关闭一部分问题。合在一起——让泄漏在技术上不可能发生。
你的下一步
- 今天:记录无代理时的基线,然后在每个工作配置文件、每个脚本里运行扩展 DNS 泄漏测试。记录结果。
- 本周:检查代码里所有不带 h 的 socks5 连接字符串,关闭浏览器里的加密 DNS 和预加载,确认配置文件之间的缓存隔离。
- 本月:在系统层面为工作进程封锁直连 DNS,禁用或封锁工作接口的 IPv6,搭建带日志的自建测试域名。
- 持续:每次更新浏览器、指纹浏览器和库后重复检查。把它变成像检查 IP 一样的仪式。
好的移动代理给你可信的地址和可信的运营商解析器。你的任务是不要在最后一米——自己的系统内部——丢掉这个优势。把 DNS 一次配置正确,让检查成为习惯,整整一类无法解释的封号就会从你的实践中消失。你读完这篇指南,不就是为了这个吗?