Translate

2016년 12월 9일 금요일

[JAVA] Received fatal alert: handshake_failure 오류




증상

1. HttpClient 를 이용해 서버(Tomcat)에 HTTPS 프로토콜 요청 및 응답 받는 로직
2. Tomcat 의 버전 6.0.36 => 6.0.45 업그레이드 시 오류가 발생





분석

try..catch 구문에서는 "IOException", "peer not authenticated" 라는 메시지가 나오며 통신오류가 발생했다.
1004lucifer
아래는 "java -Djavax.net.debug=all" 옵션을 이용해 디테일한 로그를 추출했다.


http-bio-9002-exec-7, setSoTimeout(20000) called
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1453345326 bytes = { 54, 203, 227, 17, 192, 221, 74, 47, 194, 163, 123, 78, 12, 6, 230, 251, 218, 209, 47, 176, 32, 80, 91, 7, 207, 75, 35, 68 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
***
http-bio-9002-exec-7, WRITE: TLSv1 Handshake, length = 75
http-bio-9002-exec-7, WRITE: SSLv2 client hello message, length = 101
http-bio-9002-exec-7, READ: TLSv1 Alert, length = 2
http-bio-9002-exec-7, RECV TLSv1 ALERT:  fatal, handshake_failure
http-bio-9002-exec-7, called closeSocket()
http-bio-9002-exec-7, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
http-bio-9002-exec-7, IOException in getSession():  javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
http-bio-9002-exec-7, called close()
http-bio-9002-exec-7, called closeInternal(true)
16.08.02 16:22:22[DEBUG][-bio-9002-exec-7](DefaultClientConnection.java: 165) Connection closed
16.08.02 16:22:22[DEBUG][-bio-9002-exec-7](DefaultClientConnection.java: 152) Connection shut down
http-bio-9002-exec-7, called close()
http-bio-9002-exec-7, called closeInternal(true)
16.08.02 16:22:22[DEBUG][-bio-9002-exec-7](SingleClientConnManager.java: 267) Releasing connection org.apache.http.impl.conn.SingleClientConnManager$ConnAdapter@29a3fb76
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:397)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:573)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
at com.domain.api.openapi.service.OpenApiService.doService(OpenApiService.java:433)
at com.domain.api.openapi.controller.OpenApiController.openApi(OpenApiController.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
16.08.02 16:22:22[DEBUG][-bio-9002-exec-7](AbstractMessageConverterMethodProcessor.java: 139) Written [{"header":{"resResult":"0","resMessage":"인터페이스 처리중 오류가 발생하였습니다.","errorCode":"IOException","errorMessage":"peer not authenticated"}}] as "application/json;charset=UTF-8" using [org.springframework.http.converter.StringHttpMessageConverter@729f624a]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
16.08.02 16:22:22[DEBUG][-bio-9002-exec-7](DispatcherServlet.java: 957) Null ModelAndView returned to DispatcherServlet with name 'open_api': assuming HandlerAdapter completed request handling
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
16.08.02 16:22:22[DEBUG][-bio-9002-exec-7](FrameworkServlet.java: 913) Successfully completed request
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
16.08.02 16:22:22[DEBUG][-bio-9002-exec-7](AbstractBeanFactory.java: 245) Returning cached instance of singleton bean 'sqlSessionFactory'
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:662)






해결방안

JAVA 버전을 1.6에서 1.7로 업그레이드 후 해결됨.
1004lucifer
공식홈페이지에서 톰캣의 6.0.36 / 6.0.45 두개의 버전에 대해서 달라진 점을 확인했지만 현재의 이슈에 대한건 발견하지 못했다. ㅠ



====================
2018.11.27 추가

Java6의 jsse.jar 소스와 위의 로그를 확인 시 Client에서 handshake fail 관련 코드를 준 것으로 보여진다.
위의 문제를 해결하기 위해서는 Client의 로그도 같이 확인해 봐야 정확한 진단이 가능하다는 생각이 든다.


다만 Tomcat 버전이 올라가면서 취약한 암호화알고리즘(Cipher Suites)를 사용하지 않도록 설정이 되었고, Java6의 암호화알고리즘 키제한 이슈로 인해 Java7 업데이트 시 문제가 사라진게 아닐까 생각이 든다.

링크 - [Java] JDK의 암호화 알고리즘 키 제한 이슈 (Illegal key size 오류)
링크 - [Java][WAS] 특정 브라우저에서 HTTPS 접속 시 화면이 보이지 않는경우 (Cipher Suites 이슈)
====================



참고
http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/ReadDebug.html
https://www.lesstif.com/pages/viewpage.action?pageId=29590407
http://stackoverflow.com/questions/30828759/thread-6-recv-tlsv1-alert-fatal-handshake-failure



댓글 없음 :

댓글 쓰기