使用SSLEngine(JSSE)与旧客户端进行java SSL握手
这是对“SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)”的后续问题
我已经实现了一个NIO Web服务器,它可以在同一个端口上处理SSL和非SSL消息。为了区分SSL和非SSL消息,我检查入站请求的第一个字节,看它是否是SSL/TLS消息。例如:
byte a = read(buf);
if (totalBytesRead==1 && (a>19 && a<25)){
parseTLS(buf);
}
在parseTLS()方法中,我实例化了一个SSLEngine,启动握手、包装/打开消息等。对于大多数现代网络浏览器(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希望打开更多数据时,我得到了一个空字节缓冲)
# 1 楼答案
这看起来像an SSLv2 Client Hello (see TLS specification):
80 4F
是长度,高位必须设置为1(请参见^{01
是消息类型(客户端Hello)03 00
是受支持的最高版本(此处为SSLv3)自Java7以来,this is now disabled by default
编辑:
澄清一下,这不是真正的SSLv2客户机Hello,这是SSLv2格式的SSLv3客户机Hello。在这种情况下,服务器将使用(正确的)SSLv3服务器Hello(对应于
03 00
请求的版本号)进行回复。这同样适用于TLS 1.0、1.1和1.2,尽管这种格式的使用逐渐被弃用JSSE7
SSLServerSocket
仍然会理解这样的客户机Hello,并使用SSLv3/TLS1进行适当的回复。x服务器你好