你的设备往往同时持有 IPv4 和 IPv6 两个地址。本文讲清楚网站最终看到的是哪一个、背后的两套机制,以及为什么同一台设备每次访问的结果都可能不一样。
打开 BrowserInsight 的 IP 情报工具,你常常会同时看到两个地址:一个 IPv4 地址,比如 198.51.100.20,还有一个 IPv6 地址,比如 2001:db8:85a3::8a2e:370:7334。有时候这两个地址会定位到同一座城市,有时候不会。而且如果你明天再查一次,某个网站今天记录的是你的 IPv4 地址,明天可能就变成了 IPv6——设备没换,网络没换,什么都没动。这不是故障,而是你的操作系统和浏览器每次建立连接时都要各自做出的两个决定所留下的可见结果,而这两个决定几乎从不被人看见。
核心要点
- 如今相当一部分家庭和移动网络的连接都是双栈(dual-stack)——你的设备同时持有一个有效的 IPv4 地址和一个有效的 IPv6 地址,网站最终记录到哪一个,两者皆有可能。
- 决定用哪个地址的是两套完全独立、运行在不同层面的机制:操作系统会针对每个目的地挑选一个源地址(RFC 6724),而浏览器的连接逻辑则会让两族协议同时"赛跑",谁先响应就用谁——这就是 Happy Eyeballs v2(RFC 8305)。
- 哪一族协议"获胜",只是那一次连接尝试的结果,不是你设置的偏好——同一台设备完全可能这次显示为 IPv4,下次显示为 IPv6。
- 由于商业地理位置数据库对 IPv6 地址段的覆盖比 IPv4 稀疏得多,你的两个地址有可能定位到不同的城市,甚至不同的国家。
- 如果 VPN 或代理只覆盖了其中一族协议,另一族就会走它平常未被隧道保护的路径——这是一个真实的泄露,不是无关紧要的小差异。具体可参见 WebRTC 泄露防护 和 DNS 泄露防护 这两条以同样方式出问题的泄露路径。
为什么你会同时拥有两个地址
IPv4 和 IPv6 是两套并行运作的独立寻址体系,后者并不是取代前者的"新版本"。IPv4 大约 43 亿个地址耗尽的速度超出了互联网早期设计者的预期,于是 IPv6 被设计出更庞大得多的地址空间,并采取逐步推广的方式——这也意味着两套体系要共存长达数十年。如今很多家庭和移动网络都是双栈的:路由器或运营商会同时给你的设备分配一个可用的 IPv4 地址和一个可用的 IPv6 地址。你的设备并不是在后台悄悄二选一,它其实一直同时握有这两个地址,随时可用。
不过并不是每个网络都已经走到这一步。IPv6 的部署程度在不同国家、不同运营商之间仍然差别很大,而一条没有拿到 IPv6 的连接,本来就只有一个公网地址可以拿出来。如果查询工具只报告了一个 IPv4 地址,那是你的运营商还没铺开 IPv6,不是工具出了问题——在你的宽带或手机套餐把 IPv6 打开之前,下面所有关于"网站看到的是哪一个地址"的讨论,对你其实都还用不上。
这只是背景设定。真正决定某个特定网站会看到哪一个地址的,是两个由不同软件、在不同时刻做出的独立决定。
决定一:操作系统为每个目的地挑选源地址
在任何连接尝试发生之前,你的操作系统网络栈首先要决定:面对某个特定目的地,该用你本地的哪一个地址——一台设备的同一张网卡上,常常同时挂着好几个 IPv4 和 IPv6 地址。这就是默认地址选择机制,在 RFC 6724 中被标准化,它执行一套固定规则:优先匹配作用域、优先选择与目的地址共享前缀位数最多的地址、在临时 IPv6 地址和永久地址都可选时优先选临时地址,此外还有更多细则作为决胜规则。这些规则完全不问你更想用哪种协议——它们只关心,给定目的地和你网卡当前持有的地址,哪一个源地址最合适。
决定二:浏览器让两族协议赛跑,谁先到用谁
选定源地址并不能决定到底是哪一族协议——IPv4 还是 IPv6——真正把连接送到一个双栈网站。这是另一个更晚发生的独立决定,由浏览器(或它调用的操作系统网络库)里的连接逻辑做出,时间点是在解析器同时返回了这个域名的 IPv4 地址和 IPv6 地址之后。早期的实现是先试一族协议,等它失败或超时才回退到另一族——这就让本来就有问题或偏慢的 IPv6 路径,真的成了页面加载明显变慢的一个原因。现在的解决方案是 Happy Eyeballs v2,规范于 RFC 8305:浏览器先对 IPv6 地址发起连接尝试,等待一小段时间(RFC 8305 建议约 250 毫秒),如果这段时间内 IPv6 还没成功,就同时发起 IPv4 尝试——两族协议并行进行,最终用先完成握手的那一个来承载连接,落败的一方直接被丢弃。
把这两套机制放在一起,"网站看到的到底是哪个地址"这个问题的答案就是:**由操作系统为这次连接选出的源地址,加上这次赛跑中获胜的那一族协议。**这两个决定都不是你一次性设置好就完事的东西,而是在每一次新连接中重新独立运行一遍。
而且,浏览器端根本没有办法观察这场"赛跑"。浏览器的网络信息 API(navigator.connection)向页面报告的是你连接的大致类型和估计速度,完全不会说明某次请求实际用了哪一族协议。这个信息只存在于接收端,这也正是为什么像 IP 情报 这样的工具必须去问服务器"你看到了什么",而不能从浏览器里直接读出来。
影响一:同一台设备今天是 IPv4,明天可能是 IPv6
由于这场赛跑是逐次连接重新进行的,结果又依赖于一些短暂的条件——DNS 响应时间、网络拥塞情况、哪个解析器先回应——所以同一台笔记本电脑、同一个 Wi-Fi 网络,完全可能这次加载页面时被记录为 IPv4 访客,下次加载就变成 IPv6 访客。不过对频率要有个实际的预期:在一条状态良好的双栈连接上,IPv6 通常是赢了之后一直赢,所以你不会分分钟看到它来回切换。真正会让结果翻转的,往往是底下有什么条件变了——IPv6 路径拥塞或劣化、换了一个解析器来应答、某个网站只有部分域名支持 IPv6,或者你换了网络。如果你正在琢磨为什么登录记录、限流规则或白名单规则表现得忽好忽坏,"这次赛跑挑中了哪一族协议"往往就是那个被忽略的变量,而不是哪里坏了。
影响二:你的两个地址可能定位到不同地方
IPv4 地址空间已经被商业地理位置数据库分配和标注了几十年;相比之下 IPv6 地址空间还很新,覆盖也稀疏得多,因为大量地址块是最近才分配出去的,而且很多运营商把它路由到数据库尚未完全摸清的基础设施上。实际的结果就是,你的 IPv4 和 IPv6 地址可能定位到不同的城市——有时甚至不同的国家——尽管这两个地址确确实实来自同一个连接。这不是你这边的泄露或错误,而是两套地址空间被绘制地图的完整程度不同所致。IP 地理位置定位 完整讲解了这些数据库和信号背后的机制;这里只是同一个连接的两次查询给出不同结果的这一种特殊情况。
影响三:只覆盖一族协议的隧道会泄露另一族
这是真正值得你去检查的一点。有些 VPN 客户端和代理配置只拦截 IPv4 流量——要么是刻意如此设计,要么是 IPv6 支持来得很晚甚至根本没做。这种情况下,你的 IPv4 流量会按预期走隧道,但你设备的 IPv6 地址依然在线,并且在任何支持 IPv6 的双栈网站上仍会赢下 Happy Eyeballs 的赛跑,把流量从你真实的、未被隧道保护的连接发出去。于是同一次页面加载,网站看到的是你 VPN 的 IPv4 出口地址,也看到了你真实的 IPv6 地址。这是一次实实在在的 IPv6 泄露,绝非无关紧要的小瑕疵,而且和其他破坏隧道保护的泄露路径属于同一类问题:WebRTC 泄露防护 讲的是 ICE 候选地址收集在媒体连接这一层做的同样的事,DNS 泄露防护 讲的是未加密的解析器查询如何完全绕开隧道。只检查 IPv4 地址有没有变化的泄露测试,完全可能漏掉这一点——它必须同时检查两族协议才行。
影响四:CGNAT 只是 IPv4 的问题
运营商级 NAT(CGNAT)——即 ISP 让成百上千个用户共用一个公网 IPv4 地址——存在的目的正是为了拉长日渐紧缺的 IPv4 供给。IPv6 的地址空间足够庞大,运营商可以直接给每个用户分配专属地址段,所以你的 IPv6 地址通常不会和任何人共享。这一点的影响是双向的。在 IPv4 一侧,和陌生人共用一个地址意味着同一 CGNAT 池里的一个坏行为者,就可能连累整个共享地址被标记,这正是 明明没用 VPN,为什么还被判定为 VPN 一文所讲机制的核心;而你的 IPv6 地址因为不共享,并不会带来这种特定风险。但反过来看,一个不共享的 IPv6 地址,也是一个稍微更精准地指向你个人的标识,没有其他用户的流量混在一起来模糊这个画面。(地址随时间变化背后的租约/轮换机制,为什么你的 IP 地址总在变 一文有完整讲解——这里只谈两族协议在"是否共享"上的差异。)
你现在就可以检查的事
打开 IP 情报,看看它报告的两个地址:
- **它们定位到的是不是同一个地方?**如果不是,那多半是 IPv6 数据库覆盖较薄弱在起作用,而不是出了错——原因可参见 IP 地理位置定位。
- **如果你正在使用 VPN 或代理,它显示的是不是"隧道的 IPv4 出口地址"加上"未走隧道的 IPv6 地址"?**如果你真实的 IPv6 地址和一个走了隧道的 IPv4 地址同时出现,说明你的隧道没有覆盖 IPv6,你正在每一个双栈网站上通过它泄露。
- **多刷新几次页面。**在一条正常工作的双栈连接上,结果通常是稳定不变的,因为 IPv6 会一直赢下赛跑——结果不变是正常现象,并不说明背后没有在赛跑。而如果它在其他条件都不变的情况下确实来回变化,那就是条件波动让 Happy Eyeballs 每次跑出的结果不同——同样是预期行为,不是故障。
这篇文章和站内其他 IP 主题文章的边界
这个话题很容易和站内另外三篇讲相邻机制的文章混在一起,所以在这里把边界说清楚:IPv6 隐私扩展 讲的是你 IPv6 地址中会随时间轮换的临时后缀,发生在同一个网络内;为什么你的 IP 地址总在变 讲的是 DHCP 租约和 CGNAT 如何随时间重新分配你的地址;IP 地理位置定位 讲的是任意一个地址如何映射到一个地理位置。这篇文章讲的既不是轮换也不是定位——而是在某一次连接中,你同时有效的两个地址里,服务器实际观察到的是哪一个,以及这个选择为什么轮不到你来做。
常见问题
工具只显示了一个地址,是不是坏了?
几乎可以肯定不是。最常见的原因是你的宽带运营商或手机运营商还没在你这条线路上部署 IPv6,所以确实只有一个公网地址可报——IPv6 的落地程度在不同国家和不同运营商之间差别仍然很大。另一种少见的相反情况是:你在一个纯 IPv6 网络里,通过转换网关访问 IPv4 网站,此时网站记录到的那个 IPv4 地址属于运营商的网关,而不属于你。无论哪一种,只有一个地址就意味着没有赛跑可跑。
为什么网站有时候显示的国家不对?
如果具体是你的 IPv6 地址被定位错了,IPv6 地址空间的数据库覆盖较薄弱是一个常见原因——完整情况(包括 IPv4 一侧的原因)可参见 IP 地理位置定位。
我能强制浏览器只用 IPv4 或只用 IPv6 吗?
大多数操作系统允许你在网卡层面禁用其中一族协议,这样它就完全退出了 Happy Eyeballs 的赛跑。不过这是个比较粗暴的办法——它会影响这张网卡上的所有连接,而不只是你想排查的那一个;而且禁用 IPv6 并不会让你更私密,只是让你少了两个地址中的一个而已。
同时拥有 IPv4 和 IPv6 地址是隐私风险吗?
本身不算。它只是意味着需要检查的地址从一个变成了两个,尤其是在确认 VPN 或代理是否完整覆盖了你的流量时——正如上文所说,一个被落在隧道外的 IPv6 地址就是一次真实的泄露。
Happy Eyeballs 是不是意味着 IPv6 总是优先被使用?
它会获得一个先发优势(RFC 8305 建议大约 250 毫秒),之后 IPv4 尝试也会同时发起,谁先完成 TCP 握手谁就获胜——所以在 IPv6 又快又正常的情况下它确实优先,但在同一次连接尝试中,一条又慢又有问题的 IPv6 路径会让位给 IPv4,而不是直接导致连接失败。
结语
两个地址,两个独立的决定:操作系统为目的地挑选合适的本地地址,浏览器让两族协议赛跑,谁先响应就用谁。这两个决定在浏览器内部都不可见,也都不是你按每次访问去配置的东西——这正是为什么网站看到的地址会在你这边什么都没变的情况下,在不同页面加载之间来回切换。真正值得较真的场合只有一个:使用隧道的时候。如果你依赖 VPN 或代理,检查它是否同时覆盖了两族协议,决定了你的连接到底是真正私密,还是正悄悄从一个你早已忘记自己拥有的地址那里泄露出去。
推荐阅读:


