javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb82aeef8: Failure in SSL library, usually a protocol error

이전 글을 통해 서버에서 SSLv3를 지원하지 않는 경우가 있다고 말한바 있다. 사실 있는 정도가 아니라 이름만 들으면 아는 Twitter, Feedly, Facebook API, Amazon AWS 등에서 이미 SSLv3를 지원하지 않고 있다.

이 것이 안드로이드의 HTTPsUrlConnection을 만날 때 독특한 문제를 만들어낼 수 있다. HTTPsUrlConnection은 TLS Intolerance Support를 지원하기 때문에 TLS를 이용해 통신에 실패한 경우 ‘SSLv3’를 유일한 protocol로 설정하여 다시 서버에 접속을 시도한다.  TLS를 이용한 요청이 어떤 이유로 실패했을 때, HTTPsUrlConnection은 SSLv3를 이용하여 재시도하는데 이 때 서버에서 더이상 SSLv3를 지원하지 않는다면 SSLHandshakeException이 발생하게 된다.

이 때 발생하는 에러는 SSLv3의 SSLHandshakeException처럼 보일 수 있으나, 근본적인 원인은 처음에 TLS를 통한 요청이 실패한 것이다. 단순히 생각할 때 TLS 1.2가 실패했다면 TLS 1.1, 1.0 순으로 시도하며 요청해야할 것 같은데, HTTPsUrlConnection은 TLS Intolerance Support 정책에 따라 TLS 1.2이 실패한 경우 바로 SSLv3로 시도한다.

이미 SSLv3를 지원하지 않는 서버에 SSLv3로 시도하는 것은 잘못된 것이므로, 서버의 TLS가 정상이고 일회성으로 실패한 것이라면 SSLv3로 시도하는 대신에 default protocol list를 이용해 시도하도록 수정하는 것을 고려할만 하다. 이를 위한 수정 방법은 HttpUrlConnection에서 스스로 재시도 시 SSLv3을 유일한 protocol로 지정하지 못하도록 하고, 대신에 TLS를 이용해 재시도하도록 하는 것이다.

이를 위해 안드로이드 클라이언트가 수용할 수 있는 프로토콜 리스트에서 SSLv3를 제외하여, TLS만 사용하도록 구현한다. 자세한 수정사항은 스택오버플로우의 이 답변을 참고하자.

구현 내용을 간략히 설명하면 SSLSocketFactory를 상속받은 Factory를 만든 후(아래 답변에서는 NoSSLv3Factory라는 이름의 클래스) default procotol list를 이용해 재시도 하도록 한다. 추가로 프로토콜의 이름 목록 중 불필요한 SSLv3 제거한다.

참고로, 보안 패치를 정기적으로 하는 관리자가 운영하는 서버라면 SSLv3는 보통 꺼져있을 것이다.

참조 

“javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb82aeef8: Failure in SSL library, usually a protocol error”에 대한 1개의 생각

  1. 핑백: HttpsUrlConnection의 TLS Intolerance Support | Dog발자

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.