在 SSL 中,如果握手不成功,是否总是以握手警报结束?
或者是否有其他方法来完成 SSL 连接(标准可接受)。
我问这个,因为在配置为需要客户端身份验证的 HTTPS 服务器中,如果客户端不发送证书,我会看到(通过网络数据包)从服务器到客户端的 TLS 完成消息;我期待一个警报。
SSL 握手失败模式
SSL/TLS连接必须始终以某种警告消息结束:没有警告的断开连接(例如,底层 TCP 套接字关闭)被称为不正确终止。正常终止的警报消息是close_notify
。
握手只是连接的一部分;开始时发生握手,随后的握手可以在同一连接上播放。握手通常是发生错误的地方,会触发警报消息,但致命警报消息不仅会结束握手:它会关闭整个连接。
在服务器请求客户端认证的情况下,客户端可以通过发送证书和计算签名来响应;但是,这是可选的。允许客户不履行请求。然后服务器选择要做什么。服务器可以通过关闭连接的警报消息立即拒绝客户端。服务器也可能决定继续,并在另一个级别处理缺少客户端身份验证。发送Finished
消息的服务器肯定会选择继续;可能,服务器可以决定将错误报告为隧道内的应用数据(例如,对于 HTTPS 服务器,一旦握手完成就发送HTTP错误消息)。
有关详细信息,请参阅RFC 2246的第 7.4.6 节:
This is the first message the client can send after receiving a
server hello done message. This message is only sent if the
server requests a certificate. If no suitable certificate is
available, the client should send a certificate message
containing no certificates. If client authentication is required
by the server for the handshake to continue, it may respond with
a fatal handshake failure alert.
→ 强调“可能”。
TLS 1.0 规范 (RFC 2246) 中关于客户端证书的部分是这样说的:
如果没有合适的证书可用,客户端应发送不包含证书的证书消息。如果服务器需要客户端身份验证才能继续握手,它可能会以致命的握手失败警报进行响应。
它可能会以致命警报响应这一事实并不意味着它必须如此。
您已经用 IIS 标记了您的问题,但这里有一些关于其他服务器的背景知识。在 Apache Httpd 中,请求客户端证书有3 个设置:none
和(如果您想在此处禁用证书验证)。当服务器配置了,当客户端没有提供证书时,握手仍然会进行。当服务器配置 时,如果没有客户端证书,则会出现致命的握手失败警报。Java使用和实现这些设置。optional
required
optional_no_ca
optional
required
SSLEngine
setWantClientAuth
setNeedClientAuth
请注意,继续握手并不意味着服务器将授予对资源的访问权限或授权执行请求。
致命握手失败警报行为的最大缺点是它会突然关闭连接。充其量,它会在浏览器中显示为“连接关闭 - 握手失败”消息(或类似内容)。根本不会发生 HTTP 交换,因此没有机会发送 HTTP 状态代码和/或随附的网页来描述问题。
从可用性的角度来看,这可能会非常令人困惑,尤其是对于不一定熟悉客户端证书的用户(处理证书通常有一定的学习曲线)。出于这个原因,许多服务器只需要可选的客户端证书身份验证,以便能够在授权被拒绝时发送解释。
我必须承认我对 IIS 中的设置并不完全熟悉,但文档似乎也暗示了三个选项:
如果您不想接受客户端证书,即使客户端提供了一个,请选择忽略。
选择接受以接受客户端证书。
选择需要以要求客户端证书。要使用需要客户端证书,您必须启用需要 SSL。
另一份文件表明,由于未能提供所需的证书,存在 HTTP 状态代码和错误消息:“ 403.7 Forbidden: Client certificate required ”。这种情况下有一个 HTTP 状态代码的事实意味着它不是导致握手失败的情况(否则根本不会建立连接来发送 HTTP 消息)。这意味着就 TLS 握手而言,IIS 的“要求”模式的行为类似于 Apache Httpd 的“可选”模式,也就是说,不提供客户端证书不会导致致命警报(之后的授权是不同的问题,当然)。
那么,我不确定“忽略”和“接受”是什么意思。在 SSL/TLS 中,只有服务器可以通过发送CertificateRequest
消息来请求证书。如果服务器不发送此消息,客户端将永远不会再次从 RFC 2246 发送其证书:
7.4.6。客户证书
何时发送此消息:这是客户端在收到服务器 hello done 消息后可以发送的第一条消息。仅当服务器请求证书时才会发送此消息。
我的猜测是,在帐户映射或授权方面,它们的意思是“忽略”/“接受”,更进一步。
编辑。
据我记得,默认情况下,IIS 总是使用重新协商来协商客户端证书:第一次握手成功,没有任何客户端证书请求,但随后触发了第二次握手。这意味着您将无法通过查看数据包来查看客户端证书交换,因为第二次握手将在加密会话中完成(在某些情况下,您可以使用 Wireshark 看到它,它配置了服务器的私钥,它支持密码套件)。
您可以使用netshclientcertnegotiation=enable
选项(指的是初始握手)将客户端证书协商配置为在初始握手中完成。
我将以 Apache 使用的 OpenSSL 为例。
有一个名为 SSL_VERIFY_PEER 的模式标志,当它在服务器上设置时,它将在握手时请求客户端证书。客户可以自由发送或不发送。
然后服务器的行为取决于另一个标志:
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
解释如下
服务器模式:如果客户端没有返回证书,TLS/SSL 握手会立即终止,并发出“握手失败”警报。此标志必须与 SSL_VERIFY_PEER 一起使用。
如果未设置此标志,则不会创建警报并且握手正常进行,服务器必须随后检查证书并在必要时关闭连接。
编辑:有关 IIS 7.0 中类似配置选项的更多信息:
https://www.iis.net/ConfigReference/system.webServer/security/access
似乎有一个 sslFlags 属性可以是以下之一
- 没有任何。此默认设置禁用站点或应用程序的 SSL。
- Ssl。站点或应用程序需要 SSL。
- SslNegotiateCert。站点或应用程序接受客户端证书进行身份验证。
- SslRequireCert。站点或应用程序需要客户端证书进行身份验证。
- SSL128。站点或应用程序需要 128 位 SSL 证书加密。
我想您注意到的行为发生是因为配置了 SslNegotiateCert 而不是 SslRequireCert。