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



2016년 12월 5일 월요일

[Outlook] 0x8004DF0B 오류가 발생하며 동기화 에러문제




SW version: Outlook 2010

mail: Google Gmail



증상

Google 회사 메일을 Outlook 연동하여 동기화 하려할 시 아래와 같이 나오며 정상적으로 동기화가 되지 않는다.
1004lucifer



'id@domain의 등록된 폴더를 동기화하는 중입니다.' 작업에서 다음 오류(0x8004DF0B)가 발생했습니다 : 'id@domain의 등록된 폴더를 동기화할 수 없습니다. 오류: 서버에 연결할 수 없습니다. 이 작업을 완료하려면 Outlook이 온라인 상태이거나 연결 상태가 '연결됨'이어야 합니다. 이 메시지가 계속 표시되면 서버 관리자 또는 인터넷 서비스 공급자(ISP)에게 문의하십시오.'






원인 및 해결방법

이상하게도 gmail.com 의 메일은 정상적으로 Outlook 에서 동기화가 되는데 회사메일 회사도메인의 gmail 은 위와같은 증상이 발생을 한다.
1004lucifer
정확한 정보가 나와있는 웹페이지를 볼수는 없었지만 Outlook 2010의 경우에는 예전 보안 프로토콜을 사용하기 때문에 구글의 '보안 수준이 낮은 앱의 액세스'를 활성화 시켜줘야 한다고 한다.

아래의 링크에서 '보안 수준이 낮은 앱의 액세스' 를 활성화 시킬 수 있다.
https://www.google.com/settings/security/lesssecureapps


위의 옵션을 활성화 시킨 후 Outlook 을 켜면 당장은 안될 수 있지만 시간이 지나고나서 동기화가 된다.





PS.
오랜시간 뒤에 컴퓨터를 재부팅 하거나 Outlook을 껐다가 다시켜면 또 위와같은 문제가 발생하는 경우가 있는데 '보안 수준이 낮은 앱의 액세스'를 비활성 했다가 다시 활성화 후 Outlook 을 켜면 된다.
1004lucifer
왜 구글 기업메일만 문제가 발생을 하는지는 모르겠다.