我配置了一个启用了 SSL 和 SSL 客户端身份验证的 VirtualHost,所有这些都在 apache2 2.2.8(ubuntu 服务器 8.04)上。
所有 SSL 证书(CA、服务器证书、客户端证书、CRL)都是使用 openssl 命令行生成的。
如果客户端证书无效(不存在、已过期或被撤销),我想将用户重定向到自定义错误页面。
这是我的虚拟主机的配置:
<VirtualHost *:443>
ServerName myserv.example.com
DocumentRoot /var/www/myserv/
CustomLog /var/log/apache2/myserv.access.log combined
ErrorLog /var/log/apache2/myserv.error.log
LogLevel warn
SSLEngine on
SSLOptions +StdEnvVars +ExportCertData
SSLCertificateFile "/etc/apache2/ssl/certs/servcrt.pem"
SSLCertificateKeyFile "/etc/apache2/ssl/private/servkey.pem"
SSLCACertificateFile "/etc/apache2/ssl/certs/ca.pem"
SSLCARevocationPath "/etc/apache2/ssl/crl/"
SSLCARevocationFile "/etc/apache2/ssl/crl/crl.pem"
<Directory /var/www/myserv/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
SSLVerifyClient optional
SSLVerifyDepth 1
RewriteEngine on
RewriteCond %{SSL:SSL_CLIENT_VERIFY} !^SUCCESS$
RewriteRule .* /error-page.html [L]
</Directory>
</VirtualHost>
有了这样的配置,如果用户没有任何 SSL 证书,他就会正确地重定向到错误页面。但如果他的证书已被撤销或过期,则握手会失败(正常),并且连接会关闭(在浏览器上返回 SSL 错误)。
我怎样才能告诉 apache2 将用户重定向到正确的页面而不是在 SSL 握手失败时关闭连接?
答案1
人们常见的误解是,Web 服务器可以“做一些事情”而不是在浏览器中显示大多数(可能是全部) SSL 错误。
这是因为 SSL 握手首先发生,并且完全独立于任何 HTTP 通信。虽然我们将 HTTPS 视为 HTTP,但它实际上并不是与 HTTP 不同的协议,而是“浏览器和服务器之间的 HTTP 加密通道”。
如果客户端提供的证书无效,则 SSL 握手会失败,您会收到错误。此时尚未发生 HTTP 通信,因此不存在重定向用户的机会。
答案2
尝试另一个选项:SSLVerifyClient optional_no_ca
并检查是否SSL_CLIENT_VERIFY
仍然SUCCESS
有效证书。
否则,当使用有效但不受信任的 CA 证书进行测试时SSL_CLIENT_VERIFY
,GENEROUS
可以利用重定向。
也可能像其他人所说的那样,网络浏览器检测到客户端证书已过期并中止握手......需要更多测试来确认浏览器行为。
如果客户端证书签名 CA 由于某种原因也可能不同,您将需要查看SSLCADNRequestFile
指令以指定 CA,或者如果有任何 CA,则可能是一个只有一行空的文件。
否则,httpd 会根据验证内容自动告知客户端允许哪些 CA,并且 Web 浏览器可能会中止握手,因为它找不到任何适用的客户端证书。