OpenVPN 在 Windows 上登录时启动而非开机启动?
启动快捷方式打开的是桌面应用,而不是自动服务。在移动文件之前,先确认所有者读取的是哪个配置来源。
只有在有人登录后才出现的隧道,通常是由该用户的会话启动的,而不是自动服务。常见的元凶是一个启动快捷方式,它会运行 openvpn-gui.exe,这并非安装损坏。该快捷方式在用户会话内启动桌面应用,使用的是该用户的配置文件、该用户的证书存储,以及该用户响应提示的能力。这些都无法让连接脱离已登录的人,而这正是登录前隧道所要求的。
这一症状通常有三个原因
三种情形从外面看很相似,修复方法却各不相同。第一种是执行者属于用户会话而非服务,也就是启动快捷方式的情形。第二种是配置文件放在服务不会查看的位置,于是服务启动后什么也找不到,干净地退出。第三种是服务能找到并启动该配置文件,但它的凭据需要一种任何服务都无法提供的交互。
要判断属于哪一种,需要读两样东西:服务被配置为运行什么,以及它能看见哪些文件。两者各只需一条命令,而且都不会干扰正在运行的连接。
自动服务实际读取的是什么
Community 自动服务是一个包装器,它扫描所配置的自动启动目录(通常是安装目录下的 config-auto),并为它找到的每个匹配配置文件启动一个 OpenVPN 进程。用户 GUI 菜单中可见的配置文件则位于该用户的漫游配置文件下,服务账户不会读取那个目录。Windows 服务指南描述了这一查找过程;在复制任何东西之前值得先读一读,因为目标目录是安装本身的属性,而不是固定的约定。因此把文件复制到 GUI 的文件夹对服务毫无改变,而把它复制到每个名为 config 的文件夹,只会制造重复而不是修复。
Get-Service OpenVPNService | Select-Object Status, StartType
Get-CimInstance Win32_Service | Where-Object Name -eq 'OpenVPNService' | Select-Object PathName, StartName
gci 'C:\Program Files\OpenVPN\config-auto'
最后一条命令列出包装器实际会看到的内容,这是确认配置文件放错位置的最快方法。第二行还显示服务以哪个账户运行,而该账户决定了哪些文件路径和证书存储根本可达。
为什么桌面登录有效,而开机启动无效
桌面上的成功可能长期掩盖对输入的依赖。GUI 可以在对话框中收集密钥口令、账户密码或第二因素,因为它运行在带有可见桌面的交互式会话中。服务运行在没有桌面的会话中,因此输入请求无处显示,连接会在一次超时后失败,而这次超时看起来完全不像凭据问题。
文件访问遵循同样的规则。存放在用户配置文件下的私钥,或用户个人存储中的证书,对以计算机身份运行的服务不可用。应比较绝对路径、权限以及各方所做的证书选择,而不是假定同一个配置文件就意味着同样的环境。
设置为无论用户是否登录都运行的计划任务,也会继承类似的限制。它可能成功启动 GUI 可执行文件,却仍然产生一个永远拿不到凭据的进程,因此任务管理器里存在进程并不能证明隧道可用。
选定一个执行者,并测试真实的生命周期
对于属于某个已登录用户的连接,应使用 GUI 支持的自动启动行为,并把服务排除在外。对于必须在任何人登录之前就存在的隧道,应配置服务,把配置文件放在包装器读取的位置,并使用受支持的无人工凭据机制,例如不带交互式口令的密钥,或已记录的凭据文件。
Get-Content 'C:\Program Files\OpenVPN\log\openvpn.log' -Tail 40
Get-WinEvent -LogName Application -MaxEvents 20 | Where-Object ProviderName -like '*OpenVPN*'
测试真正重要的生命周期:无人登录时重启,然后在网络变化后重新连接。为连接只保留一个执行者,因为两个相互竞争的启动机制通常会产生两个实例,争夺相同的路由和相同的服务器会话,这比单独任一机制都更难诊断。