2013-03-23 14 views
28

我看到從運行Java 6會失敗,異常客戶端的SSL連接:如何使Java 6與「SSL對等關閉不正確」的SSL連接失敗,像Java 7一樣成功?

Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:882) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199) 
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) 
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) 
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133) 
    ... 35 more 
Caused by: java.io.EOFException: SSL peer shut down incorrectly 
    at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:462) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:863) 
    ... 41 more 

服務器是基於7 Tomcat的應用程序,在Java 7中,Linux上運行,並在Amazon EC2上,爲了什麼是值得的。

我發現了很多關於可能的casues的建議,包括意外連接到非SSL端口等。我相信我已經排除了所有這些,主要是因爲運行Java 7時完全相同的客戶端沒有變化。 (在這兩種情況下都是OS X)。

下面我包含Java 6的調試輸出和Java 7的SSL連接過程。我對專家的問題是,這是否表明在Java 6中可以啓用某些可能的密碼或協議設置(可能是Java 7中的默認設置)以使其工作

的Java 6:

Allow unsafe renegotiation: false 
Allow legacy hello messages: true 
Is initial handshake: true 
Is secure renegotiation: false 
%% No cached client session 
*** ClientHello, TLSv1 
RandomCookie: GMT: 1363993281 bytes = { 77, 153, 100, 72, 45, 178, 253, 243, 195, 167, 17, 151, 39, 247, 148, 102, 213, 129, 39, 17, 26, 139, 157, 154, 63, 88, 41, 160 } 
Session ID: {} 
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 
Compression Methods: { 0 } 
*** 
main, WRITE: TLSv1 Handshake, length = 81 
main, WRITE: SSLv2 client hello message, length = 110 
main, received EOFException: error 
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake 
main, SEND TLSv1 ALERT: fatal, description = handshake_failure 
main, WRITE: TLSv1 Alert, length = 2 
main, called closeSocket() 

的Java 7:

Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA 
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 
Allow unsafe renegotiation: false 
Allow legacy hello messages: true 
Is initial handshake: true 
Is secure renegotiation: false 
main, setSoTimeout(0) called 
%% No cached client session 
*** ClientHello, TLSv1 
RandomCookie: GMT: 1363993435 bytes = { 131, 83, 80, 186, 215, 90, 171, 131, 231, 18, 184, 183, 249, 155, 197, 204, 73, 1, 74, 79, 32, 142, 236, 28, 111, 37, 58, 255 } 
Session ID: {} 
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 
Compression Methods: { 0 } 
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1} 
Extension ec_point_formats, formats: [uncompressed] 
Extension server_name, server_name: [host_name: ec2-xx-xx-xx-xx.compute-1.amazonaws.com] 
+0

服務器參數故障是否從客戶端可見?作爲正常SSL協商的一部分,我已經看到過這些類型的錯誤,即從用戶的角度來看,它「起作用」。 – Taylor 2013-03-23 17:35:10

+0

對於Java 6,客戶端hello會回退到SSLv2,而對於Java 7,它似乎是使用TLSv1進行的。我相信Java 6下的JSSE並沒有正式支持SSL V2,但我需要研究 – 2013-03-23 17:42:05

+1

使用'openssl s_client -connect servername:443',你可以調試服務器支持的協議,並通過強制諸如'ssl2','' ssl2',勾選[this](http://www.openssl.org/docs/apps/s_client.html) – 2013-03-23 17:47:22

回答

18

布魯諾的答案最終是正確的。這個系統屬性最容易控制。這就是你如何能夠控制工廠方法返回的內容。例如,設置爲「TLSv1」。

+2

當您想要使用兩個協議而不是一個時會導致問題。例如'SSLv3'和'TLSv1'。如果嘗試連接SSLv3或TLSv1,此'-Dhttps.protocols = TLSv1,SSLv3'將導致異常。 – Dragon 2013-12-04 14:38:10

+1

@Dragon真的嗎?什麼例外?爲什麼? – EJP 2015-05-13 11:43:29

6

看來,在調試日誌Java 6請求是在發送格式SSLv2。 110

作爲默認在支持Java 7.
更改客戶端使用SSLv3和上述避免這種互操作性此沒有提及的SSLv2客戶端問候消息,長度=:

主,WRITE的問題。在Java 7

尋找在JSSE供應商的差異,並從客戶端的SSLSocket或HttpsURLConnection的啓用的協議Java 6

+0

是的,這是很好的證據,事實上SSLv2似乎是問題所在。這種導致我的答案在這裏,儘管@EJP是正確的,最好找到一種方法來明確地關閉SSLv2。 – 2013-03-24 05:55:04

4

刪除「SSLv2ClientHello」。

+0

我認爲這是完全正確的,但我不知道如何去做。我正在爲該平臺構建一個'SSLSocketFactory'。 'SSLContext.createSSLEngine()'生成一個'SSLEngine',它有方法來設置(不是刪除,似乎)協議。但我不認爲這有助於'SSLSocketFactory'。 'SSLContext'也只允許你請求一個協議,而不是禁用其他任何需要的(?)。如果你碰巧知道這是怎麼回事,讓我知道。 – 2013-03-24 05:54:01

+0

獲取啓用的協議,刪除「SSLv2ClientHello」,並將它們設置爲剩下的內容。 – EJP 2013-03-24 06:33:17

+0

雖然我不相信有這樣的方法。至少我不能在'SSLContext'或'SSLSocketFactory'上看到它。 'SSLEngine'沒有幫助我相信,因爲框架將在以後自己做。將繼續尋找。 – 2013-03-24 07:11:54

1

做這樣的:

SSLSocket socket = (SSLSocket) sslFactory.createSocket(host, port); 
socket.setEnabledProtocols(new String[]{"SSLv3", "TLSv1"}); 
3

更新從-Dhttps.protocols =的SSLv3到-Dhttps.protocols =使用TLSv1,SSLv3的