使用 Apache 2.4。
我们有两个有效的 CA 证书,它们的可分辨名称仅在一个字符的大小写上有所不同(例如,CA1 的 dn 为:cn=MyCA,O=myOrg,CA2 的 dn 为:cn=MyCA,O=MyOrg)。
这两个证书均在SSLCA证书文件Apache 指令,因为我们需要验证由两个 CA 签名的客户端证书。但这种情况不会发生:只有具有由 CA1 或 CA2 签名的客户端证书的浏览器才能够访问,具体取决于文件中 CA 证书的顺序。因此,如果只有来自 CA1 的客户端能够验证自己,则在切换 SSLCACertificateFile 中的顺序并重新加载 Apache 后,只有来自 CA2 的客户端才能验证身份。
如果我们通过 执行 SSL 握手openssl s_client -connect <server>:<port> -prexit
,我们会注意到,在接受的 CA 列表中,只有一个 CA 可分辨名称被发送,并且发送的 dn 取决于 CA 证书在 SSLCACertificateFile 中的顺序。这是有道理的,因为 Openssl 计算的两个可分辨名称的哈希值是相同的,因为可分辨名称不应该区分大小写。
但浏览器似乎执行了区分大小写的匹配,因为在 Apache 日志中,当“公布的 CA”是 CA1 且客户端证书由 CA2 签名时,不会发送安装在浏览器中的证书,反之亦然。我们在 Windows 和 Linux 上尝试了 Firefox,在 Windows 上尝试了 Internet Explorer 和 Chrome。
否则,当我们使用 PEM 格式的客户端证书和密钥调用 https URL 时,curl 命令行浏览器不会出现此问题。
答案1
如果不深入研究,我敢说你无法说服浏览器在这里进行不区分大小写的搜索。对于简单的 Web 服务,你可以创建另一个 VirtualHost,所有客户端都分布在其中(例如https://detect-cert.example.com)。
这意味着客户端协商一次 TLS,然后进行重定向,然后进行另一次 TLS 协商。
虚拟主机检测-cert.example.com:
- 确保你接受
optional_no_ca
来自浏览器的证书 - 不
SSLCACertificateFile
- 查看
SSL_CLIENT_I_DN
或SSL_CLIENT_CERT_CHAIN_<n>
环境变量 - 将浏览器重定向(HTTP 302)
ca1clients.example.com
至ca2clients.example.com
虚拟主机 ca1clients.example.com:
- 确保你的
require
浏览器有证书 SSLCACertificateFile CA_lowercase.pem
虚拟主机 ca2clients.example.com:
- 确保你
require
SSLCACertificateFile CA_uppercase.pem
但你的 Web 应用程序需要支持二域名同时(例如通过X-Forwarded-Host
标头)。它绝不应该告诉通过 进入的浏览器ca2clients.example.com
重新通过 进入ca1clients.example.com
。另一个困难是用户之间交换链接(例如通过电子邮件发送某些内容的链接)。