Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server JDBC-Fehler unter Java 8:Der Treiber konnte keine sichere Verbindung zu SQL Server mithilfe der SSL-Verschlüsselung (Secure Sockets Layer) herstellen

Ich habe die SSL-Protokollierung in der Java 8 JVM auf einer Linux-Instanz aktiviert, die das Problem reproduziert. Die SSL-Protokollierung wird mit -Djavax.net.debug=ssl:handshake:verbose aktiviert . Dabei kamen einige nützliche Informationen ans Licht.

Die Problemumgehung die wir in der Produktion verwenden und die sich für uns bewährt hat, besteht darin, diesen Parameter auf der JVM zu setzen:

 -Djdk.tls.client.protocols=TLSv1

Wenn Sie weitere Einzelheiten wünschen, lesen Sie bitte weiter.

Auf einem Server, auf dem das Problem reproduziert werden kann (wiederum nur in 5-10 % der Fälle), habe ich Folgendes beobachtet:

*** ClientHello, TLSv1.2
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 195
main, READ: TLSv1.2 Handshake, length = 1130
*** ServerHello, TLSv1.2
--- 8<-- SNIP -----
%% Initialized:  [Session-79, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256]
** TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----
*** Diffie-Hellman ServerKeyExchange
--- 8<-- SNIP -----
*** ServerHelloDone
*** ClientKeyExchange, DH
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 133
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data:  { 108, 116, 29, 115, 13, 26, 154, 198, 17, 125, 114, 166 }
***
main, WRITE: TLSv1.2 Handshake, length = 40
main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT:  warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)
main, waiting for close_notify or alert: state 5
main, received EOFException: ignored
main, called closeInternal(false)
main, close invoked again; state = 5
main, handling exception: java.io.IOException: SQL Server returned an incomplete response. The connection has been closed. ClientConnectionId:12a722b3-d61d-4ce4-8319-af049a0a4415

Beachten Sie, dass TLSv1.2 wird vom Datenbankserver ausgewählt und in diesem Austausch verwendet. Ich habe beobachtet, dass, wenn Verbindungen vom problematischen Linux-Dienst fehlschlagen, TLSv1.2 IMMER die ausgewählte Ebene ist. Verbindungen schlagen jedoch nicht IMMER fehl, wenn TLSv1.2 verwendet wird. Sie versagen nur in 5–10 % der Fälle.

Hier ist jetzt ein Austausch von einem Server, der das Problem NICHT hat. Alles andere ist gleich. Das heißt, eine Verbindung mit derselben Datenbank, derselben Version der JVM (Java 1.8.0_60), demselben JDBC-Treiber usw. Beachten Sie, dass hier TLSv1 wird vom Datenbankserver anstelle von TLSv1.2 wie im Fall des fehlerhaften Servers ausgewählt.

*** ClientHello, TLSv1.2
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 207
main, READ: TLSv1 Handshake, length = 604
*** ServerHello, TLSv1
--- 8<-- SNIP -----
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA
--- 8<-- SNIP -----
%% Initialized:  [Session-79, TLS_RSA_WITH_AES_128_CBC_SHA]
** TLS_RSA_WITH_AES_128_CBC_SHA
--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----
***
*** ServerHelloDone
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
--- 8<-- SNIP -----
main, WRITE: TLSv1 Handshake, length = 134
main, WRITE: TLSv1 Change Cipher Spec, length = 1
*** Finished
verify_data:  { 26, 155, 166, 89, 229, 193, 126, 39, 103, 206, 126, 21 }
***
main, WRITE: TLSv1 Handshake, length = 48
main, READ: TLSv1 Change Cipher Spec, length = 1
main, READ: TLSv1 Handshake, length = 48
*** Finished

Wenn also TLSv1 zwischen der Linux-JVM und dem SQL Server ausgehandelt wird, sind Verbindungen IMMER erfolgreich. Wenn TLSv1.2 ausgehandelt wird, kommt es zu sporadischen Verbindungsabbrüchen.

(Hinweis:Java 7 (1.7.0_51) handelt immer TLSv1 aus, weshalb das Problem bei uns mit einer Java 7 JVM nie aufgetreten ist.)

Die offenen Fragen, die wir noch haben, sind:

  1. WARUM ist, dass die gleiche Java 8 JVM, die von zwei verschiedenen Linux-Servern ausgeführt wird, immer TLSv1 aushandelt, aber wenn eine Verbindung von einem anderen Linux-Server hergestellt wird, verhandelt sie immer TLSv1.2.
  2. Und warum sind über TLSv1.2 ausgehandelte Verbindungen meistens, aber nicht immer, auf diesem Server erfolgreich?

Aktualisierung vom 10.06.2017: Dieser Beitrag von Microsoft beschreibt das Problem und die vorgeschlagene Lösung.

Ressourcen:

http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html

http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html

http://blogs.msdn.com/b/jdbcteam/archive/2008/09/09/the-driver-could-not-making-a-secure-connection-to-sql-server-by-using-secure- sockets-layer-ssl-verschlüsselung.aspx

Java 8 , JCE Unlimited Strength Policy und SSL-Handshake über TLS

http://blogs.msdn.com/b/saponsqlserver/archive/2013/05/10/analyzing-jdbc-connection-issues.aspx

https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#descPhase2

https://blogs.oracle.com/java-platform-group/entry/java_8_will_use_tls