Mac 上的 VPN 证书登录:身份、密钥使用,还是网关信任?
证书登录背后有三个决定:选择哪个身份、VPN 组件能否使用其密钥,以及是否信任网关。
基于证书的 VPN 登录向 Mac 索取的东西比密码更窄:在这个执行上下文中,用这把特定的私钥,向那个网关证明某个身份。失败时,消息通常只描述最后出错的一步,而它很少是原因。按系统做决定的顺序逐一走完这三个决定,能让诊断保持诚实,也能避免把本地权限问题当成证书链验证失败。
按 Mac 的顺序走一遍登录
首先,客户端选出一个身份:一张配了可用私钥的证书,它可通过受支持的存储区或凭据提供方取得。接着 VPN 组件请求用这把密钥执行一次密码学操作,本地授权模型给出回答。只有当两者都成功之后,远端的握手才会发生,在那里 Mac 评估网关,网关评估客户端的证明。
| Decision | Typical symptom | Where to look |
|---|---|---|
| Identity selection | No valid identity, wrong certificate offered | Profile and which identity the client picked |
| Local key use | Signing or interaction error before any handshake | Execution context and key access rules |
| Remote authentication | Chain, name or client-admission rejection | Gateway identity and what it accepts |
从上到下读这张表,在第一行失败处停下。失败之下的一切都尚未被证明,这就是为什么“证书不受信任”是如此常见、又如此不可靠的结论。
本地权限究竟覆盖什么
在 macOS 的钥匙串模型中,受保护的条目带有针对具体操作的访问规则和一份受信任应用程序列表。用私钥签名就是其中一种操作,规则作用于执行该操作的可执行文件,而不是作为文档的证书。Apple 的访问控制参考也在这一模型与 iCloud 钥匙串、访问群组安排之间划了界线,所以为前者写的建议不能照搬到后者。
由此得出两个结果。公开证书出现在列表里,并不能证明 VPN 的后台组件能够触及那把密钥。而授予前端应用程序的权限,对独立的辅助程序或网络扩展毫无说明,因为它们是不同身份的不同代码。
应当识别实际的实现及其受支持的凭据共享机制,而不是从旧客户端里照抄一条可执行文件路径。先确认系统究竟会提供哪个身份:
security find-identity -v -p ssl-client
如何阅读 errSecInteractionNotAllowed
该状态报告的是与 Security Server 之间被禁止的交互,它对证书链只字未提。要把它和产生它的操作一起读:从无法弹出提示的上下文发出的签名请求,即使密钥和证书两者都完全有效,也会以这种方式失败。起点是记录它的那个操作,而不是证书存储区。你对信任锚所做的任何改动,都会让这个错误停在原地。
所以把这个代码当作检查执行上下文与授权的理由。把它当作网关 CA 不受信任的证据,会让你走向问题的错误一半,而你在那一半所做的改动根本不会影响这个错误。
要窄修,不要宽修
从连接所有者的注册或导入说明开始。记录客户端版本、配置文件范围、所选的第一个身份,以及第一条相关的本地错误,因为支持交接需要的正是这四项事实,之后的比较也依赖它们。受管理的配置文件或由硬件支撑的身份,可能需要管理员或提供商来修复交接,再多的本地点击也替代不了。
当产品期望用户批准时,确认是哪个组件在请求,并只通过受支持的流程批准那一次访问。当组件在其运行的上下文中无法弹出提示时,配置必须走厂商记录在案的路径,而不是从另一个终端窗口里诱出的对话框。
旧建议常把两项改动捆在一起,而两者都过宽。给每个应用程序授予私钥访问权,会把本地密钥的使用范围扩得远超需求;把证书设为 Always Trust,会改变整台机器上所有对象的证书评估。两者都没有表达“这个已获批准的 VPN 实现,使用这个预期身份”。
先本地验证,再读网关
修复之后,先确认本地操作成功,再去解释另一侧的任何回应。如果签名现在能工作,那么随后出现的名称、证书链或客户端准入拒绝就是一个新结果,而不是旧病复发,它属于另一个决定、另一个负责人。
有用的交接会点名三个决定中哪一个失败了,并就此打住。它从不包含私钥,也从不指望“干净状态”能帮忙而重置无关的钥匙串条目。这两条习惯要在事故之前定下,而不是在事故当中——那时一口气全试一遍的诱惑最强。一张写着“重建了钥匙串”的工单,对下一位读者几乎什么都说明不了。