2

这是“使用自签名证书和 SSLEngine (JSSE)进行 SSL 握手”的后续问题。

我已经实现了一个 NIO Webserver,它可以在同一个端口上处理 SSL 和非 SSL 消息。为了区分 SSL 和非 SSL 消息,我检查入站请求的第一个字节,看它是否是 SSL/TLS 消息。例子:

byte a = read(buf);
if (totalBytesRead==1 && (a>19 && a<25)){
    parseTLS(buf);
}

在 parseTLS() 方法中,我实例化了一个 SSLEngine、启动握手、包装/解包消息等。对于大多数现代 Web 浏览器(Firefox 10、IE 9、Safari 5 等)来说,一切似乎都运行良好。

问题是 IE 6 等较旧的 Web 浏览器和 Java 的 URLConnection 类等库似乎以不同的方式启动 SSL/TLS 握手。例如,IE 6 的前几个字节看起来像这样(十六进制值):

80 4F 01 03 00 ...

如果我将消息传递给 SSLEngine,它似乎无法识别该消息并引发异常。

javax.net.ssl.SSLException: Unsupported record version Unknown-0.0

那么 IE 6 和 Java 的 URLConnection 类到底发送了什么?这是 JSSE SSLEngine 可以支持的有效 SSL/TLS 消息吗?我是否必须进行一些预处理或与客户端协商以发送不同的消息?

提前致谢!

更新

感谢 Bruno 和 EJP 以及一些进一步的调试,我对正在发生的事情有了更好的理解。正如布鲁诺正确指出的那样,IE6 和 Java 6 客户端通过 SSLv2 ClientHello 发送。与我之前的评论相反,Java 1.6 中的 SSLEngine 实际上可以解开 SSLv2 消息并生成有效响应以发送回客户端。我之前报告的 SSLException 是我这边的一个错误,与 SSLEngine 无关(我错误地认为客户端已完成发送数据,而当 SSLEngine 期望更多数据解包时,我最终得到一个空的 ByteBuffer)。

4

1 回答 1

4

这看起来像SSLv2 Client Hello(请参阅 TLS 规范)

支持 SSL 2.0 版服务器的 TLS 1.1 客户端必须发送 SSL 2.0 版客户端问候消息 [SSL2]。如果 TLS 服务器希望在同一连接端口上支持 SSL 2.0 客户端,则它们应该接受任一客户端问候格式。与 2.0 版规范的唯一偏差是能够指定值为 3 的版本,以及在 CipherSpec 中支持更多加密类型。

  • 80 4F是长度,高位必须设置为 1(见msg_length说明)。
  • 01是消息类型(Client Hello)
  • 03 00是支持的最高版本(此处为 SSLv3)

从 Java 7 开始,现在默认禁用此功能

编辑:

澄清一下,这并不是真正的 SSLv2 Client Hello,这是 SSLv2 格式的 SSLv3 的 Client Hello。在这种情况下,服务器将回复一个(正确的)SSLv3 Server Hello(对应于03 00请求的版本号)。这同样适用于 TLS 1.0、1.1 和 1.2,尽管这种格式的使用逐渐被弃用。

JSSE 7SSLServerSocket仍会理解这样的客户端问候,并使用 SSLv3/TLS1.x 服务器问候进行适当的回复。

于 2012-04-17T20:01:38.480 回答