GNU/Linux >> Tutoriels Linux >  >> Linux

Erreur SQL Server JDBC sur Java 8 :le pilote n'a pas pu établir de connexion sécurisée à SQL Server à l'aide du chiffrement SSL (Secure Sockets Layer)

J'ai activé la journalisation SSL dans la JVM Java 8 sur une instance Linux qui reproduit le problème. La journalisation SSL est activée à l'aide de -Djavax.net.debug=ssl:handshake:verbose . Cela a révélé des informations utiles.

La solution de contournement que nous utilisons en production et qui a fait ses preuves consiste à définir ce paramètre sur la JVM :

 -Djdk.tls.client.protocols=TLSv1

Si vous voulez plus de détails, lisez la suite.

Sur un serveur où le problème peut être reproduit (là encore, seulement 5 à 10 % du temps), j'ai observé ce qui suit :

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

Notez que TLSv1.2 est sélectionné par le serveur de base de données et utilisé dans cet échange. J'ai observé que, lorsque les connexions échouent à partir du service linux problématique, TLSv1.2 est TOUJOURS le niveau qui a été sélectionné. Cependant, les connexions n'échouent pas TOUJOURS lorsque TLSv1.2 est utilisé. Ils échouent seulement 5 à 10 % du temps.

Voici maintenant un échange d'un serveur qui n'a PAS le problème. Tout le reste est égal. C'est-à-dire, se connecter à la même base de données, même version de la JVM (Java 1.8.0_60), même pilote JDBC, etc. Notez que, ici, TLSv1 est sélectionné par le serveur de base de données au lieu de TLSv1.2 comme dans le cas du serveur défectueux.

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

Ainsi, lorsque TLSv1 est négocié entre la JVM Linux et le serveur SQL, les connexions réussissent TOUJOURS. Lorsque TLSv1.2 est négocié, nous obtenons des échecs de connexion sporadiques.

(Remarque :Java 7 (1.7.0_51) négocie toujours TLSv1, c'est pourquoi le problème ne s'est jamais produit pour nous avec une JVM Java 7.)

Les questions ouvertes que nous avons encore sont :

  1. Pourquoi est-ce que la même JVM Java 8 exécutée à partir de 2 serveurs Linux différents négociera toujours TLSv1, mais lors de la connexion à partir d'un autre serveur Linux, elle négocie toujours TLSv1.2.
  2. Et pourquoi les connexions négociées TLSv1.2 réussissent-elles la plupart du temps, mais pas toujours, sur ce serveur ?

Mise à jour du 10/06/2017 : Cette publication de Microsoft décrit le problème et la solution proposée.

Ressources :

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 et SSL Handshake over 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


Cela semble avoir été corrigé dans la version 4.2 du pilote MS SQL JDBC. J'ai créé un programme où je me suis connecté au serveur 1000 fois, en faisant une pause de 100 ms entre chaque tentative. Avec la version 4.1, j'ai pu reproduire le problème à chaque fois, même si cela ne s'est produit que sporadiquement. Avec la version 4.2, je n'ai pas pu reproduire le problème.


Avant de mettre à niveau le pilote SQL JDBC, vérifiez d'abord la compatibilité :

  • Sqljdbc.jar nécessite un JRE de 5 et prend en charge l'API JDBC 3.0
  • Sqljdbc4.jar nécessite un JRE de 6 et prend en charge l'API JDBC 4.0
  • Sqljdbc41.jar nécessite un JRE de 7 et prend en charge l'API JDBC 4.1
  • Sqljdbc42.jar nécessite un JRE de 8 et prend en charge l'API JDBC 4.2

Source :https://www.microsoft.com/en-us/download/details.aspx?id=11774


Linux
  1. Comment sécuriser votre serveur ISPConfig 3 contre l'attaque SSL caniche

  2. Comment réparer Windows n'a pas pu analyser ou traiter le fichier de réponse sans assistance pour Pass Specialize

  3. Modifier le délai d'attente MySQL sur un serveur

  4. FATAL :erreur de module introuvable à l'aide de modprobe

  5. Utilisation d'openssl pour obtenir le certificat d'un serveur

Comment réparer l'erreur de connexion SSH refusée

Correction :Impossible d'établir une connexion FTP avec un serveur SFTP dans FileZilla

Dépannage :erreurs de connexion au serveur

Tmux ne source pas le .tmux.conf ?

Erreur FTP :Impossible de se connecter au serveur - La stratégie 534 nécessite SSL

Correction d'une erreur de tuyau cassé avec une connexion SSH