Exceptions aléatoires «non authentifiées par des pairs» avec Java SSLContextImpl $ TLS10Context

J’obtiens des échecs de connexion qui apparaissent aléatoirement lors de la connexion à un serveur HAProxy via SSL. J’ai confirmé que ces échecs se produisent sur les versions 1.7.0_21 et 1.7.0_25 de JDK, mais pas avec 1.7.0_04 ou 1.6.0_38.

L’exception est

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397) at SSLTest2.main(SSLTest2.java:52) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 

Ces échecs ne se produisent que lorsque vous utilisez le contexte SSL TLS et non avec le contexte par défaut. Le code suivant est exécuté en boucle mille fois et les échecs se produisent avant la fin de la boucle (environ 2% des connexions échouent):

 SSLContext sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(null, null, null); SSLSocketFactory factory = sslcontext.getSocketFactory(); SSLSocket socket = (SSLSocket)factory.createSocket("myserver", 443); //socket.startHandshake(); SSLSession session = socket.getSession(); session.getPeerCertificates(); socket.close(); 

Si, cependant, je crée le contexte SSL de cette façon, je n’ai aucune défaillance de connexion sur aucune des versions de Java que j’ai mentionnées:

 SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault(); 

La première méthode utilise SSLContextImpl$TLS10Context et la dernière utilise SSLContextImpl$DefaultSSLContext . En regardant le code, je ne vois aucune différence susceptible d’entraîner une exception.

Pourquoi devrais-je obtenir les échecs et quels sont les avantages / inconvénients de l’utilisation de l’appel getDefault() ?

Remarque: Les exceptions ont été observées pour la première fois avec Apache HttpClient (version 4). Ce code est le plus petit sous-ensemble qui reproduit le problème rencontré avec HttpClient.

Voici l’erreur que je vois en ajoutant -Djavax.net.debug=ssl :

 main, READ: TLSv1 Alert, length = 2 main, RECV TLSv1 ALERT: fatal, bad_record_mac %% Invalidated: [Session-101, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA] main, called closeSocket() main, handling exception: javax.net.ssl.SSLException: Received fatal alert: bad_record_mac main, IOException in getSession(): javax.net.ssl.SSLException: Received fatal alert: bad_record_mac 

Une autre information est que les erreurs ne se produisent pas si je désactive Diffie-Hellman sur le serveur proxy.

À en juger par les symptômes, je suppose que cela est lié aux navigateurs utilisant le faux démarrage TLS , un tour côté client lancé par Google pour réduire les va-et-vient dans TLS :

False Start est largement contrôlé par le navigateur et fonctionne en réduisant les deux passes aller-retour de données décrites dans les spécifications SSL officielles à un seul aller-retour. Pour ce faire, il a demandé au client d’envoyer les premiers messages ApplicationData dans un seul envoi plutôt que de les placer dans deux packages distincts et d’envoyer le second uniquement après avoir reçu une confirmation du serveur.

Google a proposé False Start comme norme officielle pour rendre SSL plus acceptable pour les sites Web qui le trouvent actuellement trop coûteux à offrir. En abrégeant le protocole de négociation qui négocie la clé de cryptage et les autres variables nécessaires à la protection des données transmises entre l’utilisateur final et le site Web, False Start visait à réduire les problèmes de performances liés à l’utilisation du protocole.

De la question pertinente soulevée dans Mozilla Firefox : (souligne le mien)

Jusqu’à présent, une liste incomplète de produits connus pour présenter des problèmes de compatibilité actuels ou antérieurs avec False Start inclut (AFAICT): F5, A10, Microsoft TMG, Cisco ASA, ServerIron ADX, ESET, NetNanny, certaines configurations de l’implémentation du serveur SSL Java .

javax.net.ssl.SSLPeerUnverifiedException se pose uniquement à cause de la sécurité HTTP. Vous devez configurer votre connexion comme https sinon ce code ..

  SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, new TrustManager[]{tm}, null); SSLSocketFactory ssf = new SSLSocketFactory(ctx); ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = client.getConnectionManager(); SchemeRegistry sr = ccm.getSchemeRegistry(); sr.register(new Scheme("https", ssf, 443)); return new DefaultHttpClient(ccm, client.getParams()); 

utilisez ceci. J’espère que cela vous aidera