在 Apache 中针对特定客户端证书强制执行客户端验证

在 Apache 中针对特定客户端证书强制执行客户端验证

我想让我的 Apache Web 服务器仅当客户端提供特定的 SSL 客户端证书时才接受 SSL 连接。换句话说,只允许一个客户端,并且它必须使用特定的客户端证书(我也拥有该证书)。

该客户端证书(我们称之为“MyClientCertificate”)是由 CA(我们称之为“MyCA”)颁发的普通 PEM 证书,而我也有该 CA 的证书。

这是我为此目的配置 Apache 虚拟主机的方式(我仅报告与 SSL 客户端验证相关的选项):

SSLVerifyClient require
SSLCACertificatePath /etc/ssl/certs
SSLCACertificateFile /etc/ssl/client/MyClientCertificate.pem
SSLCADNRequestFile /etc/ssl/client/MyClientCertificate.pem
SSLVerifyDepth 1

对选项的解释(或者至少是我的目的...):

  • 使用“SSLVerifyClient require”,我强制 Apache 始终执行客户端验证,如果失败则拒绝连接
  • /etc/ssl/certs 包含 MyCA 的 PEM 证书(已正确安装在系统中,并经过了所需的哈希+符号链接过程),以及 Apache 可以识别的所有其他知名 CA 的证书
  • 使用 SSLCACertificateFile,我将 MyClientCertificate 证书添加到 /etc/ssl/certs 中的 CA 证书列表中,作为其本身的受信任证书,使用 SSLCADNRequestFile,我说我的服务器应该只向客户端请求该证书(并且只能请求该证书),而不是 SSLCACertificatePath+SSLCACertificateFile 中的整个 CA 证书列表
  • 使用“SSLVerifyDepth 1”,我的意思是允许的客户端证书是由服务器识别的 CA 签名的(在 SSLCACertificatePath 中)

这似乎有效:Apache 需要客户端证书,如果未提供指定的客户端证书,则拒绝连接,如果提供了,则接受连接。但是,最近,客户端(我的供应商)决定更改其客户端证书,使用新的证书(我们称之为 MyNewClientCertificate.pem),使用 2048 位加密,而不是旧证书的 1024 位深度。问题是这样的:

  • 供应商称其已更改了客户端证书,目前正使用新证书进行身份验证
  • 供应商肯定地表示,他们只会出示新证书,而不会同时出示新旧证书
  • 我尚未更改我的 Apache 配置(因此,我的 Apache 仍然配置为请求旧证书)
  • 但是我的 Apache 可以毫无问题地接受供应商客户端连接!我原本以为它会开始失败,直到我更改其配置,用 MyNewClientCertificate.pem 替换 MyClientCertificate.pem 引用

新证书由与旧证书相同的 CA 颁发。供应商表示,我的 Apache 配置可能接受所有来自出示该 CA 颁发的证书的客户端的连接,而不是对客户端证书本身进行匹配。

如果是这种情况,我的配置哪里做错了?我应该将 SSLVerifyDepth 降低到 0 吗?(但这不是说证书必须是自签名的吗?)还是我必须在 SSLCACertificateFile/SSLCADNRequestFile 指令中更改某些内容?

由于该系统正在生产中,我无法执行我能想到的所有测试,但我应该尝试进行有针对性的更改,以尽快获得正确的结果。这就是为什么我非常感谢有关此主题的任何帮助。

答案1

您可以使用以下方式匹配特定的客户端证书SSLRequire指令与客户端证书中的完整主题 DN 或仅 CN 部分进行匹配:

SSLRequire %{SSL_CLIENT_S_DN} eq "C=AU, ST=Some-State, L=Springfield, O=ServerFault.com, OU=Moderators, CN=HBruijn/[email protected]"   

SSLRequire %{SSL_CLIENT_S_DN_CN} eq "HBruijn/[email protected]"

用于openssl x509 -in client.crt -text显示主题字符串。

更完整的配置是:

SSLVerifyClient      none
SSLCACertificateFile conf/ssl.crt/ca.crt
SSLCACertificatePath conf/ssl.crt

<Directory /usr/local/apache2/htdocs/secure/area>
  SSLVerifyClient      require
  SSLVerifyDepth       5
  SSLOptions           +FakeBasicAuth
  SSLRequireSSL
  SSLRequire           %{SSL_CLIENT_S_DN_CN} eq "HBruijn/[email protected]"
</Directory>

相关内容