手机 VPN 回家:让防火墙成为你的上网出口
连上家里的 LAN 不等于从家里的上行链路出网。在手机上决定转发、解析器、IPv6 和断线状态。
把手机接入家里的隧道并打开 LAN 文件共享,只能证明隧道是通的。这不能证明手机的互联网请求会从家里出去。这两种结果之间的差别是一项转发策略加一条路由,而不是手机上的又一个勾选框。这也正是大多数人以为早已配置好的差别。
出口路径来自三个决定:手机把什么送进隧道、家庭网关把它转发到哪里,以及隧道不在时会发生什么。每一种失败模式从手机屏幕上看都像另外两种。
两跳,两套策略
外层连接终止于家中的 VPN 监听端。内层数据包是另一个对象,必须被转发到某处;而转发与最初接受隧道是两件不同的防火墙决策。
phone app -> encrypted tunnel -> home listener
-> decrypted packet -> forward policy -> home uplink -> destination
在典型的家用路由器上,这两者位于不同的规则集。接受隧道是 VPN 接口上的入站策略;把手机流量送出到互联网则是转发策略,再加上上行链路所需的源地址转换。一台接受隧道却不转发任何流量的路由器,会得到一个显示已连接却打不开任何页面的手机。
如果 VPN 服务运行在家中另一台机器上,就多了一跳。此时路由器看到的是来自那台机器的流量,规则作用于服务器的地址而不是手机的隧道地址,源地址转换还会让所有手机看起来像同一台主机。
监听端不是过滤器
趁所需信息仍然存在时,先决定在哪里执行。在路由器上,手机的隧道地址可见,可以直接匹配。经过第二次转换之后它就消失了,为手机地址编写的规则会悄悄地匹配不到任何东西。
这就是同一策略对笔记本有效、对手机无效的常见原因。笔记本直连路由器,手机连接的是经由路由器转发的服务器,只有第一条路径保留了规则所期望的地址。规则并没有错;它匹配的是一个在该处已不存在的值。
把路径连同每个执行点上出现的源地址一起写下来。这一张图就能在任何规则被修改之前解决其中大多数情形。
手机究竟该发送什么
只收到通往家庭子网路由的手机,只会把该子网的流量送进隧道。其余流量都走移动网络,所以文件共享能用,而互联网请求永远到不了家。
全隧道覆盖是客户端侧的路由决定,必须用平台支持的方式设置,而不能从所安装的配置文件里假设。设置之后,回到 VPN 服务器本身的路由必须留在隧道之外,否则客户端无法维持自己的传输。
DNS 值得单独决定,因为它是最容易偏离其余流量的部分。配置文件里的解析器地址只是一个建议,各客户端的处理方式并不相同;带有自己加密解析器的应用可以走完全独立的路径。如果家庭策略依赖查询到达某个特定解析器,就在流量真正经过的地方强制执行,或者接受有些查询不会到达。绕过你的解析器的查询,永远不会碰到为它编写的规则。
IPv6 和 DNS 属于同一段,而不是附录。完整的 IPv4 隧道对 AAAA 流量只字未提,而双栈移动网络上的手机会乐于走原生路径。请明确选择承载还是阻断。
防火墙能看见什么、看不见什么
网关只能依据其执行点所暴露的信息行动:地址、端口、协议、接口以及连接的元数据。被转发的 HTTPS 请求不会仅仅因为穿过家庭隧道就交出页面正文或密码。
这条边界值得说明,因为“让它走防火墙”这句话所暗示的检查,比家用路由器实际做的更多。目标规则、DNS 策略和应用层代理是三种不同的控制手段,部署成本也各不相同。
不要以为为家庭 LAN 客户端配置的功能也适用于 VPN 接口。区域成员资格是配置选择,不在正确区域里的 VPN 接口,不会继承你从沙发上测试过的任何规则。
决定断线状态
当隧道不可用时,手机要么回落到移动网络,要么拒绝发送流量。两者都合理,而只有一种符合大多数人所认为的配置。
回落很方便,而且按定义就会泄漏:隧道掉线的那一刻,就是请求沿运营商路径出去的那一刻。阻断更强,但让手机依赖家里可达,这对出行的人来说是真实的可用性成本。两种行为都不是缺陷;它们都是产品,而无论你说不说,你都在两者之间做选择。
去测试这个选择,而不是假设它。停掉家里的服务,然后分别用手机浏览器发一个请求、用后台运行的应用发一个请求。之后再连回来,并不会撤回已经出去的请求。
最后从手机本身做两项受控检查:一个应当穿过家里的允许操作,和一个家庭策略应当执行的拒绝。确认网关在你预期的地址族里记录了你预期的流,并且是在重新连接之后。显示“已连接”的手机只是这项验证的开始,绝不是结束。