Swift. Charles 사용법에 대해서 알아봅니다.

Charles Proxy Tutorial for iOS

Posted by MinJun Ju on Wednesday, October 24, 2018 Tags: Swift Charles Raywenderlich   15 minute read

Charles Proxy Tutorial for iOS에서 필요한 부분을 의역했습니다.


Table of contents


Charles Proxy Tutorial for iOS

iOS 네트워킹 코드를 디버깅할때 Charles proxy를 사용하여 네트워크 요청을 수정, 검사, 가로채기 하는 방법에 대해서 배웁니다.

시작 해봅시다 - 우리는 올바르게 동작하지 않는 코드를 작성했으므로 디버깅이 어려울수 있습니다. 네트워크를 통해서 다른 시스템과 상호 작용할때 이는 더욱 어려워집니다.

다행히 Charles Proxy는 네트워크 디버깅을 더 쉽게 만들어줍니다.

Charles Proxy는 앱과 인터넷 사이에 있습니다. 모든 네트워킹 요청과 응답은 Charles Proxy를 통해 지나가기 때문에 네트워크 응답과 요청을 살펴보는 것이 가능하고 심지어 앱의 응답 방식을 테스트하기 위해 데이터 변경도 가능합니다.

Charles Proxy 튜토리얼에서 Charles Proxy를 어떻게 사용하는지 경험을 얻을수 있습니다.


Getting Started

먼저 최신버전의 Charles Proxy를 다운로드 해야합니다(글이 작성되는 시점에는 4.1.1 버전 이었습니다). Charles Proxy는 무료는 아니지만 모든 사람에게 30일 무료 버전이 제공됩니다. Charles는 시험 모드에서 30분 동안만 실행되기 때문에 때문에 Charles Proxy 튜토리얼 동안 Charles을 재시작 해야할수도 있습니다.

Note: Charles는 Java 기반의 앱으로 MacOS, Windows, Linux를 지원합니다. 이 Charles Proxy 튜토리얼은 MacOS 전용이며 다른 플렛폼에서는 다를수있습니다.

Charles를 실행하면 자동으로 네트워크 설정 구성하기는 것을 허락 할것이냐고 요청할것입니다.

Grant Privileges를 클릭하고 비밀번호를 입력합니다. Charles는 실행되자마자 네트워크 이벤트 기록을 시작합니다. 왼쪽 패널에 이벤트가 표시되는걸 이미 볼수 있습니다.

Note: 이벤트가 보이지 않는다면, 인증을 허가하지 않았거나, 다른 proxy가 이미 설치되어 있을 수도 있습니다. 문제 해결을 위해 Charles’FAQ page를 참조해주세요

사용자 인터페이스는 많은 경험 없이 단순하게 이해할수 있습니다. 버튼과 메뉴에 숨겨져있는 다른 좋은것들이 많이 숨겨져 있지만. 도구 모음에서 알아야하는 몇가지 항목들이있습니다.

  • 첫번째 빗자루(broom)버튼은 현재 기록된 활동의 모든 세션을 지웁니다(clear)
  • 두번째 기록/잠시멈춤(recode/pause) 버튼이 빨강색일때는 Charles이 이벤트를 기록하고 있고 회색이면 멈춰있을때 입니다.
  • 거북이와 체크 마크 중간에 있는 버튼들은 일반적으로 사용되는 행동들을 위한 접근을 제공하고, 스로틀링, 브레이크 포인트, 요청 생성을 포함합니다. 마우스를 각각 위에 올려 놓으면 간단한 설명을 볼수 있습니다.
  • 마지막 2개의 버튼은 일반적으로 사용되는 툴과 설정을 제공합니다.

이제 red record/pause button버튼을 눌러서 기록을 중지 시킵니다.

왼쪽 패널은 StructrueSequece 관점 사이에서 왔다갓다 할수 있습니다. Structure를 선택할때 모든 활동은 site 주소로 그룹화되어 집니다. 사이트 옆에 arrow를 클릭하여 개별 요청을 볼수도 있습니다.

시간순으로 정렬된 연속된 목록의 모든 이벤트를 보려면 Sequence를 클릭하세요. 자신의 앱을 디버깅할때 대부분의 시간을 이 화면에서 시간을 보내게될것 입니다.

Charles\Preferences를 클릭하고 Viewers탭을 선택하고 - Combine request and response를 체크 해제 하고 OK를 누릅니다. 변경 사항을 적용하려면 Charles를 다시 시작 해야 합니다.

사용자 인터페이스를 둘러보고 이벤트를 살펴보세요. 하나의 독특한점을 알아 차리게 될것입니다: HTTPS 이벤트에 대한 대부분의 세부 사항을 볼수 없습니다!

SSL/TLS는 민감한 요청 정보와 응답 정보를 암호화 합니다. 아마 Charles이 모든 HTTPS 이벤트에 대해서 무의미 하다고 생각 할것입니다. 그렇지 않습니다. Charles는 교활하게 암호화를 얻는 방법을 가지고 있습니다. 이것을 곧 배우게 될것입니다.


More About Proxies

Charles이 어떻게 그 마술을 이행하는지 궁금할것입니다.

Charles은 프록시 서버이므로 이것은 앱과 컴퓨터의 네트워크 연결 사이에 위치 한다는것을 의미합니다. Charles가 자동으로 네트워크 설정을 했을때, 모든 트레픽이 Charles을 통하여 지나게 하기 위해 네트워크 설정을 변경합니다. 이를 통해서 Charles이 컴퓨터에서 모든 네트워크 이벤트를 검사할수 있습니다.

프록시 서버들은 강력한 권한을 가지고 있지만, 이것은 남용의 가능성을 의미합니다. 이것이 SSL이 중요한 이유입니다. 데이터 암호화는 프록시 서버와 민감한 정보를 도청하는 미들웨어를 방지합니다.

그러나 우리의 경우에는 Charles이 SSL 메시지를 엿보고(snooping)하여 디버그 할수 있게 하고 싶습니다.

SSL/TLScertificate issuers라고 불리는 신뢰된 제3자가 생성한 인증서를 사용하여 메시지를 암호화 합니다.

Charles는 또한 iOS와 Mac 기기에 SSL/TLS 암호화 용으로 자체 서명된 인증서를 생성할수 있습니다. 이 인증서는 신뢰할수있는 인증서 발행자가 발행하지 않으면 명시적으로 신뢰하도록 디바이스에 지시해야합니다. 설치하고 신뢰할수 있게하면 Charles는 SSL 이벤트를 해독할수(decrypt) 있습니다.

해커가 네트워크 통신망을 염탐하기 위해 미들웨어를 사용할때 이것을 man-in-the-middle 공격이라고 부릅니다. 일반적으로 임의의 인증서를 신뢰하는걸 원하지 않거나 네트워크 보안을 손상시킬수 있습니다.

Charles의 교활한 main-in-the-middle전략이 효과가 없을 때가 있습니다. 예를 들어, 일부 앱은 추가적인 보안 강화를 위해 SSL pinning을 사용합니다. SSL pinning은 SSL 인증서의 공개키 사본이 있다는 것을 의미하고 이를 사용하여 네트워크 통신 이전에 유효한 네트워크 연결인지 확인합니다. Charles의 키가 일치하지 않기 때문에 앱은 통신을 거부합니다.

추가적으로 이벤트를 기록하는것 외에도 Charles을 사용하여 데이터를 즉시 수정, 기록하고 나중에 검토하여 좋지 않은 네트워크 연결을 모의 실험 할수 있습니다.


Charles Proxy & Your iOS Device

iOS 디바이스, 네트워크에 연결된 어떤 컴퓨터, 디바이스에서 트레픽을 대리하기 위해 Charles를 설정하는것은 간단한 합니다.

먼저 Charles에서 Proxy(drop-down menu)\macOS Proxy를 클릭하여 uncheck 하여 macOS 프록시를 끕니다. 이렇게하면 iOS 디바이스의 트레픽만 볼수 있습니다.

다음으로 Proxy\Proxy Settings을 클릭하고 Proxies클릭하고 port number를 기록하세요. 포트 번호의 기본값은 8888 이어야 합니다.

그런 다음 Help\Local IP Addres를 클릭하고 컴퓨터의 IP 주소를 기록합니다.

이제 iOS 디바이스를 잡으세요. Setting을 열고 Wi-fi를 탭한 다음 컴퓨터와 동일한 네트워크에 연결되어 있는지 확인하세요. 그런 다음 와이파이 네트워크 옆에 버튼을 탭하고 HTTP Proxy 색션으로 스크롤을 내리고 Manual을 탭합니다.

서버에는 Mac의 IP 주소를 입력하고 Port에는 Chalres HTTP Proxy port number를 입력합니다. 뒤로가기 버튼을 탭하거나 홈 버튼을 누르면 변경이 자동으로 저장되어 질것입니다.

이전에 Charles에서 기록을 중지한 경우 다시 record/pause 버튼을 탭하여 기록을 다시 시작합니다.

Mac에서 Charles의 iOS 장치의 연결을 허용할것인지 묻는 팝업 경고가 표시됩니다. Allow를 클릭합니다. 이 내용이 즉시 나타나지 않는다고 해도 괜찮습니다. 표시되기 까지 1-2분 정도 걸릴수 있습니다.

Charles에서 이 디바이스의 활동을 보기위해 시작해야 합니다.

iOS 디바이스에서 Safari를 열고 http://www.charlesproxy.com/getssl을 찾아가면 Profile/Certificate 설치하라는 메시지 팝업창이 나타납니다.

Detail에서 자체 서명된 Charles 인증서를 봐야합니다. Install을 누르면 경고이후 다시 Install을 탭합니다. 그 후 한번더 Install을 탭합니다. 마지막으로 Done을 탭합니다.

Apple은 이것을 설치하길 정말 원한다는 확인을 합니다 :] 다시 한번 말하지만 임의의 인증서를 설치하지 마세요. 그렇지 않으면 네트워크 보안이 구성되지 않을수 있습니다. Charles Proxy 튜토리얼의 끝에서 이 인증서를 제거할것입니다.

Note: iOS 10.3 으로 업데이트: 이 시점에서 아마 에러 메시지를 받았을 것입니다. 여기에 해결책이 있습니다.


Snooping on Someone Else’s App

대부분의 개발자와 같이, 이들이 어떻게 작동하는지 궁금할것입니다. Charles는 앱이 아닌 경우에도 앱의 통신을 검사할수 있도록 도구를 제공하여 궁금증을 해결하게 합니다.

기기의 App Store로 이동하여 Weather Underground를 찾아 다운로드하세요. 이 무료 앱은 대부분의 국가에서 사용할수 있습니다. 가능하지 않거나 다른것을 시도하고 싶다면 원하는걸 사용하세요.

Weather Underground를 다운로드 하는 동안 Charles에서 왕성한 활동을 보게 될것입니다. App Store는 꽤 수다스럽습니다.

앱이 설치되면 앱을 실행하고 Charles의 빗자루 아이콘을 클릭하여 최근 활동을 지웁니다.

앱에서 우편번호 90210을 입력하고 Beverley Hills를 내 위치로 선택하세요. 현재 위치를 사용하는 경우 위치가 변경되면 앱이 가져오는 URL이 변경되어 Charles Proxy 튜토리얼의 이후 단계를 따르기가 더 어려워질수 있습니다.

Structure 탭에는 다수의 사이트 목록이 있습니다. Weather Underground app에서의 활동 뿐만아니라 iOS 디바이스에서의 모든 활동 목록 입니다.


Sequence로 전환하고 weather의 트래픽만 보기위해 필터에 wund를 입력합니다.

api.wunderground.com의 몇개의 요청을 봐야합니다. 이들을 클릭 합니다.

Overview 색션에서 요청 세부사항이 표시되지만 그다지 많지는 않습니다. 마찬가지로 Request, Response도 많은 자세한 부분을 볼수 없습니다. Overview가 많은것을 보여주지 않는 이유는: "이 호스트에 대해서 SSL 프록시를 사용할수 없습니다: Proxy Setting에서 SSL 위치를 가능하게 해야합니다."(Notes SSL Proxying not enabled for this host: enable in Proxy Settings, SSL locations) 따라서 이 기능을 가능하게 해야합니다.

Proxy\SSL Proxying Setting 클릭하고 Host에 대한 api.wunderground.com를 입력하고 Add을 클릭합니다. Port는 빈값으로 두고 OK를 클릭합니다.

Wunderground app 으로 돌아가서 pull down to refresh 하고 데이터를 다시 가져옵니다.

데이터를 다시 가져오지 못하면, 멀티테스킹에서 앱을 종료하고 다시 시도 해야할수도 있습니다.

워우. 암호화 되지 않은 요청을 받았습니다! forecast10day를 포함하는 URL 요청을 볼수 있습니다. weather 화면에 사용되는 페이로드를 포함합니다.

앱을 사용하기전에 데이터를 변경 해봅시다. 앱이 깨지거나 재미있게 움직이게 할수 있나요?

Sequence 내에서 reqeust를 우 클릭합니다. 팝업 목록에서 breakpoints item(breakpoints)을 클릭합니다. 이제 이 URL로 요청이 있을때마다 Charles는 일시 중지하고 요청 및 응답을 편집할수 있게 합니다.

다시 앱을 새로 고침하려면 앱을 아래로 당깁니다.

Breakpoints 라는 타이틀의 새로운탭이 request와 함게 표시됩니다. 아무것도 수정하지 않고 Execute를 클릭하면 됩니다. 잠시후에 Breakpoint 탭에 response와 함게 나타납니다.

상단탭 근처의 Edit Response를 클릭하고 아래의 JSON text를 선택합니다. 아래로 스크롤하여 temperture를 찾고 정신이 나간 온도인 9800으로 변경합니다

Note: 요청이나 응답을 너무 오래 편집하면 앱이 자동으로 시간 초과하여 아무것도 표시하지 않을 수 있습니다. 편집된 온도가 나타나지 않으면 조금더 빨리 다시 시도하세요.


9800°F는 미친 듯이 덮습니다! Wunderground는 1000° 이상의 온도를 표현할수 없는것 같습니다.

Proxy\Breakpoint Setting로 이동하여 설정한 브레이크 포인트를 삭제하세요.

임시로 브레이크 포인트를 사용하지 않기 위해 api.wunderground.com에 대한 모든것을 체크 해제 하거나 행을 선택하고 Remove 버튼을 눌러 지웁니다. 다시 앱을 새로 고침하면 온도가 정상으로 되돌아 옵니다.

다음으로 느린 네트워크를 실험하기 위해 거북이(turtle) 아이콘을 클릭하여 스로틀링을 시작하세요. 사용가능한 옵션들을 보기 위해 Proxy\Throttle Settings을 클릭합니다. 기본은 56kbps 이고 이것은 꾀 느립니다. 또한 여기에 설정을 조절하여 데이터 손실, 안정성 문제, 높은 대기 시간을 실험할수 있습니다.

앱을 다시 리프레시 하고 지도를 확대 / 축소 하거나 다른 위치를 검색해보세요. 고통 스럽습니다..

안좋은 네트워크 환경에서 앱을 테스트하는것이 좋습니다. 지하철, 엘리베이터에서의 사용자를 상상해보세요. 이런 상황에서 앱이 데이터를 잃어 버리거나 악화되는것을 원하지 않습니다.

Apple의 Network Link Conditioner는 비슷한 스로틀링 기능을을 제공하지만 Charles는 네트워크 설정을 보다 세밀하게 조정할수 있습니다. 예를 들어 전체 연결을 느리게 하는 대신에 특정 URL에만 스로틀링을 적용하여 서버 응답을 적용할수 있습니다.

이것을 다했으면 throttling를 꺼야합니다. 디버깅을 시간을 보내는것보다 더 나쁜 시간은 없습니다.(ㅠㅠ)


Troubleshooting Your Own Apps

Charles Proxy는 앱을 디버깅하고 테스트하는데 적합합니다. 예를 들어 서버 응답을 검사하여 JSON 키가 올바르게 정의되고 모든 필드에 대해 예상되는 데이터 타입이 반환되는지 확인할수 있습니다. Throttiling를 사용하여 열약한 네트워크 환경을 테스트할수 있고 앱의 시간초과 및 오류 처리 로직을 확인할수 있습니다.

이 튜토리얼을 위해 만든 Charles in Charge라고 불리는 iMessage 앱을 사용하여 다루어보겠습니다.

당신이 80년대 생이라면 Scott Baio가 주연인 Charles in Charge 코미디를 알것입니다. Charles in Charge iMessage 앱은 마이크로 소프트 Bing의 이미지 검색 API를 사용하여 imessage에서 보낼수 있는 문자의 이미지를 제공합니다.

데모앱을 구성하기 위해 먼저 Bing Image Search API 키를 받아야 합니다. 여기에서 Microsoft Cognitive Services 계정을 만들어야 합니다. 이메일을 확인하고 계정 설정을 완료하기 위해 확인 링크를 클릭하세요. 이는 API키를 생성하는데 필요합니다.

가입한 후 무료로 시작하기 또는 계정 페이지에서 새로운 무료 평가판을 구독하세요. Bing Search 무료 체크박스를 선택하고 이용 약관등을 동의 하고 구독을 클릭합니다.

가입을 완료하면 두개의 접근 키가 생성 됩니다. 둘중 하나를 복사합니다(곧 필요하게 될것입니다)

지금은 위의 그림과 다른 인터페이스 입니다. 계정을 생성하면 2개의 키를 얻을수 있는 부분이 있습니다.

다음으로 Charles in Charge를 다운로드 하고 CharlesInCharge.xcodeproj를 엽니다.

MessageExtension 그룹을 열고 몇개의 Swift 파일들을 봅니다.

CharlesInChargeService는 이미지들을 검색하기 위해 Bing을 호출하여 관리하고 ImageDownloadService앱에서 사용하기 위한 각 이미지를 다운로드 합니다.

CharlesInChargeService 클레스 내에 findAndDownloadImages(completion:) 메소드 에서 BingImageSearchService 초기화를 위한 subscriptionKey 매개변수 키가 빈 스트링 값으로 설정되어 있는것을 볼수 있습니다.

아까 복사한 access Key를 여기로 붙여넣습니다.

앱을 다시 빌드하고 실행합니다.

Charles 에서 Proxy를 클릭하고 macOS Proxy를 선택하여 다시 켭니다(체크 표시가 나타나지 않으면)

그후 Proxy\SSL Proxying Settings를 클릭하고 api.cognitive.microsoft.com을 목록에 추가합니다.

다음으로 시뮬레이터에서 Charles Proxy SSL 요청을 허용하기 위해 Proxy SSL 인증서를 설치해야합니다. 이전에 했던것과 같이 하고 시뮬레이터를 종료 합니다. 그후 Charles 에서 Help\SSL Proxying\Install Charles Root Certificate in iOS Simulators를 클릭합니다.

Xcode로 돌아가서 프로젝트르 빌드하고 실행합니다. iMessage 가 실행되면 Charles in Charge를 찾고 선택합니다. 그런 다음 이미지가 로드 될떄까지 기다립니다. 여기에서 무엇을 하는건가요?

콘솔에서 다음과같은 출력을 볼수 있습니다.

Bing search result count: 0

이 글을 의역하고 있는 2018.12.4일 프로젝트에 작성된 끝점이 업데이트되어 작동하지 않습니다. BingImageSearchService.swift search 함수에서 사용된 끝점을 https://api.cognitive.microsoft.com/bing/v7.0/images/search으로 변경합니다.

앱이 검색 결과를 얻지 못하고 있거나 데이터를 매핑하는데 문제가 있는것으로 보입니다. 마지막으로

먼저 데이터를 가져왔는지 확인하세요.

Charles에서 cognitive를 필터상자에서 입력하여 Bing Image Search를 찾습니다. 목록에서 요청을 클릭하고 Response 탭을 선택하고 하단의 JSON text을 선택합니다. JSON 전체 value을 확인하여 실제로 검색 결과가 반환되는것을 확인할수 있습니다. 따라서 BingImageSearchService 내에서 이상한 일이 발생했다는걸 알수 있습니다.

Xcode에서 이 클레스를 열고 JSON에서 SearchResult 구조체로 맵핑된 검색 결과 위치를 찾습니다.

guard let title = hit["name"] as? String,
  let fullSizeUrlString = hit["contenturl"] as? String,
  let fullSizeUrl = URL(string: fullSizeUrlString),
  let thumbnailUrlString = hit["thumbnailurl"] as? String,
  let thumbnailUrl = URL(string: thumbnailUrlString),
  let thumbnailSizes = hit["thumbnail"] as? [String: Any],
  let thumbnailWidth = thumbnailSizes["width"] as? Float,
  let thumbnailHeight = thumbnailSizes["height"] as? Float else {
    return nil
}

어떤 키도 발견하지 못한다면 SearchResultnil이 됩니다. Charles에서 응답 데이터와 이 키들을 각각 비교하세요: 대소 문자가 중요합니다.

잘보면, contentUrlthumbnailUrl에서 매핑코드가 대문자 U가 매핑코드에 없다는것을 볼수 있습니다. 이 키를 고치고, 앱을 다시 빌드하고 실행합니다.


성공입니다.


Remove Charles’ Certificate

과거에는 Charles가 사용하는 모든 장치에서 공유된 인증서를 만들었습니다. 다행히 Charles는 이제 고유한 인증서를 생성합니다. 이것은 인증서를 기반으로 하는 man-in-the-middle 공격의 가능성이 크게 줄어들지만 여전히 기술적으로 가능합니다. 그러므로 Charles를 다 사용했을때 이것을 항상 지우는걸 기억해야합니다.

먼저 macOS에서 인증서들을 지웁니다. Keychain Access 애플리케이션을 열고 Charles Proxy를 검색하고 검색 필드의 모든 인증서를 삭제합니다. 대부분 한번만 삭제하면 됩니다. 끝났다면 Keychain 애플리케이션을 닫습니다.

다음으로 iOS 디바이스에서 인증서를 지웁니다. Settings app을 열고 General\Profiles & Device Management를 찾아갑니다. 구성 프로파일 아래에 한개 이상의 Charles Proxy에 대한 하나 이상의 항목이 표시된걸 보아야 합니다. 탭하고 Delete Profile을 누릅니다. Charles Proxy 인증서에 대해 이를 반복해야합니다.

Profiles & Device ManageMents는 iOS 시뮬레이터에서 사용할수 없습니다. Charles Proxy 인증서를 제거하려면 시뮬레이터에서 컨텐츠 및 설정 재설정을 클릭하여 시뮬레이터를 재설정 합니다(Reset Content and Settings).


Where to Go From Here?

Charles Proxy 튜토리얼에서 다루지 않은 많은 기능이 여기 있습니다. JSON Keys가 정정된 Charles in Charge 최종 앱은 여기에서 다운 받을수 있습니다.

SSL/TLS에 대해서 궁금하다면 https://en.wikipedia.org/wiki/Transport_Layer_Security에서 더 자세한 내용을 알수 있습니다. Apple은 결국 모든 애플리케이션이 안전한 네트워크 연결을 사용하길 요구할것입니다.

또한 MacOS에 대해 https://paw.cloud/ 사용을 검토하세요. 새로운 API 요청을 작성하고 매개 변수를 테스트하는데 도움을 주는 Charles의 훌륭한 동반자 입니다.