有一个误解会让人白费一周:以为 Mac 只有一个叫“登录前”的时刻,以为 VPN 客户端要么在那时启动,要么就不启动。实际上,这台机器至少有三个与网络访问有关的时刻,把它们区分开的是:在该时刻谁有权持有凭据。由登录项启动的客户端只覆盖其中一个,而且是最后一个。

一个设置覆盖整个启动过程的迷思

再读一遍产品页面,看这项功能说的是哪个阶段。“登录时启动”复选框意味着登录项,它在用户会话存在之后才运行。“按需连接”复选框意味着客户端在流量匹配某条规则时打开连接,这仍然要求客户端及其凭据可用。

两者都到不了启动过程。这不是厂商忘了移除的限制,而是操作系统允许的边界。卷尚未解锁时,没有正在运行的系统可以用来启动客户端;注销之后,用户的秘密随会话一起离开。两道彼此独立的墙,没有哪一道会因为另一个复选框而让路。

一旦把阶段拆开,原来的问题就变了形状。与其问 VPN 是否在登录前启动,不如问三个具体时刻中哪一个必须能用;随后你会发现,每个时刻的归属都不同:加密栈、网络扩展,或者用户会话。

每个阶段实际发生了什么

启动始于一个加密卷,必须先解锁它,才有一个可用于任何常规工作的系统。这次解锁发生在受限的上下文中,只有受限的一组凭据;Apple 明确记载:没有有效的解锁,加密数据就无法访问。

接着是登录窗口:系统在运行,但还没有用户会话。如果用户已注销,用户上下文的扩展已经结束;全局系统扩展可能仍在运行,但在运行并不等于持有你的 VPN 所需的凭据。

然后才是会话,普通客户端在这里可以读取登录钥匙串、请求第二因素并应用下发的路由。人们所说的大多数登录前功能其实属于这个阶段,它在会话早期触发,而不是在会话之前。

StageWhat it can useWhat it cannot do
FileVault unlockCredentials supplied at the console to unlock the volumeRun an ordinary VPN app or read a user keychain
Login windowSystem context, possibly a joined networkUse a user secret that only exists after login
User sessionLogin keychain, interactive MFA, full client featuresExist before the volume unlocks

为什么 launch daemon 无法替缺席的用户登录

更高权限看起来应当能解决问题,其实不能。launch daemon 以系统进程运行,背后没有用户会话,因此既没有可解锁的钥匙串,也没有人能应答提示。它可以打开套接字、读取文件;它做不到的是成为持有凭据的那个用户。权限不等于身份,而这正是两者最容易被混淆的地方。

人们在这个空档里造出来的,是把密码写进脚本的做法,这比原来的问题更糟。

诚实的版本要求更窄。如果机器必须在无人值守时访问受保护资源,那么该资源接受的身份,必须是机器可以在没有人参与的情况下持有的身份:设备证书、系统钥匙串中的凭据,或者第二因素不是推到某人兜里手机上的账号。有意识地设计这种身份,阶段问题通常就自己回答了。

Windows 的登录前功能不能照搬

Windows 为某些远程访问产品提供了有文档记载的登录前访问机制,名字比能力走得更远。Windows 部署指南里描述的功能,并不能说明同一厂商是否在 macOS 上实现了对等能力。

请厂商就 Mac 硬件、macOS 版本、客户端版本和你实际使用的认证方式给出明确说明。笼统的支持声明不够,因为能用与不能用的差别往往就在这四项之一。

如果厂商答不上来,那就是答案。请按会话阶段做规划,并为无人值守场景设计替代方案,而不是等到部署时才发现缺口。

该改问什么

用阶段的语言来写需求:哪个资源、谁需要、在什么上下文中、连接尚不存在时能接受多长的延迟?

如果答案是“用户登录后需要隧道”,按需连接加一个启动项就足够,也不贵。如果答案是“机器过夜重启且必须上报”,设计就需要受支持的磁盘解锁路径、设备身份,以及网络始终起不来时也能工作的恢复流程。如果答案是“依赖隧道的组织登录”,那么登录、身份与 VPN 的设计必须一起做,而不是分开采购。

Apple 的FileVault 文档是解锁阶段的正确起点。此后的一切都是客户端与身份的问题,应当在下单前由厂商的说明来定案。

相关文章