2013-08-15 7 views
50

Otrzymuję awarie połączeń, które pojawiają się losowo podczas łączenia się z serwerem HAProxy za pomocą protokołu SSL. Potwierdziłem, że te awarie występują w JDK w wersji 1.7.0_21 i 1.7.0_25, ale nie w wersji 1.7.0_04 lub 1.6.0_38.

Wyjątkiem jest

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) 

Te awarie tylko wtedy, gdy przy użyciu protokołu SSL i TLS kontekst nie z kontekstu domyślnego. Poniższy kod jest uruchamiany w pętli tysiąc razy i porażki wydarzyć przed zakończeniem pętli (około 2% połączeń 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(); 

Jeśli jednak utworzyć kontekstu SSL ten sposób nie mam połączenia awarie na żadnej z wersji Java wspominałem:

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

pierwszy sposób wykorzystuje SSLContextImpl$TLS10Context a później wykorzystuje SSLContextImpl$DefaultSSLContext. Patrząc na kod, nie widzę żadnych różnic, które spowodowałyby wystąpienie wyjątku.

Dlaczego otrzymam awarie i jakie są zalety/wady korzystania z połączenia getDefault()?

Uwaga: wyjątki zostały po raz pierwszy zaobserwowane za pomocą Apache HttpClient (wersja 4). Ten kod jest najmniejszym podzbiorem, który odtwarza problem związany z HttpClient.

Oto widzę błąd podczas dodawania -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 

Kolejną informacją jest to, że błędy nie występują, jeśli mogę wyłączyć DiffieHellman na serwerze proxy.

+3

Proszę ponownie uruchomić z -Djavax.net.debug = ssl, uzgadnianie i opublikuj dane wyjściowe z nieudanego uruchomienia. – EJP

+0

Wykonano ponownie z włączoną opcją debugowania. Zaktualizowano pytanie, podając te informacje. Czy ktoś ma jakieś pomysły? – user2687486

+0

Dlaczego preferujesz cztery linie kodu do jednego? – EJP

Odpowiedz

1

Sądząc po objawach, jestem zgadywania jest to związane z przeglądarkami za pomocą TLS false start, który jest sztuczka po stronie klienta Google wprowadził do reduce the back-and-forth in TLS:

Fałsz Start jest w dużej mierze kontrolowane przez przeglądarkę i działa poprzez zredukowanie dwóch obiegowych przebiegów danych opisanych w oficjalnych specyfikacjach SSL do pojedynczego przejazdu w obie strony. Zrobił to, polecając klientowi wysłanie komunikatów Zakończone i pierwszych Danych Aplikacji w jednej wysyłce, zamiast umieszczania ich w dwóch odrębnych paczkach i wysyłanie drugiej tylko po otrzymaniu potwierdzenia z serwera.

Firma Google zaproponowała False Start jako oficjalny standard, aby uczynić SSL bardziej przyjaznym dla stron, które obecnie są zbyt drogie do zaoferowania. Skracając handshake, który negocjuje klucz szyfrowania i inne zmienne potrzebne do ochrony danych przechodzących między użytkownikiem końcowym a witryną internetową, False Start miał na celu obniżenie kary za wydajność, o której wielu twierdzi, że używa protokołu.

Z relevant issue raised in Mozilla Firefox: (kopalnia nacisk)

Dotychczas niekompletny wykaz produktów, które są znane posiadają aktualne lub wcześniejsze problemy ze zgodnością falstart include (AFAICT): F5, A10, Microsoft TMG, Cisco ASA, ServerIron ADX, ESET, NetNanny, niektóre konfiguracje implementacji serwera SSL Javy.

+0

Połączenie, w przypadku OP, a także w moim przypadku, jest pomiędzy klientem napisanym w JAVA a serwerem (proxy lub http). Bez przeglądarki tutaj ... –

+0

@ LorenzoDematté Aah, oczywiście, masz rację. Nie mogę uwierzyć, że to przegapiłem. – JvR

-3

javax.net.ssl.SSLPeerUnverifiedException wynikać tylko z powodu bezpieczeństwa http trzeba skonfigurować połączenie https inny śledzić ten kod ..

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

używać. Mam nadzieję, że pomoże ci

+3

Po prostu wprowadzasz lukę w zabezpieczeniach z "ALLOW_ALL_HOSTNAME_VERIFIER", to nie pomaga. – Bruno

+0

To wcale nie "powstaje tylko z powodu bezpieczeństwa HTTP". Nie ma nic wspólnego z HTTPS. Zdarza się to w warstwie TLS. – EJP

Powiązane problemy