2012-04-17 189 views
1

這是針對「SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)」的後續問題。使用SSLEngine(JSSE)與舊客戶端的SSL握手

我已經實現了一個NIO網絡服務器,可以在同一個端口上處理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消息嗎?我是否必須做一些預處理或與客戶協商發送不同的信息?

在此先感謝!

UPDATE

感謝布魯諾和EJP和一些進一步的調試我有一個更好的瞭解這是怎麼回事的。正如Bruno正確指出的那樣,IE6和Java 6客戶端通過SSLv2 ClientHello進行發送。與我之前的一個評論相反,Java 1.6中的SSLEngine實際上可以打開SSLv2消息,並生成一個有效的響應以發送回客戶端。我之前報告的SSLException是我的錯誤,與SSLEngine無關(我錯誤地認爲客戶端已經完成了數據發送,當SSLEngine期待更多數據解包時,我最終得到了一個空的ByteBuffer)。

回答

4

這看起來像an SSLv2 Client Hello (see TLS specification)

TLS 1.1,支持SSL 2.0版服務器必須發送SSL 2.0版客戶端的Hello報文[SSL2]客戶端。 TLS服務器應該接受 客戶端hello格式,如果他們希望支持相同連接端口上的SSL 2.0客戶端 。與Version 2.0 規範唯一的區別在於能夠指定值爲 的版本,以及對CipherSpec中更多加密類型的支持。

  • 80 4F是長度和高比特必須被設置爲1(見msg_length description)。
  • 01是消息類型(客戶機問候)
  • 03 00是支持的最高版本(這裏的SSLv3)

由於Java 7,this is now disabled by default

編輯:

只是爲了澄清,這是不是一個真正的客戶端的SSLv2你好,這是在格式的SSLv2客戶端對你好的SSLv3。在這種情況下,服務器將回復一個(適當的)SSLv3服務器Hello(對應於03 00所請求的版本號)。這同樣適用於TLS 1.0,1.1和1.2,儘管此格式的使用逐漸被棄用。

JSSE 7 SSLServerSocket仍然會理解這樣一個Client Hello,並且適當地回覆SSLv3/TLS1.x Server Hello。

+0

謝謝。根據[http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#Introduction](JSSE參考指南),SUN的SSLEngine不支持SSLv2。那麼我應該怎樣發回客戶?只需關閉連接? – Peter 2012-04-17 20:27:04

+0

它不支持,但它確實支持使用此SSLv2 ClientHello啓動的更高版本的SSL/TLS(提供支持的版本,它指示SSLv3或TLS 1.x):它將以SSLv3 ServerHello回覆該消息,以' 80 4F 01 03 00'。 – Bruno 2012-04-17 20:28:35

+0

對不起,我太早點擊了輸入鍵。所以你說我應該使用SSLv3 ServerHello來響應SSLv2 ClientHello? – Peter 2012-04-17 20:34:59