路由器上的 VPN 下 STUN 看到的是哪个源地址
路由、源地址选择与转换共同决定反射器报告的地址。先记下三个事实,再用一次查询确认哪条路径胜出。
这个问题听起来像一次查询,实际却是三个决定。绑定请求走哪条路由,内核对这条路由选择哪个源地址,以及途中是否有东西改写这个源地址。改变其中任何一个,STUN 服务器报告的地址都会随之改变。所以「VPN 在路由器上」这句话本身几乎说明不了什么。
决定取决于三个事实
第一是路由:策略规则和路由表决定请求从隧道还是从普通 WAN 出去,而被排除的目的地即使隧道已建立也会走第二条路径。第二是源地址:内核为选定的路由选择源地址,这一选择取决于该路由的首选源地址以及任何匹配的规则。第三是转换:途中的 NAT 会替换被选定的源地址。反射出的地址是三者的乘积,而不是隧道的属性。
改变三者之一,答案就会改变,而每个组件在自己的日志里看起来仍然健康。这就是这类诊断卡住的常见原因。
开始之前,先为你要测试的流写下三个事实。接口、路由和转换规则足以预测结果,而正是这种预测让意外变得有信息量。如果三者中有一个填不出来,那个空白就是真正的发现。
沿路径跟踪一个绑定请求
STUN 绑定请求要求服务器报告它观测到的源传输地址。回复描述的是请求走过的路径,而不是客户端机器上的接口清单。两条路径上的两个请求会诚实地报告两个不同的地址。
| Path taken | Source the reflector sees | What it means |
|---|---|---|
| Tunnel to a public exit that translates | The exit's public address | The reflector learns nothing about the LAN |
| Tunnel to a private reflector, translated to the tunnel address, no later translation | That tunnel address | An internal identifier is disclosed to that reflector |
| Excluded flow over the ordinary WAN | The WAN address | The tunnel was not used at all |
把那张表读成一组条件,而不是供应商菜单。中间一行要求私有反射器在隧道自身的路由和对等策略下可达;这是可以核实的配置事实,而不是账户层级所暗示的东西。最后一行通常才是策略上重要的,因为那部分流量本该留在隧道里。两者之间是常见情形:出口做转换,反射器只看到出口。
主机候选和服务器反射候选来自不同机制,所以候选列表并不能说明媒体实际走了哪条路径。想知道会话去了哪里,要读被选中的配对,而不是收集日志。
路由器的隧道地址不是什么
分配给路由器的隧道地址属于路由器上的一个接口。LAN 主机上的浏览器有自己的接口地址,也无法直接看到路由器的隧道接口。把两者当成可以互换,就会对网页能了解到什么给出自信而错误的答案。
转发把两者连起来。请求作为被路由的流量穿过路由器,它的源地址是路由和转换产生的结果。
如果隧道路径保留 LAN 源地址,私有反射器就能得知那个 LAN 地址,这是真正的泄露,且不同于隧道地址。如果路径转换为隧道地址,反射器得知的就是隧道地址。两种结果都与同一主机上的同一浏览器相容,所以观测必须绑定到特定的流。在责怪应用之前,先问内核会使用哪个源地址。
泄露与绕过:两个发现,两种修复
被反射的隧道地址在你允许的路径上泄露了内部标识符。直接走 WAN 的请求绕过了你本想强制的路径。前者是信息问题,后者是执行问题,修复的位置不同。把两者合成一个词,得到的修复哪个都不解决。
WebRTC 让这一点更明显,却没有让它变错,因为收集候选并不等于选择候选。
ip route get 203.0.113.7 from 192.0.2.25
ip rule show对你允许的每个反射器地址运行路由查询,使用你预期该流携带的源地址,然后对排除的网段再运行一次,看看回退选择什么。把两个答案与你写下的策略对比。当它们以你并未预期的方向不一致时,你就找到了修复点,而不必去解释浏览器的候选列表。