混淆来自于 OpenSSL 措辞其配置选项的方式。
在协议中,有两个非常不同的东西:
协议版本。这可以是 SSL 3.0、TLS 1.0、TLS 1.1 或 TLS 1.2(或其他尚未定义的内容)。在内部,版本被分别编码为值 0x0300、0x0301、0x0302 或 0x0303 的 16 位整数(因此 TLS 1.0 确实是在线上的“SSL 3.1”)。(我在这里不是在谈论 SSL 2.0。)
密码套件。这些是(在线上)客户端和服务器愿意使用的密码算法组合的 16 位标识符。客户端发送一个列表,服务器选择将使用的列表。大多数密码套件适用于 SSL 3.0、TLS 1.0 和 TLS 1.1;一些最近的密码套件仅适用于 TLS 1.2,因为它们使用仅适用于 TLS 1.2 的协议功能。
OpenSSL 在其用于指定密码套件列表的配置字符串中使用一些助记符,例如“SSLv3”。在这种情况下,“SSLv3”并不意味着“协议版本 0x0300”;它的意思是“可以使用 SSLv3 的密码套件列表”。当您在支持的密码套件列表的配置中写入“!SSLv3”时,您应该将其阅读为“删除所有可能与 SSL 3.0 一起使用的密码套件”。但这不是:“删除所有在实际使用 SSL 3.0 时可能与 SSL 3.0 一起使用的密码套件”。删除是全有或全无;您无法根据协议版本有条件地删除支持(这在概念上是可行的,但 OpenSSL 不能那样工作)。
因此,如果您删除了对所有可能与 SSL 3.0 一起使用的密码套件的支持,那么您也将删除其他协议版本的密码套件。特别是,由于 SSL 3.0、TLS 1.0 和 TLS 1.1 都使用相同的密码套件,因此列表中唯一剩余的密码套件是特定于 TLS 1.2 的密码套件。实际上,您也刚刚取消了对 TLS 1.0 和 1.1 的支持。
如果您使用“ !SSLv3:!SSLv2”,那么服务器可以假装仍然支持 SSL 2.0,但支持的密码套件列表为空,因此不会走得太远;不会发生实际的握手。这就像给你的车钥匙,但卸下轮子。