没有客户端证书的 OpenVPN:改的是服务端策略,不是配置文件
如果服务端仍然要求客户端证书,删掉证书与密钥行不会有任何改变。把要求移到服务端,并保留客户端自身的服务端校验。
你删掉证书和密钥行,把配置文件交出去,连接仍然会因证书错误而失败。配置文件从来不是强制执行该项要求的地方。客户端证书是否强制,由服务端决定,任何客户端侧的修改都无法通过协商取消它。因此正确做法是有意识地修改服务端策略,并在同一次操作中更新所有依赖它的东西。
配置文件不是策略
Community OpenVPN 2.6 默认强制要求客户端证书,因为 verify-client-cert 的默认值是 require。把它设为 none,才能停止索要证书,并把客户端身份验证交给服务端已经在运行的用户名与密码机制。较旧的指南会去用 client-cert-not-required,那是同一思路的旧写法,所以请以你安装的版本文档中的指令为准。无论如何,改动发生在服务端,任何客户端配置文件都做不到。
下面这段就是服务端改动的全部内容,它本身并不是一套可用的身份验证配置。verify-client-cert none 取消证书要求,而 username-as-common-name 让账号名成为后续回调和每客户端文件所看到的身份。两行都不校验密码,所以仍然必须有一个校验器。
verify-client-cert none
username-as-common-name
那个校验器是由 auth-user-pass-verify 驱动的插件或脚本,它必须在上面的任何一行生效之前就位。顺序反过来,就会留下一段既不要证书也不校验账号的窗口。
还有什么在验证服务端
去掉客户端证书并不意味着去掉 TLS。服务端保留自己的证书和密钥,客户端保留 CA 信任和主机名校验,从而不会与冒充者通信。因为客户端没有证书了就删掉 remote-cert-tls server 或 CA 包,是一种常见而严重的误读,2.6 参考文档 明确指出两个方向相互独立。一个方向是客户端验证服务端,另一个方向是服务端验证客户端。
配置文件还可能带有 tls-auth 或 tls-crypt 块。那是控制通道的共享密钥,有自己的分发与轮换周期,所以没有证书或密钥行的文件并不自动适合公开发布。在你读清楚它之前,把它当作机密对待。
从可用配置文件中复制出来的证书文件本身什么也证明不了;拥有意味着持有与之匹配的私钥,而基于证书认证的部署会校验这一点。包含证书的文件,并不是一个能用它来完成认证的文件。
校验器必须做到什么
去掉证书要求之后,一切都压在校验器上:一个插件,或由 auth-user-pass-verify 驱动的脚本。它必须拒绝无效凭据,拒绝被禁用或不符合条件的账号,并在无法联系后端时失败关闭。username-as-common-name 常常同时启用,它会改变后续回调和每客户端配置文件所看到的身份。它不校验密码,也不会让不符合条件的账号变得符合条件。这些是彼此独立的工作,把它们混为一谈,正是迁移能通过顺利路径测试、却在第一次真实事故中失败的原因。
否定情形要和肯定情形一样仔细测试。显示密码提示的配置文件只证明客户端能画出提示,而接受错误密码的服务端证明的是更糟的事情。测试集里要加入被禁用的账号和已过期的凭据,而不只是一个错误密码。
策略、配置文件和映射要一起改
要协调三件事:服务端指令、客户端配置文件,以及 按客户端划分的身份映射。分开改,客户端要么在验证之前就失败,要么以管理员没预料到的名字连上来,而后者更糟,因为它看起来像成功。用错误身份建立的成功连接,比失败的连接更难被察觉。
为这条路径保留两个测试账号,一个有效、一个已知有问题,并在每次改动校验器之后都用上它们。有效账号证明顺利路径和身份映射,有问题的那一个证明拒绝仍然生效。两个测试都不能告诉你任何关于资格规则的事,所以如果部署有这类规则,还要加一个应因策略原因被拒绝的账号。每次改动后把三个都跑一遍,因为开始全盘接受的校验器,看起来和正常登录一模一样。
记录服务端实际接受哪些身份验证方式,而不是配置文件暗示的那些。这份记录回答了人们反复追问的问题:谁能连上这个服务。它也会比下一任管理员活得更久,否则对方只能从抓包里重新发现它。