无需管理员权限的便携 VPN 客户端:仍然会坏在哪里
便携 VPN 客户端可以跳过安装程序,却仍需要隧道设备、路由和解析器写入。在信任它之前,请先跑完这些检查。
“便携”描述的是安装程序,而不是内核。客户端可以只是一个放在 USB 盘上的可执行文件,但在第一个数据包发出之前,它仍然需要隧道设备、路由表条目和一次解析器写入。目标机器允许你碰这三样中的哪一样,决定了那个版本在那里到底能不能用。下面的检查按客户端会遇到的顺序回答这个问题。
便携涵盖三种不同的承诺,而只有一种是免费的
没有安装程序,意味着厂商没有注册服务、没有附卸载程序、也没有添加菜单项。没有管理员,意味着普通账户就能启动客户端并完成连接。没有主机改动,意味着你退出之后机器看起来一模一样。那些写着“便携”的下载页面通常只承诺第一项,而另外两项正是部署失败的地方。一个版本也可以在狭义上便携:它从只读介质运行,完全不写点文件,但这仍然无助于说明网络栈的情况。
昂贵的承诺是第二项和第三项。一个需要适配器、路由或解析器写入的可执行文件,是在向操作系统索要“便携”这个标签从未涵盖的权限。
找出客户端会调用的特权助手
几乎没有哪个 VPN 客户端能自己搬运数据包。在 Windows 上,数据路径经过 WFP 过滤器和 Base Filtering Engine;在 macOS 上,经过用户在系统设置中批准的 NetworkExtension 提供程序;在 Linux 上,则经过 tun 设备和路由栈。你复制过来的那个二进制文件是这些组件的控制面,而不是它们的替代品。先问清楚客户端期待哪个组件,再确认它已安装、正在运行,并且你的账户能用它。
Linux 是最容易证明这一点的平台,因为检查只有一次系统调用。打开 /dev/net/tun 并向内核请求设备需要 CAP_NET_ADMIN,而 内核 TUN/TAP 文档 同时写明了属主规则和能力要求。请用将来启动客户端的那个账户来跑这项检查,而不是用 root。
ls -l /dev/net/tun
ip tuntap add dev vpntest mode tun
ip link delete vpntest
中间那一行的权限错误正是你要找的答案:这个账户无法创建隧道接口,所以任何需要它的用户态客户端都会在连接时失败,而不是在下载时失败。最后一行会删除测试设备,成功时不打印任何内容。如果两行都成功,主机就没有留下永久改动。
在第一次连接之前测试路由和解析器改动
分离隧道把一次连接变成路由决策,而完整隧道把它变成默认路由的替换。两者都是对主机网络栈的写入,而且即便客户端本身干净启动,非特权账户也会让两者失败。解析器是第三次写入,在 systemd 主机上通常也是最后坏掉的那一项。当你要决定把提权安装花在哪里时,这个顺序很重要。
路由检查需要一个你真正在意的目标,所以请把下面的占位符换成你自己配置文件里的子网。设备名必须存在,路由才能挂到某个东西上。
ip route add 10.20.0.0/16 dev vpntest
ip route del 10.20.0.0/16
resolvectl query intranet.example.internal
如果第一行返回 RTNETLINK answers: Operation not permitted,就说明该账户无法安装配置文件要求的私有路由。第二行从反方向证明了同一权限,这一点很重要,因为能添加路由却不能删除路由的客户端会留下一张坏掉的表。随后解析器查询会显示私有名称是通过隧道解析的,还是泄漏给主机已经信任的那个解析器。
趁测试设备还在时把这三行都跑一遍,然后删掉它。指向已消失设备的路由,是笔记本在一次失败连接之后失去连通性的最常见原因。
决定什么必须活过这次会话
删掉文件夹不是清理方案。适配器、路由、解析器设置、受信任证书和已保存凭据都可能比进程活得更久,而启动时的服务可能不声不响地恢复其中一部分。要在运行之前写下客户端允许留下什么,而不是在第一次断开失败之后才写。
实用的规则是:对你即将改动的三个面做一次快照,之后再对比。第一次连接之前记录接口、主路由表和解析器状态,等客户端退出后再重复同样的三次读取。
ip -brief addr show
ip route show table main
resolvectl status
第二次抓取里有、第一次里没有的东西,都需要一个负责人。要么客户端在退出时删掉它,要么你用当初创建它的同一条命令把它删掉,而这种删除应当写进部署笔记,而不是留在某个人对当时发生了什么的记忆里。在 Windows 上,对应的读取是 Get-NetAdapter、Get-NetRoute 和 Get-DnsClientServerAddress,它们不需要提权,但会显示同样的残留。