Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

mitmproxy로 iOS 기기의 네트워크 트래픽 살펴보기

개발을 하다 보면 가끔 직접 소스를 수정할 수 없는 프로그램의 네트워크를 보고 싶은 경우가 있다. 네트워크를 볼 수 있는 프로그램도 많이 있고 웹 같은 경우는 브라우저의 개발자 도구를 열면 대부분을 볼 수 있지만, 모바일 쪽으로 가면 상황이 달라진다. 나는 모바일 개발자는 아니라서 그쪽 생태계는 잘 모르지만, 모바일 개발자의 도움 없이 앱의 네트워크 동작을 봐야 할 일이 있었다.(남의 앱은 아니고 우리 회사의 앱)

mitmproxy

mitmproxy 웹사이트

그렇게 방법을 찾아보다가 알게 된 도구가 mitmproxy다. 이름에서 알다시피 MITM(man in the middle)으로 네트워크를 중간에서 가로채서 볼 수 있게 해주는 도구이고 오픈소스이면서 무료로 사용할 수 있다. How mitmproxy works에 나와 있는 대로 폰의 모든 요청을 mitmproxy로 가게 하고 mitmproxy가 다시 이를 원래 요청한 서버로 보내주는 방식이다.

설치

$ brew install mitmproxy

설치는 macOS의 경우 brew로 쉽게 설치할 수 있다. Linux와 Windows는 문서에 잘 나와 있다.

$ mitmproxy --version
Mitmproxy: 5.3.0
Python:    3.9.0
OpenSSL:   OpenSSL 1.1.1h  22 Sep 2020
Platform:  macOS-10.15.7-x86_64-i386-64bit

설치가 완료되면 버전을 확인해 볼 수 있고 현재 버전은 5.3.0이다.

맥북에서 mitmproxy 설정

아이폰과 맥북이 같은 Wi-Fi 네트워크에 붙어있다고 했을 때 맥북에서 mitmproxy를 실행한다.

$ mitmproxy

터미널에서 mitmproxy를 실행하면 아래와 같은 화면이 나타난다. 아직 트래픽을 보내지 않았으므로 아무것도 안 나오는 게 맞다.

터미널에서 mitmproxy를 실행한 빈 화면

mitmweb 명령어를 통해서 웹 인터페이스도 제공하지만 몇 번 사용해보니 느려지기도 하고 사용성 면에서 터미널에서 사용하는 것이 훨씬 나아서 더는 웹 인터페이스는 사용하지 않는다.

그리고 현재 맥북의 로컬 IP를 확인한다. 나는 Alfred 같은 도구로 IP를 보통 확인하는데 터미널에서는 다음과 같은 명령어로 확인할 수 있다.

$ ifconfig | grep "inet " | grep -Fv 127.0.0.1 | awk '{print $2}'
172.30.1.52

내 로컬 IP는 172.30.1.52다.

iPhone에서 프락시 설정

iOS의 Wi-Fi 설정의 HTTP Proxy 메뉴

아이폰에서 [설정] - [Wi-Fi]에서 현재 사용 중인 Wi-Fi를 눌러서 들어가면 맨 아래 HTTP PROXY라는 부분을 볼 수 있다. 보통은 사용 안 하니 Off로 되어 있는데 "Configure Proxy"를 눌어서 들어간다.

Congifure Proxy 부분에서 IP와 포트를 입력함

여기서 "Manual"을 누르고 서버에서는 위에서 확인한 IP 172.30.1.52를 입력하고 포트는 8080을 입력한다.

iPhone에서 인증서 설정

아이폰에서 브라우저를 열고 http://mitm.it에 접속하면 아래와 같이 플랫폼별 인증서를 설치하는 화면이 나온다. HTTP라면 상관없지만, HTTPS의 경우 인증서 때문에 네트워크를 모니터링 할 수 없어서 인증서를 바꿔치기 해야 한다. 물론, 이건 내 폰에서 내가 직접 설정해야 가능한 것이므로 다른 사람의 폰을 감시하거나 할 수는 없다.(현재 iOS 14.2를 사용 중이다)

mitm.it 사이트에서  플랫폼별 인증서 다운로드 메뉴

만약 mitmproxy로의 프락시 설정이 제대로 되지 않았다면 아래와 같은 화면이 보일 것이다. 이때는 앞의 과정으로 돌아가서 맥북에 mitmproxy가 잘 떠 있는지 아이폰에서 프락시 설정이 잘 되어 있는지 확인해야 한다.

mitmproxy 프록시가 제대로 설정안되었으면 If you can see this, traffic is not passing through mitmproxy라고 나온다

맥북에서 아까 띄워놓은 mitmproxy를 보면 아이폰에서 브라우저로 http://mitm.it에 접속하면서 보낸 트랙픽을 확인할 수 있다.

터미널에 띄워놓은 mitmproxy에 트래픽이 잡혔다

http://mitm.it에서 iOS 부분의 "Get mitmproxy-ca-cert.pem"을 클릭한다.

iOS가 구성 프로필을 다운로드 할 것인지 묻는다

구성 프로필을 다운로드 할 거냐고 경고가 나온다. 보통은 조심해야 할 메시지지만 여기서는 의도한 것이므로 Allow 한다.

프로필 메뉴에 다운로드 받은 프로필이 표시된다

다운로드가 완료된 후 아이폰의 [설정] - [General]에 들어가면 하단에 Profile이라는 메뉴에 들어가면 mitmproxy 프로필을 볼 수 있다.

프로필 상세페이지에 Not Verified라고 표시되고 install 버튼이 있다

아직 다운로드한 것이므로 들어가서 Install을 누른다.

설치가 완료되어 프로필이 verified로 바뀌었다

설치가 완료되면 프로필이 Verified로 바뀐다.

다시 아이폰의 [설정] - [General] - [About]에 들어가면 최하단을 보면 "Certificate Trust Settings"라는 메뉴가 있다.

Certificate Trust Settings에 mitmproxy의 토글 버튼이 생긴다

이곳에 들어가면 좀 전에 설치한 mitmproxy 인증서를 볼 수 있다. 이 인증서를 신뢰하는 인증서로 설정해 주어야 네트워크 트래픽을 볼 수 있음으로 켜준다.

활성화 할때 enabling this certificate for websites will allow third parties to view any private data sent to websites라는 경고 메시지가 나온다

여기서는 의도한 동작이지만 보통 다른 인증서를 신뢰하도록 하는 것은 위험한 행위이므로 경고 메시지가 나온다. 무서워하지 않고 Continue를 누른다. 이제 모든 설정이 완료되었다.

mitmproxy로 네트워크 모니터링하기

아이폰에서 실행한 앱의 트래픽이 터미널에서 띄운 mitmproxy에 표시된다.

이제 아이폰에서 아무 앱이나 실행하면 네트워크 로그가 남는 것을 볼 수 있다. 여기서는 트위터 앱을 실행해 보았다. 한 줄이 하나의 요청이고 화살표로 위아래 움직일 수 있는데 이동하는 커서는 왼쪽에 >>로 표시된다.

터미널 UI라서 사용하기가 어려울 수 있는데 조금 익숙해지면 그리 어렵지는 않다. ?를 누르면 아래처럼 단축키를 알 수 있고 UI의 사용법은 mitmproxy 문서에도 안내되어 있다.

mitmproxy에서 단축키와 설명이 표시된다.

자세히 보고 싶은 요청을 Enter를 눌러서 들어가면 요청과 응답을 볼 수 있다.

각 요청의 상세보기에 들어가면 요청/응답/상세로 탭이 나뉘어져서 정보가 표시된다

위처럼 HTTPS 요청이지만 내용을 모두 볼 수 있는걸 알 수 있다. Details 부분에서는 커넥션에 걸린 시간, 첫 바이트를 받은 시간, 핸드쉐이크에 걸린 시간 등을 볼 수 있다. 터미널 UI라서 진입 장벽이 있고 불편하게 느껴질 수 있지만 트래픽 보는 것이 복잡한 작업은 아니니 트래픽을 뒤적거리다 보면 익숙해지게 된다. 물론 mitmproxy는 그냥 트래픽 모니터링만 하는 것이 아니라 요청을 다시 보내보거나 관심 있는 트래픽을 다운로드 받아보거나 하는 등 다양한 기능을 제공하고 있다.

참고로 mitmproxy를 쓰다가 프로그램을 종료하면 아이폰에서 인터넷이 전혀 되지 않음으로 위에서 설정한 HTTP PROXY 설정을 꺼주어야 한다.

2020/11/30 18:30 2020/11/30 18:30