同一台机器上,两个启动器打开同一份配置,只有 GUI 能连上。文件本身完好,安装程序多半也没问题;差别在于每个启动器交给 openvpn.exe 的上下文。工作目录、账户身份和文件属性都随这份上下文一起变化。按这个顺序逐项检查,遇到第一个能解释错误的就停下来。

确认是哪个启动器失败

先证明这个分界。如果同一个配置路径下 GUI 能连、服务不能连,说明文件对某些身份是可读的,问题就变成谁在读、从哪里读。如果两者都失败,配置本身就是坏的,本文都不适用。记下服务名,以及让它加载的确切配置路径。

指向自身自启目录的服务,加载的可能不是你正在编辑器里打开的那个文件。把服务配置里的路径和 GUI 里的路径逐字符比对,因为末尾多一层文件夹名或盘符不同,就足以把你引到错误的分支。

相对路径在哪里解析

如果配置只用裸文件名引用 ca.crt 或辅助脚本,查找就相对于进程所在的位置进行。GUI 从配置目录启动,这些名字自然能解析。由服务管理器启动的服务没有这样的起点,在任何证书被读取之前查找就已经失败。这就是同一份配置在一个启动器里能用、在另一个里不能用的原因。

给包装程序指定一个启动目录,或者把所有引用改成绝对路径。在命令行上复现 GUI 的上下文,形如:

openvpn --cd "C:\VPN\profiles\office" --config "C:\VPN\profiles\office\office.ovpn"

提高这条命令的详细程度,会显示出实际尝试的确切路径。请在改权限之前做,因为文件缺失和读取被拒需要不同的修法。默认日志区分不了这两种情况。多一个参数能省下一小时的猜测。

服务身份读不到文件时

服务以系统身份运行,而不是你的身份。只给你的账户完全控制、不给其他人的 ACL,在你的会话里完美工作,到了服务那里就会失败。配置放在映射驱动器或需要认证的共享上,也会因同样的原因失败。在看别的之前,先确认文件的权限。

检查分两步:读取有效权限,再以服务身份尝试读取。第一步在提升权限的命令行里执行:

icacls "C:\VPN\profiles\office\office.ovpn"

然后用服务身份做同样的读取,例如用 Sysinternals 的 psexec -s -i,观察文件是否打开。如果打不开,任何路径修正都没用。修好 ACL,或者把配置移到服务身份可读的位置。

文件级加密是第二种、也更少见的情况。带加密文件系统属性的配置,对加密它的用户透明解密,对服务账户始终不可读。这就是同一个文件在你的编辑器里能打开、在服务下却打不开的原因。

该属性在提升权限的命令行里可见,查看它并不会打开配置。两条命令都执行,读取输出:

cipher /s:"C:\VPN\profiles\office"
attrib "C:\VPN\profiles\office\office.ovpn"

清除属性会让文件可读,同时也去掉了它原本带的保护。如果配置必须保持受保护,就把机密材料放到服务身份有明确授权的位置,而不要依赖按用户加密。这种安排能经受口令变更,也让除加密者之外的其他人可以审查访问权限。

决定隧道归谁所有

GUI 可以提示输入口令,也能从你的用户存储里读取证书。服务两者都做不到,所以依赖交互式机密的配置,无论路径怎么修,都不可能无人值守地启动。这个限制是设计决定,不是需要绕过的缺陷。先选定一个所有者,再改别的。

如果隧道必须在登录前就建立,就给服务一个无人值守的凭据来源和它自己的配置副本。如果只需要你在桌前时存在,就把它留在 GUI 里,并删除服务的副本。两者同时存在,正是产生适配器冲突和重复路由的配置。

这种冲突通常被诊断为配置错误,而不是两个所有者争抢同一块适配器。事件日志会显示某个进程打开 TAP 设备失败,看起来像权限问题,其实不是。先数一数所有者。

服务包装程序实际启动的是什么

服务的入口是一个小包装程序,它读取自己保存的参数,然后启动 openvpn.exe。当事件日志里的命令行与你的预期不符时,要检查的就是那些值。重装会把它们重置为默认值,并销毁证据。先读取它们。

这些值存放在服务自己键下的注册表里,而 sc qc 会显示服务管理器将要启动的二进制路径。在改动任何一处之前,先把该路径与包装程序保存的配置比对。

用自己可控的脚本替换包装程序侵入性更强,但它把有效的命令行收敛成一个可读文件。以重启收尾,然后读按配置划分的日志,直到出现第一条启动成功的记录。服务状态显示正在运行,只说明包装程序还没退出;它的子进程立刻死掉时,也一样。

相关文章