OpenVPN 在本机询问私钥口令,因此一份能用的登录文件永远回答不了它。服务没有终端可输入,启动要么卡住,要么失败,日志条目只提到缺失的输入,而不说原因。这里牵涉两个机密,重启 unit 之前,各自都需要可读的来源。下面的步骤把它们分开,再检查真正打开每个文件的身份。

区分两种提示

密钥口令用于解密本地私钥;账号凭据用于向服务器认证会话。两者来源不同、失败时机不同、报错也不同。混淆二者会让人去找密码重置,而账号根本没参与。改任何选项之前先读提示文字,因为措辞是判断缺哪个机密的唯一可靠线索。

在 Community OpenVPN 2.x 中,askpass 指定的文件首行存放密钥口令,auth-user-pass 指定的文件一行用户名、下一行密码。两个文件都不能满足对方的选项。桌面应用或 NetworkManager 配置可能把两者存在自己的密钥库里,命令行客户端从不读取它,所以写路径前先确认自己在配置哪个客户端。

让两个选项都指向可读文件

需要两种输入的配置最终会有 三个文件引用:加密密钥、解锁它的口令,以及登录凭据对。添加它们时不要动 CA 和身份校验,那些决定服务器是谁,不属于这个问题。如果部署根本不用账号凭据,加上 auth-user-pass 只会造出一个没人能提供的输入。

key /etc/openvpn/client/office.key
askpass /etc/openvpn/client/office-key.pass
auth-user-pass /etc/openvpn/client/office-login.auth

不带参数的选项与带路径的选项行为不同,在服务里这个差别很关键。不带参数的 askpass 仍然读控制台,而只写了用户名的 auth-user-pass 文件仍会留下一个等待输入的密码提示。客户端一旦转入后台,就完全无法向终端索要输入,这样配置的服务起不来。

绝对路径消除了工作目录的问题,但并不授予访问权限。接着是属主、权限位和路径可达性,三者都要按进程运行所用的账号检查。

先看 unit 的配置,再看配置文件

决定实例加载哪份配置的是 unit,而不是你正在编辑的文件。读它的命令行和所有 drop-in,再顺着工作目录找到真正在用的配置文件。把口令引用加到另一个 .ovpn 文件里,对这个实例毫无影响。

三条只读命令能回答大部分问题。第一条打印 unit 与所有 drop-in,第二条打印约束进程的身份与沙箱设置,第三条打印上一次启动实际报的错。用主机上真实存在的实例名:

systemctl cat [email protected]
systemctl show [email protected] -p User -p Group -p WorkingDirectory -p ProtectHome
journalctl -u [email protected] -b

注意 ProtectHome,以及配置文件自己的 user、group、chroot 选项。home 目录下的文件在你的 shell 里可读,一旦 home 被隐藏,服务内部就看不见它。systemd 启动时用的账号,并不总是最后打开密钥的那个账号。

证明运行时身份能打开两个文件

只看权限位不够,路径上每一级目录都必须能被同一身份穿过。逐级检查路径,然后用进程所用的账号实测打开。属主为 root、权限 600 的文件只在进程仍是 root 时可用,而许多配置在降权之后就不再是。两条命令分别覆盖路径穿越和打开:

namei -l /etc/openvpn/client/office-key.pass
sudo -u openvpn test -r /etc/openvpn/client/office-key.pass && echo readable

第一条打印每一级的权限,并在账号无法穿越处失败;第二条回答唯一要紧的问题:运行时身份能否以只读方式打开该文件。两条都不打印文件内容,这正是文件里存口令时需要的。对登录文件重复同样的测试,因为两者的属主常常不同。

如果进程用了 chroot 或受限命名空间,就要在那个视图内部跑同样的测试,否则测的是错误的文件系统。存在被隐藏的 home 目录下的口令,就是“unit 外测试通过、unit 内失败”的典型例子。

先看首次启动,再看重连

启动实例一次,看第一个失败而不是最后一个。缺少输入文件、密钥解密失败、服务器返回 AUTH_FAILED,是三件不同的事,修法也各不相同。修掉一条权限告警,并不证明密钥已被解锁。

日志行会告诉你属于哪一种。修法取决于哪个输入失败了:

What the journal showsWhich input failedWhere to look
A path that cannot be openedThe file the profile namesAskpass or login path, and the unit's working directory
A key decryption errorThe key passphraseFirst line of the askpass file, and read access for the runtime identity
AUTH_FAILED from the serverThe account credentialsLogin file contents, and whether the account is still valid

然后测试 你真正需要的生命周期:开机启动和支持的重连,而不只是在 shell 里手动启动一次。启用 auth-nocache 后,输入在首次使用后就被丢弃,之后的每次重连仍需一个可读来源。桌面登录时解锁的密钥环,对在任何人登录之前就启动的服务不可用,这正是手动测试通过、重启却失败最常见的原因。如果首次启动成功、之后重连失败,先读重连事件的日志,再考虑改权限。

把口令和密钥放在一起,会削弱加密带来的保障,所以要限制该文件及其备份的权限。去掉密钥口令属于另一项凭据决策,而不是缺少输入时的修法。依赖人工批准或交互式 MFA 的部署,需要用受支持的 agent 或管理集成;把一次性口令永久保存下来并不是等价的替代。

相关文章