2013-08-15 8 views
50

Ottengo errori di connessione visualizzati casualmente quando ci si connette a un server HAProxy tramite SSL. Ho confermato che questi errori si verificano nelle versioni di JDK 1.7.0_21 e 1.7.0_25 ma non con 1.7.0_04 o con 1.6.0_38.

L'eccezione è

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) 

Questi fallimenti si verificano solo quando si utilizza il contesto SSL TLS e non con il contesto predefinito. Il seguente codice viene eseguito in un ciclo mille volte e fallimenti accadere prima del ciclo completa (circa il 2% delle connessioni FAIL):

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(); 

Se, invece, creo il contesto SSL in questo modo non ho collegamenti fallimenti su una qualsiasi delle versioni di Java che ho citato:

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

il primo modo utilizza SSLContextImpl$TLS10Context e la successiva utilizza SSLContextImpl$DefaultSSLContext. Guardando il codice, non vedo alcuna differenza che possa causare l'eccezione.

Perché dovrei ottenere i guasti e quali sono i vantaggi/gli svantaggi dell'utilizzo della chiamata getDefault()?

Nota: le eccezioni sono state visualizzate per la prima volta utilizzando Apache HttpClient (versione 4). Questo codice è il sottoinsieme più piccolo che riproduce il problema riscontrato con HttpClient.

Ecco l'errore che vedo quando si aggiunge -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 

Un altro pezzo di informazione è che gli errori non si verificano se spengo Diffie-Hellman sul server proxy.

+3

Per favore ri-esegui con -Djavax.net.debug = ssl, handshake e pubblica un output da una corsa fallita. – EJP

+0

Ancora in esecuzione con l'opzione di debug attivata. Aggiornata la domanda con queste informazioni. Qualcuno ha qualche idea? – user2687486

+0

Perché preferisci quattro righe di codice a una? – EJP

risposta

1

giudicare dai sintomi, sono indovinando questo è legato al browser utilizzando TLS false start, che è un trucco sul lato client Google ha introdotto a reduce the back-and-forth in TLS:

False Start è in gran parte controllata dal browser e funziona riducendo i due passaggi di andata e ritorno dei dati descritti nelle specifiche SSL ufficiali ad un singolo pass di andata e ritorno. Ciò è stato fatto istruendo il client a inviare i messaggi Fine e primo ApplicationData in una singola distribuzione piuttosto che inserirli in due pacchetti distinti e inviare il secondo solo dopo aver ricevuto conferma dal server.

Google ha proposto False Start come standard ufficiale per rendere l'SSL più appetibile per i siti Web che attualmente lo trovano troppo costoso da offrire. Abbreviando la stretta di mano che negozia la chiave di crittografia e altre variabili necessarie per proteggere i dati che passano tra l'utente finale e il sito Web, False Start ha lo scopo di ridurre la penalità delle prestazioni che molti dicono derivano dall'uso del protocollo.

Dalla relevant issue raised in Mozilla Firefox: (sottolineatura mia)

Finora, un elenco incompleto di prodotti che sono noti per avere problemi di compatibilità attuali o precedenti con False Start includono (AFAICT): F5, A10, Microsoft TMG, Cisco ASA, ServerIron ADX, ESET, NetNanny, alcune configurazioni dell'implementazione del server SSL Java.

+0

La connessione, nel caso dell'OP e anche nel mio caso, è tra un client scritto in JAVA e un server (proxy o http). Nessun browser qui ... –

+0

@ LorenzoDematté Aah, certo, hai ragione. Non posso credere di averlo perso. – JvR

-3

javax.net.ssl.SSLPeerUnverifiedException sorgere solo per motivi di sicurezza http è necessario configurare la connessione https come il resto seguire questo codice ..

  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()); 

uso questo. spero che ti possa aiutare

+3

Stai appena introducendo una vulnerabilità della sicurezza con "ALLOW_ALL_HOSTNAME_VERIFIER", che non aiuta. – Bruno

+0

Non si presenta affatto solo a causa della sicurezza HTTP. Non ha nulla a che fare con HTTPS. Succede al livello TLS. – EJP