배경
User(ex. Chrome) -> Kernel -> Network Interface Card(NIC) -> H/W 구조로 패킷이 전송된다.
패킷은 Frame으로 둘러싸여있으며, 최대용량 MTUrk 1500 바이트 정도가 일반적이다.
Kernel에서 NIC로 넘어가는 곳에 Filter가 있고 특별한 역할을 하지 않는 경우 Sensor로써 그냥 패킷이 거쳐가는 역할을 한다.
Wireshark는 이 Sensor에 쌓이는 정보들을 Npcap을 활용하여 로그에 대한 검색 등의 각종 기능을 제공한다.
패킷은 1500 바이트씩 엄청나게 많으므로 이 내용들을 검색해주는 기능이 핵심이다
Wireshark은 2개의 filter를 갖고 있으며, 1개는 패킷 수집용 필터, 1개는 검색 등을 위한 디스플레이 필터이다
예제파일
https://www.chappell-university.com/wireshark101-2ndedition
프레임(패킷) 캡쳐하기
캡쳐 파일 형식
Capture- CaptureOption에서 filter를 선택하여 무차별 캡쳐 방식(Promiscuous) 중 특정 내용만 수집할 수 있다.
수집되는 파일은 trace file이라고하며 라이브캡쳐 시에 메모리를 잡아먹으므로 계속 켜둔 것은 아닌지 주의해야한다.
200MB 이하 정도의 trace file만 wireshark으로 분석하는 것을 권장한다
분석하기
예제파일의 http-browse101 파일을 연다. 특정 프레임을 클릭한 후, Http 프로토콜인 Hypertext Transfer Protocol 부분을 찾아서 Host 부분에 우클릭 후 apply as Column을 누르면 위쪽 Display에 HTTP의 Host 정보만 필터링할 수 있는 컬럼이 생기는 것을 볼 수 있다.
이렇게 컬럼으로 지정하는 것은 DB와 같이 indexing을 잡는 것이기 때문에, 연산이 필요하게 되어 컴퓨터에 부하를 주게 된다. 컬럼을 다시 우클릭 해서 Remove 해버리면 index를 날리게 되는 것이다. 자주 보는 컬럼이라면 그대로 두고 hide만 해놓는 것이 컴퓨터에 도움이 될 수 있다.
TCP 요청을 클릭 후 우클릭 Colorize with Filter로 TCP 요청만 다르게 색칠할 수 있다.
우클릭 Follow -> TCP Stream 등 특정 Stream을 클릭하면 그 Stream에 대한 패킷만 조립해준다.
HTTP 패킷에 Follow -> HTTP Stream을 클릭하고 맨 밑으로 내려보면 알 수 없는 문자열로 .PNG가 조립된 부분이 있을 수 있다.
이 부분은 File -> Export objects -> Filename에서 GET 요청에 적혀있는 파일명을 찾은 뒤, Preview 버튼을 눌러보면 어떤 그림인지 확인이 가능하다.
Display 필터
필터링을 하는데 문법이 일반적인 언어들과 약간 다른 부분이 있다. 특히 !=는 일반적으로 다름을 표시하지만, Wireshark에서는 A != B 가 아니라 !(A == B)로 !를 인버트(invert) 개념으로 사용해야한다.
ip 주소 부분에 우클릭 후 Apply as Filter -> Selected를 클릭하면 특정 ip 주소만 필터링 되면서 명령어줄에 ip.src == {특정 ip 주소} 로 표기된다. 이런 식으로 ip.src는 ip주소의 출발지, ip.dst는 ip주소의 목적지 등을 표기하는 문법이 된다. 또한 and, or나 &&, || 등의 논리연산자도 적용이 가능하다.
특정 필터를 적용했을 때, 전체 패킷 중 어느 정도의 패킷이 해당하는지는 우측 아래에 표기된다. 패킷이 많은 경우 이렇게 필터링을 적용하여 내가 분석하고자하는 패킷의 범위를 좁혀나가는 것이 중요하다.
209.93.102.0/24 처럼 ip 주소를 CIDR 표기법으로 네트워크 대역으로 지정해서 표현식을 쓰고 필터링을 적용할 수도 있다.
필터를 잘 사용하는게 wireshark를 사용하는 핵심이고, 필터를 잘 사용하려면 결국 각 프로토콜의 필드나 속성값들의 특징을 잘 알아야한다. 즉 HTTP, TCP, UDP 등의 프로토콜에 대해서 잘 알고 있는 것이 패킷 분석의 핵심이 된다.
HTTP 분석
예제로 HTTP 패킷을 하나 분석해본다. 예제 파일은 http-sfgate101.pcapng 파일이다.
다음처럼 http.response.code > 400이라고 쳐보면 404 에러가 난 패킷들을 볼 수 있다.
그리고 맨 앞쪽에 <- 화살표가 있는 패킷을 눌러서 Follow -> Http Stream을 클릭해보면,
404 응답에 대한 요청이 10208번 패킷으로 들어왔고, GET /favicon.ico에 대한 요청에 대해 서버에서 실패응답으로 404를 보냈다는 것을 알 수 있다.
다른 필터 적용
Edit -> Find Filter에 들어가보면 명령어 입력창 밑에 패킷 종류, 문자열 종류 등을 선택할 수 있는 확장 화면이 나온다. 여기서 Regular Expression을 선택하여 정규 표현식을 통해 특정 패킷들을 구분할 수도 있다.
문법상 contains "문자열", matches "정규표현식" 등으로 패턴을 찾을 수 있다.
TCP 분석
장애가 났을 때 문제 원인을 분석하는 것은 베이스 계층부터 시작해야한다. 클라이언트와 서버는 똑같이 Application - Kernel(OS) - H/W 단으로 3개로 나눌 수 있다. 여기서 앞서 말한 베이스 계층은 H/W 단을 말한다. H/W에서 랜케이블이 빠져있거나 전기가 끊겼다면 그 위 계층보다 더 근본적인 문제일 수 있다. 따라서 베이스 계층부터 시작해야한다.
서버 - 클라이언트 사이의 네트워크 연결도 베이스 계층이다. 서버가 응답을 보냈는데 응답의 패킷 순서에 맞지 않게 클라이언트에게 전달되는 Out of order 문제가 있을 수 있다. 또는 Network Interface Card(NIC)에서 인터넷으로 신호를 보냈는데 신호를 잃는 Lost Segment 문제가 발생했을 수도 있다.
Out of Order가 발생한 경우 상위 Kernel 단의 TCP에서 재전송 요청(ReTransmission)을 보낸다. 이 때 Duplicated ACK 요청이 함께 나간다.
이런 배경지식을 갖고 Wireshark을 통해 문제가 발생한 경우 TCP 분석을 활용할 수 있다.
분석
I/O Graph
Statistics -> I/O Graphs에 들어가면 TCP 전체 에러들을 그래프로 표시해준다.
전체 에러 필터는 해제하고, 앞서 살펴본 가장 심각한 Lost Segment 에러를 필터링 해본다. 이름은 Lost Segments로 지었고, Display Filter는 tcp.analysis를 치면 자동완성 부분에 ack_lost_segment 속성이 뜬다. 심각한 오류이므로 색깔은 빨간색, Style은 bar 형태로 표시했다. 아무런 내용이 없음을 볼 수 있다.
다음으로 중요한 Out of Order 필터를 앞서 만든 Lost Segments 필터에 추가한다. 그럼 에러가 발생한 것을 볼 수 있다.
또한 위에서 설명한 Retrasmission, duplicate_ack 에러를 추가해본다. 마지막으로 Application 단에서 buffer에 제대로 패킷이 들어오지 못하는 zero_window도 체크해볼 수 있다.
그래프를 분석해보면, 초기에 zero_window가 나면서 버퍼에 여유가 없다가(수신 측의 buffer가 가득 찼다가), 25초 후 다시 window가 업데이트 되면서 다시 통신이 일어난 것을 볼 수 있다. 그리고 50초 이후대에 아래 그림처럼 갑자기 트래픽이 몰리는 현상도 볼 수 있다.
TCP Stream Grpah
TCP 요청에 우클릭 -> Follow -> TCP Stream을 클릭 후, Statistics -> TCP Stream Graphs -> Time Sequence(Stevens)를 클릭해보면 아래 그림같은 그래프를 도출할 수 있다.
위 I/O Graph와 마찬가지인데, 1번 구간은 Zero Window가 발생한 지점이다.
정상적으로 네트워크 송수신이 된다면 2번이 가장 이상적인 그래프이다. 만약 네트워크 상황이 좋지 않아서 속도가 느리다면 3번 그래프처럼 보일 것이다. 현재 4번 그래프처럼 기울기가 일정하지 않고, Sequence의 번호도 들쭉날쭉한 상황이라면 에러가 의심되는 상황인 것이다.
HTTPS 트래픽을 평문으로 보기(SSL Inspection)
https가 적용된 사이트에서 패킷을 받아보면, TLS 프로토콜로 확인이 가능하다. https, http2가 아니다. TLS도 SSL(Secure Socket Layer)와 비슷하게 전송 계층이라는 의미를 담아서 Transport Layer Security로 표현할 뿐이다.
브라우저와 서버가 통신 시, TCP -> TLS -> HTTP | HTTP2 방식으로 통신을 한다.
서버단에는 SSL 인증서 내에 Public Key, Private Key가 있으며 Public Key는 암호화에, Private Key는 복호화에 사용한다. 클라이언트(브라우저) 에서는 암호화된 Session Key를 갖고 있다. Session Key를 통해 암호화, 복호화를 하는데 이 암호화된 Session Key는 SSL 인증서의 Public Key를 통해 수행한다.
Session Key를 추출하면 이를 통해 복호화가 가능하다. 그리고 이를 위해서 SSL 인증서의 Public Key가 필요하고, Public Key에 대한 정보를 얻기 위해서는 Private Key까지 얻어내야한다.
일단 Session Key를 얻기 위해서 브라우저가 Session Key를 만드는 Log를 추적하도록 해야한다. 강의에서는 윈도우 및 크롬 기준으로 로그를 저장하는 방법을 설명하는데, 나의 경우에는 크롬은 잘 안되고, 파이어폭스도 개발자 버전으로 진행해야만 브라우저가 로그를 남겨줬다. 방법은 아래 링크를 참고했다.
https://stackoverflow.com/questions/61947541/sslkeylog-file-for-chrome-mac-not-working
Date="$(date)"
mkdir -p -- "$Date"
cd "$Date"
export SSLKEYLOGFILE=$PWD/keylog.log
open -n /Applications/Firefox\ Developer\ Edition.app
그리고 Edit -> Preferences 항목이 사라져서 여러가지로 시도해보다 방법을 찾았다.
패킷 하나 우클릭 -> Protocol References -> Transport Layer Security -> Open Transport Layer Security Preferences -> TLS 선택 후 강의 내용대로 로그 추가
로그 등록 전에는 TLSv1.2, TLSv1.3 프로토콜의 패킷들만 보이다가, 로그 추가 후에는 HTTP2 프로토콜의 패킷들도 보인다.
Fiddler
Fiddler는 L7의 Application 단에서 통신 시, Client <-> Server 사이에 있는 로컬의 Proxy쪽을 분석할 때 편하게 사용할 수 있는 도구이다. Client <-> Proxy간은 HTTP로 통신하고, Proxy <-> Server간은 HTTPS로 통신하면, 패킷 분석을 위해서 그냥 Proxy 쪽의 HTTP를 분석하는게 편할 것이다.
다만 회원가입도 해야하고 10일 동안만 Free Trial로 이용할 수 있다. 강의 내용 대비 UI도 많이 바뀌어서 그냥 Fiddler가 어떤 기능을 제공하는지만 화면 캡쳐를 통해 기록해둔다.
보통 브라우저의 경우 개발자 도구를 통해서 모든 요청에 대한 상세한 정보들을 살펴볼 수 있다. 그런데 Fiddler는 이런 브라우저뿐만 아니라 외부와 통신하는 프로세스들을 아래 화살표처럼 창 위에 Handler를 끌어놓아서 통신을 살펴볼 수 있다. 그리고 HTTPS와 같이 암호화된 경우, 마치 해킹처럼 Fiddler에서 SSL 인증서를 만들어서 Session Key를 해석하고 요청을 HTTP화한다.
참조
널널한 개발자TV 강의
https://www.youtube.com/watch?v=jnKdAg4gMrc&list=PLXvgR_grOs1AM8xNKin4NPEb-VL7bkSal
'Programming-[Backend] > Network, etc' 카테고리의 다른 글
국가별, 언어별 코드 표준: ISO 3166-1, ISO639-1, Accept-Language header (0) | 2023.11.16 |
---|---|
Stream 방식의 이해: RTSP, RTMP, HLS, WCS(Web Call Server), CCTV 접속 방식 (0) | 2023.11.14 |
[TIL][link] HTTP 상태 코드별 내용 정리 (0) | 2023.09.08 |
ngrok: 로컬 서버 인터넷 연결, 콜백 api 예제(AWS 람다) (0) | 2022.10.27 |