[IOS] API 통신에서 겪은 SSL 인증서 및 ATS 관련 이슈에 대하여
IOS

[IOS] API 통신에서 겪은 SSL 인증서 및 ATS 관련 이슈에 대하여

출시 프로젝트에서 공공데이터포털의 투어 API를 사용했다.

 

HTTPS를 지원하는 API 서비스였기 때문에 출시 과정에서 문제없이 ATS를 사용할 수 있을 거라고 생각했지만

 

결국 보안 관련 이슈를 겪게됐고 문제의 원인과 해결 방법을 작성한 글이다.


1. 이슈를 겪게된 과정

나는 공공데이터포털에서 제공하는 오픈 API 서비스를 출시 앱에 사용하기 위해서

Alamofire를 통해 제공되는 URL로 네트워크 요청을 시도했는데 아래 콘솔 메시지가 출력됐다.

Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."

요약하면 SSL 오류가 발생해서 서버로 보안 연결을 할 수 없다는 뜻이다.

 

같은 URL을 크롬 브라우저로 요청했을 때 정상적으로 응답이 왔었고 HTTPS 통신 역시
아무 문제가 없었는데 xcode나 다른 클라이언트로 요청하면 SSL 오류가 발생했다.

 

대표적으로 Insomnia에서 HTTPS 요청 시 아래 메시지가 출력된다.

Error: SSL peer certificate or SSH remote key was not OK

SSL(Secure Sockets Layer)은 TLS가 표준화 되기 전 이름인데

TLS는 HTTPS 통신 시 서버와 클라이언트가 안전하게 데이터를 주고받게 해주는 역할이다.

 

두 사례에서 발견된 공통 문제는 "보안"이므로 여기에 초점을 맞춰 해결 방법을 찾았다.

 

2. 문제의 원인과 해결 방법

결론적으로 문제가 되는 것은 "보안"이므로 프로젝트에서 ATS 설정을 해제하고

HTTP 통신을 사용하면 쉽게 문제를 해결할 수 있지만 정확한 원인을 알고 싶었다.

 

그래서 ATS 사용 조건 중 어느 부분이 문제가 있는지 진단하기 위해서

터미널에 공공데이터포털의 도메인과 명령어를 입력했다.

$ nscurl -- ats-diagnostics --verbose https://apis.data.go.kr

이 명령어를 입력하면 자동으로 ATS 예외 조건들을 변경해가면서 해당 URL로 네트워크 요청한 결과를 알려준다.

 

내가 확인한 공공데이터포털 도메인의 경우 NSExceptionRequiresForwardSecrecy의 값이
false일 때 요청 결과가 항상 성공임을 알 수 있었다.

 

그렇다면 ForwardSecrecy가 뭘까?

이 개념을 이해하기 위해선 HTTPS 통신 과정(SSL Handshake)을 조금 이해할 필요가 있다.

 

https 통신에서 서버와 클라이언트는 데이터를 암호화하기 위한 키를 주고 받는데,

대표적으로 RSA 알고리즘을 사용한 키 교환 방식은 다음과 같다.

  1. 서버는 SSL 인증서를 통해 클라이언트에게 공개키를 전달한다.
  2. 클라이언트는 실제 데이터 암호화에 사용할 비밀키(대칭키)를
    서버에게 받은 공개키를 사용해 암호화 한 뒤 서버에게 전달한다.
  3. 서버는 가지고 있던 개인키로 비밀키(대칭키)를 해독해 클라이언트와 같은 비밀키를 가진다.

그런데 만약 누군가가 서버의 개인키를 탈취했고 암호화된 데이터를 가지고 있다면

탈취한 개인키로 암호화된 비밀키를 해독하여 암호화된 데이터를 복호화할 수 있게된다.

 

이런 단점을 보완한 키 교환 방식이DH 알고리즘인데,

비밀키(대칭키) 자체를 교환하는게 아니라 비밀키(대칭키)를 만들기 위한 재료를 교환한다.

 

이 재료는 공개적으로 노출되어도 상관없고 키 교환 과정이 매우 간편하기 때문에

새로운 키를 만들기에 매우 용이하다.

 

따라서 이런 알고리즘의 특징을 이용해 일시적으로 사용하는 비밀키를 만들어서 그 키로 암호화하는 것을

FS(Forward Secrecy) 또는 PFS(Perfect Forward Secrecy)라고 한다.

일회성 키를 생성할 수 있는 DH 알고리즘을 DHE라고 부른다. E는 Ephermeral 의 약자

 

꽤나 멀리 돌아왔지만 다시 한번 짚고 넘어가보자.

HTTPS 통신 과정 중에 서버와 클라이언트 사이에서 데이터 암호화를 위한 키 교환이 일어나고

어떻게 키를 교환하느냐에 따라 보안성이 달라진다는 것을 길게 설명했다.

 

그러니까 서버에서 HTTPS를 지원하더라도 ATS 사용을 위해서는 기본적으로 PFS를 지원해야하며

그렇지 않은 경우 예외처리를 해야 오류가 발생하지 않는다.

 

그래서 정말로 서버 도메인이 PFS를 지원하지 않는지 확인해봤다.

HTTPS 통신 시 FS와 추가적으로 서버의 certificate chain에도 문제가 있는 것을 발견했다.

Insomnia에서 발생한 오류는 아마도 이것 때문인 것 같다. (명확한 SSL 인증서 오류였기 때문)

 

그리고 크롬 브라우저에서는 이것을 내부적으로 처리해주기 때문에 정상적으로 통신이 가능했던 것 같다.

 

여담이지만 Handshake 시뮬레이션 결과 iOS는 다른 클라이언트와 다르게 대놓고 안된다고 뜬다...



결론적으로 프로젝트의 info.plist에서 해당 도메인에 대한 ATS 예외 설정을 통해 HTTPS 통신을 할 수 있었다.

물론 앞서 얘기했던 것 처럼 그냥 AllowsArbitraryLoads 키를 true로 설정해도 출시에 걸림돌이 되진 않는다.

 

3. 참고 문서

https://aws-hyoh.tistory.com/entry/HTTPS-%ED%86%B5%EC%8B%A0%EA%B3%BC%EC%A0%95-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EB%B2%88%EC%99%B8%ED%8E%B8Perfect-Forward-Secrecy

 

HTTPS 통신과정 쉽게 이해하기 번외편(Perfect Forward Secrecy)

여러분은 오픈소스 패킷 분석 툴인 Wireshark(와이어샤크)를 자주 사용하시나요? 직무가 네트워크 엔지니어인 저는 꽤 자주 사용하는 편입니다. 통신이 안 되는 구간이 있다면 그 구간 내 어느 지

aws-hyoh.tistory.com

https://developer.apple.com/forums/thread/128414

 

NSURLErrorDomain Code=-1200 | Apple Developer Forums

I am using the URLSession library to connect to certain pages using the https protocol. To get access to certain urls I had to create a delegate to include the public part of the certificate offered by the server. The problem I find is that in some urls th

developer.apple.com

https://velog.io/@lhj26/ATSApp-Transport-Security

 

ATS(App Transport Security)

잘못된 내용은 댓글로 남겨주시면 감사하겠습니다.😎 URLSession을 이용한 네트워크 통신을 구현하는 중 다음 에러를 보게 됨. >App Transport Security has blocked a cleartext HTTP connection since it i

velog.io