这是“的后续问题”使用自签名证书和 SSLEngine (JSSE) 进行 SSL 握手".
我已经实现了一个 NIO Web 服务器,可以在同一端口上处理 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 消息吗?我是否需要进行一些预处理或与客户端协商才能发送不同的消息?
提前致谢!
UPDATE
感谢 Bruno 和 EJP 以及一些进一步的调试,我对正在发生的事情有了更好的理解。正如 Bruno 正确指出的那样,IE6 和 Java 6 客户端通过 SSLv2 ClientHello 发送。与我之前的评论之一相反,Java 1.6 中的 SSLEngine 实际上可以解包 SSLv2 消息并生成有效的响应以发送回客户端。我之前报告的 SSLException 是我这边的一个错误,与 SSLEngine 无关(我错误地认为客户端已完成发送数据,当 SSLEngine 期望打开更多数据时,我最终得到了一个空的 ByteBuffer)。
这看起来像SSLv2 Client Hello(请参阅 TLS 规范):
支持 SSL 版本 2.0 服务器的 TLS 1.1 客户端必须发送 SSL
2.0 版客户端问候消息 [SSL2]。 TLS 服务器应该接受
如果他们希望支持 SSL 2.0 客户端,则可以使用客户端问候格式
相同的连接端口。与 2.0 版本唯一的差异
规范是指定版本的能力,其值为
三以及 CipherSpec 中对更多加密类型的支持。
-
80 4F
是长度,高位必须设置为 1(参见msg_length描述).
-
01
是消息类型(Client Hello)
-
03 00
是支持的最高版本(此处为 SSLv3)
从 Java 7 开始,现在默认禁用此功能.
EDIT:
澄清一下,这并不是真正的 SSLv2 Client Hello,这是 SSLv2 格式的 SSLv3 的 Client Hello。在这种情况下,服务器将回复(正确的)SSLv3 Server Hello(对应于03 00
请求的版本号)。这同样适用于 TLS 1.0、1.1 和 1.2,尽管这种格式的使用已逐渐被弃用。
JSSE 7SSLServerSocket
仍会理解此类客户端问候并使用 SSLv3/TLS1.x 服务器问候进行适当回复。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)