어플리케이션을 개발하다 보면, 트래픽 데이터를 가시화시키지 않고 서버 개발자와 업무적 소통을 하는 것이 얼마나 부정확하고 무의미한 지 알 수 있게 됩니다.
통신의 과정을 보기 위해 별도의 요령이 없다면 높은 비율로 로그를 찍을 것이고, 툴을 활용하는 경우 flutter라면 devtools를 사용할 확률이 높습니다.
그리고 외부 프록시 툴을 사용하는 분들은 유료 툴인 fiddler, charles, burpsuite 중 고민하게 될 것입니다.
그러나 오늘 소개하려는 물건은 그저 국내에 소개가 덜 되고 좋은 한글 가이드 문서가 없을 뿐, 완전히 무료에 심지어 오픈소스로 제공되는 툴입니다.
본래 화이트해킹용(ㅋ..? 그냥 해킹용) 툴이지만, 제가 업무에 쓰고 있을 뿐이죠.
Zed Attack Proxy의 약칭 ZAP는 기본적으로 웹 트래픽을 가시화하고, 각 세션을 관리하여 해커가 직접 변조한 request를 전송하거나, active scanner로서 동작하여 모든 트래픽을 감시하고 자동변조나 정보탈취 기능을 본연의 목표로 합니다.
물론 우리 모바일 개발자들에게 아주 잘 된 일이죠, 망내 보안체계로 인해 devtools를 쓰지 못하는 저에게는 특히요.
ZAP의 인터페이스 입니다. (보안사항은 가렸습니다)
하단에 트래픽들의 목록이 뜨고, 원하는 통신을 선택하면 Http request/response의 header/body를 직관적으로 볼 수 있습니다.
앱 개발자로서 이런 프록시 툴을 사용함으로 인해 얻는 장점은 다음과 같습니다.
- 트래픽을 가시화할 수 있다
-> 원인과 책임을 분명히 하는 데 걸리는 시간이 짧아진다. 같이 보면 커뮤니케이션도 쉬워진다. - 변조된 트래픽을 날릴 수 있다
-> API 테스트를 할 수 있다 - response body를 빠르게 찾아 편집할 수 있다
-> API sample response가 없어도 백엔드개발자가 변경한 개발서버 응답을 ‘Json to dart’ 같은 툴에 복붙하여 response data VO의 작성을 반자동화 할 수 있다 - Android 로그 길이 제한 극복
-> 개발툴로 Android studio를 사용할 때에 안드로이드 폰을 쓰면 더 막강한 분석기능들을(메모리분석, 프로파일링, 시스템분석 등) 사용할 수 있지만, 트래픽 로그를 풀로 찍을 수가 없다 - Devtools의 불안정성과 부실한 기능 극복
-> 웹으로 돌아가다 보니 쉽게 세션이 끊어지고, 재접속하면 모든것이 날아가는데 상대적으로 프록시 툴은 안정성이 좋다
문제는, 기본적으로 외부CA인증서를 시스템 레벨에서 신뢰시킬 수 있는 네이티브앱과는 달리 flutter는 그것이 되지 않는다는 점입니다.
(해당 이슈는 아래 링크 참고)
그래서 flutter 앱에서 네트워크 프록시를 경유시키려면 별도의 작업이 필요합니다.
먼저 setProxy라는 메소드를 생성합니다.
void setProxy(HttpClient httpClient) {
if (Const.useProxy && !kReleaseMode) {
String proxy = Const.proxyAddress; // 프록시 태울 pc 주소 "ip:port"
httpClient.findProxy = (uri) {
return "PROXY $proxy;";
};
httpClient.badCertificateCallback =
((X509Certificate cert, String host, int port) {
return true;
});
}
}
사용은 다음과 같습니다.
Future<http.Response> getRequest(
String path, Map<String, dynamic> param, Map<String, String> header) {
Log.i("HttpRequest getRequest");
try {
var url = ApiUrl.BASE_URL + path + Uri(queryParameters: param).toString();
Log.v("http_log getRequest $url"); HttpClient httpClient = HttpClient();
setProxy(httpClient); // <- 여기서 사용
IOClient ioClient = IOClient(httpClient); return ioClient.get(
Uri.parse(url),
headers: header,
);
} catch (error) {
rethrow;
}
}
(용례는 jumpit_boilerplate 프로젝트의 코드를 참고하세요)
먼저, 보안을 위해 Release빌드가 아닐 때에만 실행되도록 하고 있습니다.
useProxy라는 상수를 두고 해당값이 true로 빌드되면 프록시를 사용하도록 설정하였습니다. 프록시 사용으로 인해 인증서 에러가 뜰 수도 있으므로 badCertificateCallback을 통해 그냥 패스하도록 합니다.
이 방법을 씀으로 인한 장점은, API통신에 대해 별도의 시스템 인증 신뢰절차 없이 트래픽 분석이 가능하다는 점 입니다.
앱내 코드의 작성이 완료되면, 이제 ZAP를 세팅해 볼 차례입니다.
홈페이지에서 개발환경에 맞는 버전을 받거나(윈도우, 맥, 리눅스) 혹은 Java11로 돌아가는 크로스플랫폼버전을 다운받아 켜시면 됩니다.
제가 사용하는 레이아웃이 모바일 개발에는 최적인데요, 이 레이아웃을 만드는 세팅은 상단 아이콘을 통해 이렇게 선택해 주시면 됩니다.
[tools]-[options] 메뉴입니다. 대부분의 세팅은 여기에서 이루어 질 것입니다.
먼저, [local proxies] 메뉴에서 connection을 받을 포트를 정해 줍니다.
저는 fiddler를 쓰던 습관 때문에 8888포트를 사용합니다.
다음은 [client certificate] 메뉴에서 unsafe ssl 트래픽을 허용합니다.
프록시 헤더가 추가되는 것을 방지하기 위해 [replacer] 메뉴에서 add를 누른 뒤 Proxy-Connection header를 자동으로 삭제하도록 추가하고 저장합니다.
특정 보안체계에서는 이 헤더값을 가지고 들어오는 트래픽을 거부하기 때문입니다.
특정 도메인만 스캐닝을 태우기 위해 [global exclude url]에 정규식을 등록하도록 합니다. 저같은 경우는 jumpit과 saramin도메인만 허용해 봤습니다.
이것을 하지 않으면 시스템인증서를 통해 global traffic scanning을 할 때에 모든 앱의 트래픽이 프록시를 타므로 구글플레이나 앱스토어 등의 중요 서비스가 접속이 거부됩니다.
JSON 규격을 사용하는 경우가 많을 텐데, 기본 뷰에서는 pretty format이 되지 않아 보기 불편할 수 있습니다.
상단에 있는 이 버튼을 누르면 add-on 매니저가 뜹니다.
Marketplace 탭에서 JSON View 플러그인을 설치합니다.
(만일 목록에 없다면 [online]-[zap marketplace] 메뉴를 눌러 웹에서 다운받아 import 해야 합니다)
이제 API통신 분석을 위한 세팅이 완료 되었습니다.
여기까지만 해도, flutter앱의 API통신을 분석하는 데에는 지장이 없습니다.
그러나 앱내 웹뷰 트래픽을 분석하는 것은 또 다른 이야기가 되죠.
만일 웹뷰의 트래픽도 분석을 해야 하는 상황이라면, 아래에 적은 세팅들을 추가로 해 주셔야 합니다.
휴대폰에 설치할 CA인증서를 저장합니다.
파일 버튼을 눌러 저장하고 폰에 설치를 합니다.
안드로이드폰 설치는, 파일을 폰으로 옮깁니다.
(케이블, 이메일, 메신저 등 어떤 방법이든 상관없음)
[설정]-[보안]-[기타 보안 설정]-[기기에 저장된 인증서 설치]-[CA인증서] 에서 인증서를 설치하면 됩니다.
아이폰의 경우에는 파일 앱으로 옮기면 되는데, 사용하는 컴퓨터가 맥이라면 airdrop을 통해 좀더 쉽게 설치할 수 있습니다.
[설정]에서 알림이 뜨는 것을 눌러 인증서 설치를 하고, [일반]-[정보]-[인증서 신뢰 설정] 화면에 들어가서 신뢰 처리를 해 주어야 합니다.
해당 기기의 global proxy를 활성화 시키려면, wifi 설정에서 접속한 wifi망의 상세 설정에 들어가면 proxy 설정을 ‘수동' 으로 바꿀 수 있는데, 여기서 proxy PC의 ip와 port를 설정하면 됩니다.
이렇게 flutter 앱의 API통신과 웹뷰(혹은 글로벌)의 트래픽을 분석할 수 있는 ZAP에 대해 소개해 보았습니다.
모든 앱 개발 조직이 사용하는 것은 아닐 수 있지만, 문제의 원인에 대해 빠른 분석을 요구하고, 그로 인해 요령이 생긴 조직이라면 이런 프록시 툴을 사용하고 있을 겁니다.
즉, 학생이나 취미 개발자가 이런 툴에 익숙해지는 것도 현업 수준에 한발 더 다가갈 수 있는 부분이라고 생각합니다.
글을 마무리 하며, 다음에 또 실무적인 팁으로 찾아뵙겠습니다.