证书已经安装,私钥也在,隧道却仍然认证失败。一台计算机装有多张证书时,可能把自己都不想要的某张证书交给 VPN,而客户端无从知道网关会接受哪一张。删掉其余证书,是一项会影响本机每项服务的选择策略。不如缩小可选范围,然后确认实际提供的是哪一张。

多张证书,只有一张被提供

使用计算机证书认证的 Windows 原生 VPN 配置文件提供两个用于限制候选的筛选器:颁发者筛选和扩展密钥用法筛选。它们缩小客户端可选的集合。它们并不修复不合适的证书,也不保证服务器接受剩下的那一张。这条边界值得写进变更记录,因为下一位读者会以为筛选器决定的比实际更多。

它们针对的故障很窄也很具体。来自错误机构的有效证书,或为网关不接受的目的签发的证书,被排在意图的那张前面选中,于是在健康的存储旁出现认证失败。两个筛选器把它变成小到可以推敲的集合,本页其余部分按顺序应用它们。

编辑配置文件前先检查存储

在配置文件实际使用的存储中列出候选证书及其属性。这里不会导出任何私钥,也不需要任何证书离开这台计算机:

Get-VpnConnection -Name 'Office' | Select-Object Name, TunnelType, AuthenticationMethod
Get-ChildItem Cert:\LocalMachine\My | Select-Object Subject, Issuer, Thumbprint, NotAfter, HasPrivateKey, EnhancedKeyUsageList

阅读输出里决定判断的那几个属性:可用的私钥、可接受的生效期、预期的颁发者,以及扩展中的用途。一张证书可以同时具备、登记正确,却对这次连接毫无用处。指纹列就是之后要拿来比对的那一列,所以请保留输出。

编辑之前先确认配置文件及其作用域,因为 LocalMachine 中的计算机证书、用户 EAP-TLS 证书和应用自己的私钥存储,是三种不同的上下文。当受管配置文件位于全部用户作用域时,就使用该作用域和管理上下文。另建一个名字相近的配置文件,会掩盖连接实际使用的配置。

颁发者筛选要的是对象

颁发者参数期望的是证书对象,不是显示名称,也不是裸的指纹字符串。从你已核对的路径提供获批机构的证书,放进它所属的存储:

$issuerPath = Read-Host 'Certificate-provider path for the approved issuer CA'
$issuer = Get-Item -LiteralPath $issuerPath
Set-VpnConnection -Name 'Office' -MachineCertificateIssuerFilter $issuer

不要因为参数类型接受,就替换成客户端自己的叶证书、主题相近的另一家机构,或刚生成的根证书。 两家机构可以共用同一个主题字符串,这正是对象比文本更重要的原因。Microsoft cmdlet 参考 记录了两种输入类型,值得在第一次编辑之前读,而不是在失败之后。

用法筛选要的是 OID 字符串

扩展密钥用法参数接受 OID 字符串,而客户端认证的用途是 1.3.6.1.5.5.7.3.2。应用它会将候选限定为携带该用途的证书,这正是客户端认证部署想要的:

Set-VpnConnection -Name 'Office' -MachineCertificateEKUFilter '1.3.6.1.5.5.7.3.2'

该值是一个数组,因此需要多个用途的部署把它们作为列表传入。筛选器做不到的是给证书增加用途:它是针对已签名扩展求值的选择表达式,没有筛选器会改写这些扩展,所以缺少该用途的证书必须重新经过登记。

把用户证书的 EAP 配置与计算机证书筛选分开保管,因为它们位于不同位置,改动一处很少能解释另一处的失败。还要检查配置文件归域还是归设备管理所有,因为本地编辑可能在下次策略刷新时被替换,而没人碰过这台计算机。

证明客户端提供的是哪张证书

建立新连接,读取客户端和服务器针对预期身份给出的认证证据。当不止一张证书满足筛选时,结果是一个更小的池,而不是被钉死的叶证书,所以下一次尝试可能选中另一个成员。记下证据中出现的指纹,与从存储里记下的那张比对。

命令成功不等于认证成功。值得记录的,是预期的那张证书在受管策略下完成认证,同时每张无关证书仍对依赖它的服务可用。如果两个筛选器之后故障仍在,下一步该看的是剩下的候选,而不是整个配置文件。

相关文章