VPN 已连上,VM 却失联?问题多半从来不在路由
你把藏起 host-only 网络虚拟机的责任归给了隧道。通常路径仍在本地,真正拦截的是客户端过滤器或监听地址。
连上 VPN,一分钟前还有响应的开发用 VM 忽然安静下来。显而易见的故事自己就写好了:隧道抢走了路由,主机把访客流量送进了公司网络,解决办法是加一条静态路由或把网卡切成桥接模式。这个故事有时成立。但它不是常见原因,先照它动手通常会把别的东西弄坏。
host-only 网络是主机拥有、与其虚拟机共享的软件网络,与任何物理连接无关。VPN 客户端自身的接口并不会改变那个网络,所以在动手之前,先弄清四层里究竟是哪一层失败了。
路由通常仍在本地
去问内核,而不是看路由表的第一页。在 Linux 上,ip route get 192.168.56.10 会报出真正会被使用的路由、接口和源地址,这与读默认路由再猜是两个答案。如果输出点名的是 host-only 接口,隧道根本没有参与这条路径。
两件事确实能把它弄坏,而它们都是地址问题,不是 VPN 问题。与 host-only 前缀重叠的远端子网会让更具体的路由获胜,而安装低度量宽路由的 VPN 客户端会把该前缀抢走。两者都能在同一条命令里看到:输出里点名的接口会是隧道,修正则属于那张地址规划的主人。
选路与放行数据包是两个不同的决定
这是心智模型通常会漏掉的部分。即使本地路由完美,VPN 客户端依然可以拒绝这个数据包。许多客户端会执行本地网络访问策略,决定隧道之外允许去往哪些目标,而已连接的子网并不会自动更新那份白名单。
于是从应用这一侧看,故障与路由问题一模一样;从客户端那一侧看,却完全不同。如果 ip route get 点名了正确的接口,连接却仍然超时,别再改路由,去读客户端文档里写明的本地访问行为。有些客户端为本地子网提供允许列表,有些会把隧道之外的一切都拦下,还有些只在启用断网开关时才拦截。
这一区分之所以重要,是因为两种修法并不能互换。加路由满足不了过滤器,而为了一台虚拟机去关掉过滤器,比症状暗示的决定要大得多。
访客有三种方式说不
能上网的访客并不能证明你想要的这个服务可用。监听端可能只绑在访客内部的 127.0.0.1 上,那样无论路径多好,来自主机的请求都到不了。在访客里用 ss -ltn 确认,看的是本地地址那一列,而不只是端口。
接下来是访客自己的防火墙。一个默认设置严格的开发镜像会收下主机的数据包,却在服务边界把它们丢掉,产生的超时看起来与路由黑洞毫无区别。最后是服务自身的配置:绑定到特定主机名的 Web 应用,或一份客户端地址白名单,即便每个包都抵达,也会拒绝来自 host-only 子网的请求。
在考虑改 VM 的网络模式之前,先把这三项走一遍。每一项都比重新设计访客的网络连接要小,而且每一项都有明确的验证方法。
桥接到底是什么,代价又是什么
把网卡切成桥接模式并不是在修 host-only 路径。那是把访客放上另一个网络的决定,通常是物理局域网,它会变得对那里的一切可见。这也许正是你想要的。但它不是原配置在做的事。
只有当访客确实需要成为那个局域网上的对等成员、且暴露范围被批准时,才用它。不要因为某一个服务停止应答就用它,因为这项改动可能把访客移出原本让它安全可开发的隔离环境。
任何获批的修正之后,按固定顺序验证:从主机到访客的新请求、经由隧道的必需公司资源,以及断开隧道时预期应出现的拒绝行为。如果最后一项不再成立,这次修正就超出了问题本身。
VirtualBox 关于 host-only 网络的那一节描述了主机侧软件接口,以及它与桥接连接的区别;在假定两种模式可以互换之前,那是值得一读的资料。