你选了一个国家,连上之后,某个网站却在另一个国家迎接你。列表里的标签从来没有承诺过你会从哪个地址出去:它只是某人发布的一个字段,用一套你没见过的方法推导出来。把这个字段当成地址,正是混乱开始的地方。

有三样彼此独立的东西各自带着国家值,它们可以在没人说谎的情况下互相不一致。把它们区分开,这种不一致就能被诊断,而不是变成谜团。

三样不同的东西都带着国家标签

第一样是目录自己的字段,它可能由运营者自行上报,可能从地址数据库推断,也可能只是创建条目时照抄过来的。第二样是地址本身,它属于宣布该地址的网络,地理位置查询正是用公开发布的映射数据、按 RFC 8805 所描述的形式来回答这个问题。第三样是应用决定显示什么,它可能来自另一个数据库、账户设置,或你在设备上授予的权限。只有第二样是网络事实,而且它也只是查询,不是观测。

这三者之间保持一致当然好,但没有任何地方要求如此。不一致只说明它们来自不同的推导方式,仅此而已。

检查地址,而不是旗帜

有用的问题是:你的流量究竟从哪个公网地址出去。这个问题可以从客户端回答,也不依赖任何列表字段。把答案与你预期的前缀、以及地理位置查询对它的说法分别比对,并在笔记里把两个结果分开记。预期国家与查询之间的差距是路由或数据库问题,而查询与应用判断之间的差距同样是数据库问题。

如果该服务在区域内有多条出口,就检查两次。地址池在连续连接中可能分配不同地址,一个样本只描述其中之一。

地图上的接近不等于网络上的接近

邻近国家可能比遥远国家路径更长,因为光纤线路并不沿国界走。为延迟选节点,意味着测量你在意的目的地,而不是挑最近的旗帜。同样的逻辑也适用于容量,因为隔两个国家的轻载出口可能胜过隔壁的饱和出口。先测量,再决定,并记下时段,因为两个数字都会变。

位置也不能说明留存策略,更不能说明谁在运营端点。这些需要各自的证据,一个国家列装不下。

自己确认出口地址

问客户端和外部服务你的地址看起来是什么样,再问本地路由表这条路径是怎么选出来的。下面的命令把三件事都做了,而第三件正是人们常跳过的。把接口名换成你自己的隧道设备。

curl -sS https://api.ipify.org; echo
curl -sS --interface tun0 https://api.ipify.org; echo
ip route get 1.1.1.1
ip -6 addr show dev tun0

前两行应当一致;如果不一致,你以为存在的那条路径就不是承载你流量的路径。路由查询会给出内核为某个目的地会使用的接口和源地址,这正是出口地址背后的机制。IPv6 那一行很重要,因为一台机器可以为一个协议族保留隧道,为另一个协议族走直连路径。国家标签本身覆盖不了其中任何一种情况。

把观测到的地址、数据库的判断和应用的显示写成三条独立的笔记。这样下一次遇到不一致时,就很容易归因。

相关文章