삽질하며 배운 ssl certificate verification(ruby의 json client는 쓰지 말자.)

우리 서버에서 사용하던 private api 중 하나가 도메인 변경을 하며 기존 http 요청하던 것을 https로 요청해줄 것을 요청했다. 너무나도 쉽지만 여러 프로젝트의 코드 상에 박혀 있는 도메인을 바꿔서 배포하기만 하면 되는 그저 짜치는 업무 정도로만 생각했다. 순조롭게 짜치는 작업들을 이어가던 중에 ruby on rails으로 이루어진 프로젝트의 베타 단계 서버를 배포하던 중에 에러가 발생했다.

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

?????? 몇가지 가능성을 생각해봤지만 간단하게 답이 나오지는 않았다.

  1. 해당 서버의 문제(인증서 등)은 아닌 것 같다.
    • 해당 프로젝트에서 다른 api를 호출할 때는 https를 이미 잘 활용하고 있었다.
    • 그런데 현재 변경 작업 중인 api만 jsonclient를 이용해서 클라이언트가 구현돼 있었다.
  2. 코드 레벨의 문제도 아닌 것 같다.
    • 알파 / 샌박에서는 잘 됐다.
    • 그런데 알파 / 샌박과 os 버전이 다르다.
    • 그런데 jsonclient는 ssl 처리 과정에서 os version에 따라 다르게 동작하는 로직이 없다.
  3. 상대 서버의 문제도 아니다.
    • 베타 서버의 cli에서 curl을 보내면 이상 없이 응답한다.

위의 조건들을 하나씩 찾아내고, 다 찾으며 수 많은 삽질을 한 끝에 문제는 jsonclient가 사용하는 인증서의 문제였다. jsonclient는 다른 httpclient들과는 다르게 본인들의 소스코드에 인증서를 직접 넣어놓고 이를 통해 verification 작업을 하도록 했다. 그런데 문제는 이 인증서가 가장 최근에 업데이트 된 것이 3년 전이라는 것이다. 이 인증서를 증명해준 상위 인증서들이 이미 폐기된것이고 그래서 이 인증서를 verification하는 작업에 실패했다는 것이 우리의 결론이 되었다.

TLS(ssl의 상위 버전 표준)의 세 가지 중요한 역할은 암호화, 인증 무결성 보장이다. 이때 인증이란 데이터를 주고 받는 상대가 믿을만한 상대인지 확인하는 것이다. 클라이언트 – 서버 구조에서는 클라이언트가 서버를 인증하게 된다.

인증을 위해, TLS handshake 과정에서 서버는 클라이언트에게 인증서를 보내주고, 클라이언트는 이 인증서로 상대가 믿을만한 상대인지 확인한다.

<여기에 인증서 신뢰 사슬에 대해 설명을 나중에 좀 업데이트 하겠다.>

하지만 여전히 풀리지 않는 의문이 우릴 헷갈리게 했는데, jsonclient가 사용하는 인증서가 문제라면 알파 / 샌박 단계에서는 왜 무사히 테스트를 통과했는가이다.

다시 한번 수 많은 삽질을 한 끝에 정의한 넓은 범위의 가설은 jsonclient의 동작과 인증서 사이에 개입 되는 운영체제와 openssl의 동작이 Centos 6와 Centos7 사이에서 다르다는 것이다. 알파 / 샌박은 centos7 으로 구성돼 있었고, 베타 서버는 centos6로 구성돼 있었다.

strace를 통해서 ssl verfication 과정을 살펴본 결과는 ruby의 다른 http client들은 두 버전 모두 운영체제의 루트 ca를 가져와서 서버가 보내준 인증서를 verification 한다. 하지만 jsonclient는 인증서를 가져오는 방식이 운영체제와 openssl 버전에 따라 달랐다. centos7에서는 jsonclient가 운영체제의 ca를 사용하지만 centos6에서는 jsonclient의 수동 설정된 인증서를 가져오는 것이었다. 하지만 jsonclient 내부에 운영체제 분기 처리가 없었으므로 openssl의 상위 버전에서 수동 설정된 ca를 다루는 방식에 차이가 있음을 추측했다. 이 추측이 실제인지는 이제 찾으러 가봐야한다. 뿅

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

search previous next tag category expand menu location phone mail time cart zoom edit close