在 Ubuntu Touch 上,两个问题常被当成一个:这个桌面软件包能不能跑,以及手机能不能用上 VPN。容器回答的是前者。容器里没有任何东西能回答后者,因为容器对文件系统有自己的视角,而网络栈及其策略属于手机。在承诺一套工作流程之前,先追查每一部分究竟在哪里。

看起来像一个问题的两个问题

在容器里运行桌面应用是打包层面的成果。让手机的连接管理器建立隧道、在休眠后继续维持、并在断开时决定如何处置,这是平台层面的事。在容器里安装成功的安装器只能证明依赖在那里得到了解决。它说明不了手机有没有获批的 VPN 插件、隧道能不能扛过重启,也说明不了哪些应用在用这条隧道。

在任何评估里,把这两件事写进不同的句子。把它们合并,正是实验室演示变成无人能兑现的支持承诺的方式。

容器边界实际提供什么

Libertine 容器是一层可写环境,叠在基础系统为只读的手机之上。这正是为什么在其中安装软件包能成功,也是为什么在基础系统上做同样的安装不行。它让应用在前台运行,并与手机显示集成;它明确不是运行服务器软件、也不是让进程在后台存活的手段。这些约束对 VPN 客户端很重要,因为后者本应一直在线。

libertine-container-manager list
libertine-container-manager info -i <container-id>
libertine-launch -i <container-id> bash

列表显示存在哪些容器,info 命令报告发行版与安装状态。launch 命令给你一个内部 shell,那才是检查软件包究竟装了什么的地方。它给不了你的是对手机网络的控制权。容器内的二进制若要建立隧道,需要特权接口,而那个接口属于平台,不属于容器。

手机的网络状态存在哪里

名称、路由与连接配置由手机的网络服务管理,位于任何容器之外。只有当平台支持该 VPN 类型、且运营商安装了对应插件时,隧道条目才会出现在那里。

nmcli connection show
ip route get 10.42.0.10
ip -br addr show

连接列表才是「这台手机上有没有 VPN 配置」的权威答案。如果隧道不在那张列表里,容器里做多少工作都不会让它出现。路由查询回答的是更窄的问题:这台手机去往某个目的地会走哪个接口。每次改动之后都该重做这项检查,因为配置可以存在,却仍然不是某个应用实际走的路径。

把一个工作流程从头读到尾

挑一个真实任务,比如用桌面客户端访问私有数据库。然后跟踪流程:应用在容器里启动,通过手机所用的解析器解析主机名,打开套接字,再由手机的路由决定哪个接口承载它。每一步都有归属。容器负责应用,平台负责解析器与路由,VPN 端点负责认证。任何一步失败都是那一步失败,而不是整个想法失败。

把私有主机名和私有地址分开测试。解析到公网地址的名字,与被路由进隧道的地址,是两种不同的观察;把它们混为一谈,就会写出无法复现的报告。

答案是「不行」时该记录什么

有时诚实的结论是:这台手机、这个版本,承担不了该流程。把它连同证据写下来:平台提供哪些连接类型、试过哪些客户端、在哪一步失败。

然后说明被接受的替代方案:换设备、换接入方式,或者收窄为一个留在容器内、不触碰私有网络的任务。

不要为复现旧配方而重新挂载基础系统,也不要授予来路不明的特权。能开机的手机,和半年后你仍能推敲其网络策略的手机,并不是一回事。

相关文章