Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Błąd JDBC programu SQL Server w języku Java 8:sterownik nie może nawiązać bezpiecznego połączenia z programem SQL Server przy użyciu szyfrowania Secure Sockets Layer (SSL)

Włączyłem logowanie SSL w JVM Java 8 na instancji Linuksa, która odtwarza problem. Rejestrowanie SSL jest włączane za pomocą -Djavax.net.debug=ssl:handshake:verbose . To ujawniło kilka przydatnych informacji.

Obejście którego używamy w produkcji i sprawdził się dla nas, jest ustawienie tego parametru w JVM:

 -Djdk.tls.client.protocols=TLSv1

Jeśli chcesz uzyskać więcej informacji, czytaj dalej.

Na serwerze, na którym problem może się odtworzyć (ponownie, tylko w 5-10% przypadków), zaobserwowałem, co następuje:

*** 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

Zauważ, że TLSv1.2 jest wybierany przez serwer bazy danych i używany w tej wymianie. Zauważyłem, że gdy połączenia z problematyczną usługą linuksową zawodzą, TLSv1.2 jest ZAWSZE wybranym poziomem. Jednak połączenia NIE ZAWSZE kończą się niepowodzeniem, gdy używany jest protokół TLSv1.2. Nie udaje im się to tylko w 5-10% przypadków.

Teraz tutaj jest wymiana z serwera, który NIE ma problemu. Wszystko inne jest równe. Np. łączenie się z tą samą bazą danych, tą samą wersją JVM (Java 1.8.0_60), tym samym sterownikiem JDBC itp. Zauważ, że tutaj TLSv1 jest wybierany przez serwer bazy danych zamiast TLSv1.2, jak w przypadku wadliwego serwera.

*** 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

Tak więc, gdy protokół TLSv1 jest negocjowany między maszyną JVM systemu Linux i serwerem SQL, połączenia są ZAWSZE udane. Podczas negocjacji TLSv1.2 otrzymujemy sporadyczne awarie połączenia.

(Uwaga:Java 7 (1.7.0_51) zawsze negocjuje TLSv1, dlatego problem nigdy nie wystąpił u nas z Java 7 JVM.)

Nadal mamy otwarte pytania:

  1. DLACZEGO ta sama wirtualna maszyna Java 8 uruchomiona z 2 różnych serwerów Linux zawsze negocjuje TLSv1, ale podczas łączenia się z innym serwerem Linux zawsze negocjuje TLSv1.2.
  2. A także dlaczego wynegocjowane połączenia TLSv1.2 są skuteczne przez większość czasu, ale nie przez cały czas na tym serwerze?

Aktualizacja 6.10.2017: Ten post od firmy Microsoft opisuje problem i proponowane rozwiązanie.

Zasoby:

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, polityka nieograniczonej siły JCE i uzgadnianie SSL przez 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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak dodać lub upuścić kolumnę za pomocą graficznego interfejsu użytkownika w SQL Server — samouczek SQL Server / T-SQL, część 39

  2. Wywołanie API z procedury składowanej SQL Server

  3. Znajdź najbliższą datę w SQL Server

  4. Jaki jest najdłuższy możliwy numer telefonu na świecie, który powinienem wziąć pod uwagę w SQL varchar (długość) dla telefonu?

  5. Pisanie rekurencyjnego CTE przy użyciu składni Entity Framework Fluent lub składni wbudowanej