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.
Proszę ponownie uruchomić z -Djavax.net.debug = ssl, uzgadnianie i opublikuj dane wyjściowe z nieudanego uruchomienia. – EJP
Wykonano ponownie z włączoną opcją debugowania. Zaktualizowano pytanie, podając te informacje. Czy ktoś ma jakieś pomysły? – user2687486
Dlaczego preferujesz cztery linie kodu do jednego? – EJP