Ik heb SSL-logboekregistratie ingeschakeld in de Java 8 JVM op een Linux-instantie die het probleem reproduceert. SSL-registratie is ingeschakeld met -Djavax.net.debug=ssl:handshake:verbose
. Dit leverde nuttige informatie op.
De oplossing die we gebruiken in de productie en waarvan bewezen is dat ze voor ons werken, is door deze parameter op de JVM in te stellen:
-Djdk.tls.client.protocols=TLSv1
Als je meer details wilt, lees dan verder.
Op een server waar het probleem kan worden gereproduceerd (wederom, slechts 5-10% van de tijd), merkte ik het volgende op:
*** 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
Merk op dat TLSv1.2 wordt geselecteerd door de databaseserver en gebruikt in deze uitwisseling. Ik heb opgemerkt dat, wanneer verbindingen van de problematische linux-service mislukken, TLSv1.2 ALTIJD het geselecteerde niveau is. Verbindingen mislukken echter niet ALTIJD wanneer TLSv1.2 wordt gebruikt. Ze falen slechts 5-10% van de tijd.
Nu is hier een uitwisseling van een server die het probleem NIET heeft. Al het andere is gelijk. D.w.z. verbinding maken met dezelfde database, dezelfde versie van de JVM (Java 1.8.0_60), hetzelfde JDBC-stuurprogramma, enz. Merk op dat hier TLSv1 wordt geselecteerd door de databaseserver in plaats van TLSv1.2 zoals in het geval van de defecte server.
*** 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
Dus wanneer TLSv1 wordt onderhandeld tussen de Linux JVM en de SQL Server, zijn verbindingen ALTIJD succesvol. Wanneer TLSv1.2 wordt onderhandeld, krijgen we sporadische verbindingsfouten.
(Opmerking:Java 7 (1.7.0_51) onderhandelt altijd over TLSv1, daarom is het probleem bij ons nooit opgetreden met een Java 7 JVM.)
De open vragen die we nog hebben zijn:
- WAAROM is dat dezelfde Java 8 JVM die vanaf 2 verschillende Linux-servers wordt uitgevoerd, altijd over TLSv1 zal onderhandelen, maar wanneer er verbinding wordt gemaakt vanaf een andere Linux-server, wordt altijd onderhandeld over TLSv1.2.
- En waarom zijn TLSv1.2-onderhandelde verbindingen meestal succesvol, maar niet altijd, op die server?
Update 6/10/2017: Dit bericht van Microsoft beschrijft het probleem en de voorgestelde oplossing.
Bronnen:
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-establish-a-secure-connection-to-sql-server-by-using-secure- sockets-layer-ssl-encryption.aspx
Java 8, JCE Unlimited Strength Policy en SSL Handshake via 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