如何用自己的资源通过 VPN 测试 IPv6
要证明一条路径可用,你不需要公开的 IPv6 检查器。使用你自己掌控的资源,记录两端,并说明这次测试没有覆盖什么。
公开的 IP 检查页面只回答一个问题,而且通常不是你真正要问的那个。它只会告诉你页面看到的出口地址;它不会告诉你隧道内的 IPv6 路由是否工作,主机是优先选择 IPv6 还是回退,也不会告诉你被排除的应用走了另一条路。你自己掌控的授权资源能正确回答这个更窄的问题,因为你能看到两端。下面的步骤讲的是如何得到一个站得住脚的结论,而不是拿到一个绿色的结果。
第 1 步:说清楚你在测试哪条 IPv6 路径
用一句话说清楚。向隧道服务器自身的 IPv6 地址发起请求,测试的是隧道;向出口之外的主机发起请求,测试的是出口的 IPv6 出口;向私有 IPv6 地址发起请求,测试的是内部路由。
这是三个不同的主张,一次成功的请求无法同时支撑它们。挑出对眼前决策真正重要的那一个,并在动手之前写下来。如果担心的是 IPv6 是否绕过隧道泄漏,问题就在于主机的路由选择,而不是出口的可达性。如果担心的是远端能否访问内部服务,出口就无关紧要。
第 2 步:确认主机确实选择了这条路径
ip -6 route get 2001:db8:1::10 会打印路由、源地址以及内核将要使用的接口,而测试的其余部分都取决于这一事实。
接口存在并不等于接口被选中。双栈主机有优先级表,Linux 上的 /etc/gai.conf 可以改变一个同时解析到两种地址的名字由哪个协议族胜出。
第 3 步:使用合法的主机和合法的名字
如果你在测试 HTTPS,就用证书签发所对应的主机名,并保持校验开启;为了通过测试而改用字面地址,恰好会关闭那个能证明你到达了目标主机的检查。你自己掌控的诊断服务,用已知名字和有效证书应答,是最干净的目标。它还能给你一条服务器端日志用于比对,第三方检查器永远不会给你这个。
用能显示所用地址的形式运行请求:curl -6 -sS -o /dev/null -w '%{remote_ip} %{http_code}\n' https://test6.example.net/。-6 强制指定协议族,这样你就能把 IPv6 不工作和 IPv6 没有被优先选择区分开来。
如果只是做纯粹的可达性检查,并且允许 ICMPv6,ping -6 -c 3 2001:db8:1::10 就足够了。它证明路径,不证明路径之上的任何东西。
第 4 步:把两端对上
当你能同时接触两端时,在客户端运行 tcpdump -ni any ip6 and host 2001:db8:1::10,在资源端运行对等的命令,都带上时间戳,并确认同一条流在两边都出现。正是这一点把貌似合理的结果变成了证据:只看客户端无法区分来自资源的应答和来自中间某个环节的应答。把抓包范围限制在单一目的地,使输出保持可读,也不会把别人无关的会话写进文件。
如果担心的是策略能否在重启后保留,就在重新连接之后再测一次。连接时一次性应用的路由和防火墙状态,可能与重新应用后的状态不同,而这种差异只会在第二次连接时显现。
需要的话,把失败情形单独测一遍。掉线时阻断 IPv6 的隧道和任其泄漏的隧道是两种不同的设计,而只有其中一种能用成功的请求加以验证。
第 5 步:写下测试没有证明的东西
第五步是写下测试没有证明的东西,而这恰恰是最容易被丢掉的部分。对私有端点的一次成功测试,并不证明公网 IPv6 出口,不证明 DNS 行为,也不覆盖你从隧道中排除的应用。每一项都需要自己的目的地和自己的观察。写一句一次请求后 IPv6 就能用,这不是结论;这是带了时间戳的猜测。
值得保留的记录很短:目的地、名字、主机选择的源地址、观察到的远端地址以及时间。RFC 7359 讨论了如何测试一条相关的 IPv6 路径是否真的可用,这正是本步骤想用更简单的工具逼近的标准。如果结论非要靠一个公开检查器才能成立,那这次测试就还不够具体。