OpenVPN 在等待 systemd 的密码请求:该不该回答?
systemd 的密码提示是服务的请求,而不是网关的判决。判断被要求的是哪个秘密,以及谁应该回答它。
终端里出现一条关于 systemd-tty-ask-password-agent 的消息,而隧道并未建立。诱人的解读是 VPN 拒绝了密码,现在有东西在等待纠正。更准确的说法是:某个服务向 systemd 请求了交互式输入,而该请求尚未得到回答。是哪个服务发问、它要的是哪个秘密——这两个问题你都可以在动手输入之前解决。
两个条件决定谁应该回答
第一个条件是:这个实例是不是你有意启动的。紧接在你某项操作之后出现的请求归你回答,而在没有相应操作时冒出来的请求属于别的东西。第二个条件是:这个秘密是账户认证还是密钥保护,因为二者存放在不同位置,走的是不同代码路径。只要在动手前查看,两个答案都能在日志里看到。
当两个答案都清楚时,决定很简单:通过该服务自身受支持的提示路径来回答。当其中任何一个不清楚时,正确的做法是去调查,而不是向一个你无法归属的提示里输入密码。
规则就是这些,值得在命令之前说清楚。下面的一切都由它推出。
在输入任何内容之前先列出请求
代理可以在不作任何回答的情况下枚举待处理的请求。sudo systemd-tty-ask-password-agent --list 会打印尚未处理的请求,而这个输出正是你把提示与某个单元对应起来所需要的证据。在提供凭据之前先读它,并且把请求描述排除在任何公开的诊断粘贴之外。
把清单与你启动的操作、以及与拥有它的单元对应起来。如果清单里没有任何一项与你的操作匹配,那么你看到的提示属于另一个服务,不该由你来解决。清单里的单元名是提示与服务之间唯一可靠的关联。
不要回答你无法归属的请求。等待的代价是延迟,而答错提示的代价是凭据放错了地方。
这个实例真正需要的是哪个秘密?
auth-user-pass 涉及向 VPN 服务进行账户认证,在没有凭据文件的情况下,文档记载的行为是在控制台上询问。askpass 则获取解锁受保护密钥材料的口令,而且是在进程转为后台之前完成。这是两种寿命不同的秘密。
文件格式也不同。账户形式期望一行用户名和一行密码,而密钥口令文件把第一行当作它的密码来读。把另一种角色的凭据文件配方照搬过来,通常只会产生又一个提示,而不是解决方案。格式不对的文件比没有文件更糟,因为失败会转移到无人盯防的地方。
在决定输入什么之前,先确认实例用的是哪条指令。指令的名称就告诉你这个提示对应哪个秘密。
--query 做了哪些 --list 不做的事
--query 会处理调用终端上所有待处理的请求,这比回答单个提示要宽泛得多。它不是 OpenVPN 的选择器,在繁忙的机器上它可能回答属于其他单元的请求。监视模式更宽,因为它会在请求到达时持续处理。
使用能起作用的最窄机制。对单个服务来说,该服务自身的提示流程比全局代理更窄,而且它让答案与发问的单元保持绑定。
只因为通知出现过一次,就把一次性请求变成无人值守的全局代理,正是一时烦扰变成永久设计的途径。同样的谨慎也适用于在全主机范围内停用密码通知单元。
做出决定,然后记录选择
对于无人值守的部署,要与连接的所有者商定凭据来源、文件权限和续期计划。交互式第二因素可能需要一个人,或一个专用的服务身份。压制提示并不会产生那种认证,而移除 auth-user-pass 只会破坏需要它的服务。
交互之后,观察同一实例的下一个事件,并测试私有资源。如果没有任何待处理项,就回到该实例的状态,而不是启动主机上的每一个 OpenVPN 单元。