web-dev-qa-db-fra.com

Réception de SSLHandshakeException: handshake_failure malgré que mon client ignore tous les certificats

J'ai un programme Java qui se connecte à un serveur Web à l'aide de SSL/TLS et envoie diverses demandes HTTP via cette connexion. Le serveur est localhost et utilise un certificat auto-signé, mais mon code est à l'aide de TrustManagers personnalisés et ignore les certificats non valides. Cela a fonctionné parfaitement jusqu'à présent.

La seule différence sur le serveur est qu'il exécutait jboss 6 et exécute maintenant jboss 7. Je ne sais pas s'il s'agit d'un problème de configuration ou s'il y a un problème avec mon code, mais j'obtiens les mêmes erreurs si J'essaie de me connecter en utilisant d'autres programmes basés sur Java comme WebScarab ou ZAP.

Dans tous les cas, puis-je faire quelque chose pour mon code pour contourner ce problème? Voici l'erreur dans son intégralité:

Received fatal alert: handshake_failure
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at com.Sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.Sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(Unknown Source)
        at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at Sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
        at Sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
        at Sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)

Voici les messages de débogage avant l'échec:

main, WRITE: TLSv1 Handshake, length = 75
main, WRITE: SSLv2 client hello message, length = 101
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, handshake_failure
19
Rsaesha

J'ai donc trouvé le problème. Il peut y avoir un bogue dans Java, mais le client semble initier une prise de contact TLSv1, mais envoie ensuite un message de bienvenue au client SSLv2, auquel cas le serveur rejette la connexion.

Cela se produit même si vous créez votre SSLContext avec une instance de TLS:

SSLContext sslContext = SSLContext.getInstance("TLS");

La solution consiste à définir une propriété système avant toute tentative de connexion:

System.setProperty("https.protocols", "TLSv1");

Il y a probablement d'autres solutions, mais celle-ci a fonctionné pour moi.

25
Rsaesha

Cela a-t-il déjà été résolu?

J'ai eu exactement le même problème, essentiellement je recevais une exception de poignée de main immédiatement après le client Bonjour. Donc, la chaîne d'événements était

  1. Je présenterais mon certificat au serveur
  2. Le serveur répondrait immédiatement par un échec de prise de contact. (Je n'obtiendrais même pas de serveur Bonjour).

Finalement, j'ai trouvé que le serveur exigeait un algorithme de chiffrement/déchiffrement plus fort que ce que je fournissais dans la phase de négociation initiale (c'est-à-dire que le client et le serveur ne pouvaient pas s'entendre sur un algorithme de chiffrement mutuel à utiliser pour la communication SSL).

J'ai besoin d'installer le Unlimited Java JCE (Java Cryptography Extension Policy). Il y a des règles d'exportation sur son utilisation, donc si vous expédiez votre code à l'étranger cela peut avoir des implications .. cependant c'est ce qui a résolu mon problème.

Ce lien explique comment installer les politiques mises à jour http://suhothayan.blogspot.com/2012/05/how-to-install-Java-cryptography.html

C'était aussi un excellent lien qui m'a aidé à comprendre exactement ce qui se passait https://support.f5.com/kb/en-us/solutions/public/15000/200/sol15292.html#id =

Cela peut ou non être le problème, mais lorsque la prise de contact échoue immédiatement après le client Bonjour, il semble que le client et le serveur ne peuvent pas s'entendre sur quelque chose (dans de nombreux cas, ce sont les algorithmes de chiffrement dont ils auront besoin mutuellement pour communiquer).

4
DMHarris

Les informations que vous fournissez sont très peu ainsi que votre trace de pile.
Je vais deviner ici.
Ce que je soupçonne, c'est que sur le nouveau serveur, le protocole est TLSv1 pendant que vos clients essaient de se connecter avec SSLv3 (ou moins) et que la prise de contact échoue.

Changer vos clients pour utiliser une version supérieure de TLS ou
Faites en sorte que votre serveur Web prenne également en charge SSLv3. Je sais comment faire cela dans Tomcat mais pas dans JBoss.

Si cela ne fonctionne pas, mettez à jour la publication avec plus d'informations (et une trace complète de la pile).
Vous devez activer les informations de débogage ssl -Djavax.net.debug=ssl

4
Cratylus

Vous voyez probablement cette erreur car le magasin de clés auquel votre JBoss 6 avait accès n'est pas accessible à votre instance de JBoss 7.

Ce que je recommanderais est le suivant.

Votre certificat de serveur auto-signé doit être importé dans un magasin de clés de confiance

keytool -import -alias gridserver -file server.crt -storepass $YOUR_PASSWORD_HERE -keystore server.keystore

Ajoutez les propriétés suivantes à votre run.conf

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=server.keystore
-Djavax.net.debug=ssl # very verbose debug. Turn this off after everything looks good.
-Djavax.net.ssl.keyStorePassword=$YOUR_PASSWORD_HERE
-Djavax.net.ssl.trustStorePassword=$YOUR_PASSWORD_HERE
1
uaarkoti

La trace de la pile provient de votre code client et de votre client "Reçu [une] alerte fatale". En d'autres termes, l'erreur SSL s'est produite dans Jboss, pas dans votre client.

Vos TrustManagers personnalisés côté client n'ont donc rien à voir avec cela. Je suppose que votre nouveau Jboss 7 est configuré pour exiger un certificat client et que votre client n'en a pas présenté.

Pour déboguer votre connexion SSL, utilisez openssl et essayez ceci:

openssl s_client -connect jboss.server.com:443

ou est-ce un serveur SSLV3

openssl s_client -connect jboss.server.com:443 -ssl3

Cela devrait imprimer beaucoup d'informations intéressantes.

0
Bruno Grieder

Je pense que cela est lié à un bogue Java 7 . Il est difficile d'être sûr sans plus de détails.

0
Michael Munsey

Pour moi, la solution était: System.setProperty("https.protocols", "TLSv1.1,TLSv1.2");

0
Mahmoud Saleh