【问题标题】:SSL Handshaking With Older Clients Using SSLEngine (JSSE)使用 SSLEngine (JSSE) 与旧客户端进行 SSL 握手
【发布时间】:2012-04-29 02:23:51
【问题描述】:

这是“SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)”的后续问题。

我已经实现了一个 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 发送。与我之前的一个 cmets 不同,Java 1.6 中的 SSLEngine 实际上可以解开 SSLv2 消息并生成有效响应以发送回客户端。我之前报告的 SSLException 是我这边的一个错误,与 SSLEngine 无关(我错误地认为客户端已完成发送数据,而当 SSLEngine 期望更多数据解包时,我最终得到一个空的 ByteBuffer)。

【问题讨论】:

    标签: java ssl jsse sslengine


    【解决方案1】:

    这看起来像an SSLv2 Client Hello (see TLS specification):

    支持 SSL 2.0 版服务器的 TLS 1.1 客户端必须发送 SSL 2.0 版客户端问候消息 [SSL2]。 TLS 服务器应该接受 如果他们希望支持 SSL 2.0 客户端,则可以选择客户端问候格式 相同的连接端口。与 2.0 版的唯一偏差 规范是指定具有值的版本的能力 三以及对 CipherSpec 中更多加密类型的支持。

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

    从 Java 7 开始,this is now disabled by default

    编辑:

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

    JSSE 7 SSLServerSocket 仍会理解这样的 Client Hello 并使用 SSLv3/TLS1.x Server Hello 进行适当的回复。

    【讨论】:

    • 谢谢。并且根据 [docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/… 参考指南)SUN 的 SSLEngine 不支持 SSLv2。那么我应该把什么发回给客户呢?只是关闭连接?
    • 它不支持,但它支持使用此 SSLv2 ClientHello 启动的更高版本的 SSL/TLS(如果它指示的支持版本是 SSLv3 或 TLS 1.x):它会回复一个 SSLv3以 80 4F 01 03 00 开头的该消息的 ServerHello。
    • 抱歉,我敲回车键太早了。所以你是说我应该用 SSLv3 ServerHello 响应 SSLv2 ClientHello?
    • 是的,取决于支持的版本(此处为 03 00 -> SSLv3、03 01 -> TLSv1.0、03 02 -> TLSv1.1,...)。
    • 你建议我使用什么 api 来生成响应? SSLEngine 中的 unwrap 方法似乎对我不起作用。
    猜你喜欢
    • 2012-03-29
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多