OpenVPN 启动时会打印一条建议启用 auth-nocache 的警告,诱人的做法是加上这个选项,然后看着那行警告消失。但那条建议假设的是交互式登录。一旦用户名和密码存放在文件里,比较的前提就变了:该选项不再保护那份持久副本,而在会降低权限的客户端上,它还可能在此后破坏重协商。动手修改配置之前,值得把两种存储模型分开来看。

回答凭据提示的两种方式

第一种模型是人在终端里输入凭据,或者由管理界面在会话期间持有凭据。OpenVPN 保留这份副本,以便在下一轮重协商时不必再次询问,而这正是那条警告所指的情况。整个过程不涉及磁盘,因此唯一需要保护的是持有该值的进程。关闭客户端,副本也随之消失。

第二种模型是用 auth-user-pass 指向一个文件:文件本身就是存储,客户端在需要取值时读取它。这里真正要紧的风险不是进程内存,而是该文件的权限和属主。启动警告来自配置里的指令,而不是对你如何提供密码的检查,所以它在两种模型下都会出现,却并不指向其中任何一种。

余下的比较都从这一分野推出:一种模型看内存处理,另一种看文件处理与进程身份。

auth-nocache 究竟丢弃了什么

在交互式登录下, --auth-nocache 会在凭据被使用之后把保存的副本从内存中移除。 代价是每个重协商间隔都要重新提示一次,因为下一轮无法重用已被丢弃的内容。

在使用文件的登录下,客户端可以再次读取文件,所以这种丢弃基本看不出来。它只在一个人们意想不到的地方显现:当守护进程降低权限之后,如果凭据文件对它现在所使用的账户不可读。

加这个选项,应该是因为你理解这笔交换,而不是因为出现了警告。为了让日志安静一点而加的选项,就是没人衡量过其效果的选项。

依赖文件的路径在哪里断裂

客户端以 root 启动去打开隧道设备,随后切换到 user 和 group ,它会读两次凭据文件:一次在切换之前,一次在随后的重协商时。如果文件权限是 600 且属于 root,第二次读取就会失败,而这个失败会在一小时后表现为看起来像服务器问题的认证错误。先查重协商间隔前后的客户端日志,再把账户与文件放在一起核对。

stat -c '%a %U:%G' /etc/openvpn/client.creds
ps -o user:12,args -C openvpn | head

两行都重要。第一行告诉你谁能读这个文件,第二行告诉你正在运行的守护进程实际上是谁,而两者的不一致正好解释了一种无论重输多少次密码都修不好的故障。

实际修法并不光鲜:把文件移到一个守护进程所属账户可读的目录并改好属主,或者保留特权读取并确认客户端只读一次。不要用让所有人都能读来解决。

确实需要这个选项的情形

携带一次性口令的登录需要 auth-nocache ,理由不同。一次性口令在第一次认证时就被用掉,所以缓存副本在下一轮重协商时毫无用处,而过期的值甚至可能被重放。

这是凭据类型的问题,而不是存放位置的问题。受保护文件里的静态密码正好相反:它在每次重协商时都必须可读,需要加固的是文件本身。

把这两条理由分别写进配置注释,否则下一位管理员会以为这个选项是为了他自己会选的那个理由。

用一个决定做完比较

有人在场、新鲜度重要时,选交互式模型,并接受重复提示作为代价;客户端无人值守时,选文件模型,把精力花在属主、权限和降权上。

两种模型本身都不能让存储的密码变安全,也都不能让启动警告变得有意义。

如果警告是你打开配置的唯一理由,那就记录决定,而不是留下一个没有解释的选项:凭据来自守护进程账户可读的文件,重协商已被观察到成功,改动间隔之前也读过 OpenVPN 2.6 手册中关于重协商的那一节 。这条备注比任何单个开关都活得久。

相关文章