네트워크 패킷 캡처
아래의 예시에서는 tcpdump를 사용하여 workerman-chat 애플리케이션이 websocket을 통해 전송하는 데이터를 확인합니다. workerman-chat 예시에서 서버는 7272 포트를 통해 외부에 websocket 서비스를 제공합니다. 따라서 7272 포트에서 데이터 패킷을 캡처합니다.
-
명령 실행
tcpdump -Ans 4096 -iany port 7272 -
브라우저 주소창에 입력
http://127.0.0.1:55151 -
닉네임 입력
mynick -
입력창에
hi, all !작성
최종 캡처된 데이터는 다음과 같습니다:
/*
* TCP 첫 번째 핸드셰이크
* 브라우저 로컬 포트 60653이 원격 포트 7272에 SYN 패킷을 전송
*/
17:50:00.523910 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [S], seq 3524290970, win 32768, options [mss 16396,sackOK,TS val 28679666 ecr 28679554,nop,wscale 7], length 0
E..<.h@.@.HQ...........h..i..........0....@....
............
/*
* TCP 두 번째 핸드셰이크
* 원격 포트 7272가 브라우저 포트 60653에 SYN+ACK 패킷을 응답
*/
17:50:00.523935 IP 127.0.0.1.7272 > 127.0.0.1.60653: Flags [S.], seq 692696454, ack 3524290971, win 32768, options [mss 16396,sackOK,TS val 28679666 ecr 28679666,nop,wscale 7], length 0
E..<..@.@.<..........h..)I....i......0....@....
............
/*
* TCP 세 번째 핸드셰이크, TCP 연결 완료
* 브라우저 로컬 포트 60653이 원격 포트 7272에 ACK 패킷을 전송
*/
17:50:00.523948 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [.], ack 1, win 256, options [nop,nop,TS val 28679666 ecr 28679666], length 0
E..4.i@.@.HX...........h..i.)I.......(.....
........
/*
* websocket 핸드셰이크
* 브라우저 로컬 포트 60653이 원격 포트 7272에 websocket 핸드셰이크 요청 데이터를 전송
*/
17:50:00.524412 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [P.], seq 1:716, ack 1, win 256, options [nop,nop,TS val 28679666 ecr 28679666], length 715
E....j@.@.E............h..i.)I.............
........GET / HTTP/1.1
Host: 127.0.0.1:7272
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://127.0.0.1:55151
Sec-WebSocket-Key: zPDr6m4czzUdOFnsxIUEAw==
Cookie: Hm_lvt_abcf9330bef79b4aba5b24fa373506d9=1402048017; Hm_lvt_5fedb3bdce89499492c079ab4a8a0323=1403063068,1403141761; Hm_lvt_7b1919221e89d2aa5711e4deb935debd=1407836536; Hm_lpvt_7b1919221e89d2aa5711e4deb935debd=1407837000
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
/*
* websocket 핸드셰이크
* 원격 포트 7272가 브라우저 포트 60653에 ACK 패킷을 전송, 원격 7272 포트가 websocket 핸드셰이크 요청 데이터를 수신했음을 나타냄
*/
17:50:00.524423 IP 127.0.0.1.7272 > 127.0.0.1.60653: Flags [.], ack 716, win 256, options [nop,nop,TS val 28679666 ecr 28679666], length 0
E..4(u@.@..M.........h..)I....lf.....(.....
........
/*
* websocket 핸드셰이크
* 원격 포트 7272가 브라우저 포트 60653에 websocket 핸드셰이크 응답을 전송, 핸드셰이크 성공을 나타냄
*/
17:50:00.535918 IP 127.0.0.1.7272 > 127.0.0.1.60653: Flags [P.], seq 1:157, ack 716, win 256, options [nop,nop,TS val 28679669 ecr 28679666], length 156
E...(v@.@............h..)I....lf...........
........HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Sec-WebSocket-Version: 13
Connection: Upgrade
Sec-WebSocket-Accept: nSsCeIBUsFnDJCRb/BNlFzBUDpM=
/*
* websocket 핸드셰이크 성공
* 브라우저 로컬 포트 60653이 원격 포트 7272에 ACK를 전송, websocket 핸드셰이크 응답 데이터를 수신했음을 나타냄
*/
17:50:00.535932 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [.], ack 157, win 256, options [nop,nop,TS val 28679669 ecr 28679669], length 0
E..4.k@.@.HV...........h..lf)I.#.....(.....
........
/*
* 닉네임 입력 요청
* 브라우저가 websocket 프로토콜을 통해 7272 포트로 닉네임 요청 {"type":"login","name":"mynick"}
* 브라우저가 서버에 전송한 데이터는 websocket 프로토콜 마스크 처리가 된 데이터이므로 원문 {"type":"login","name":"mynick"}을 확인할 수 없음
*/
17:50:30.652680 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [P.], seq 716:754, ack 157, win 256, options [nop,nop,TS val 28687198 ecr 28679669], length 38
E..Z.l@.@.H/...........h..lf)I.#.....N.....
...^.......&_...+..C}..J0..H}..H>...e.._1..M}.
/*
* 닉네임 입력 요청
* 7272 포트가 브라우저에 ACK를 반환하여 닉네임 요청이 수신되었음을 나타내며 사용자 목록을 반환 {"type":"user_list" ...
*/
17:50:30.653546 IP 127.0.0.1.7272 > 127.0.0.1.60653: Flags [P.], seq 157:267, ack 754, win 256, options [nop,nop,TS val 28687198 ecr 28687198], length 110
E...(w@.@............h..)I.#..l............
...^...^.l{"type":"user_list","user_list":[{"uid":783654164,"name":"\u732a\u732a"},{"uid":783700053,"name":"mynick"}]}
/*
* 닉네임 입력 요청
* 브라우저가 ACK를 반환하여 사용자 목록 데이터가 수신되었음을 나타냄
*/
17:50:30.653559 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [.], ack 267, win 256, options [nop,nop,TS val 28687198 ecr 28687198], length 0
E..4.m@.@.HT...........h..l.)I.......(.....
...^...^
/*
* 닉네임 입력 요청 완료
* 7272 포트가 브라우저에 ACK를 반환하고 로그인 결과를 반환 {"type":"login",...
*/
17:50:30.653689 IP 127.0.0.1.7272 > 127.0.0.1.60653: Flags [P.], seq 267:346, ack 754, win 256, options [nop,nop,TS val 28687198 ecr 28687198], length 79
E...(x@.@............h..)I....l......w.....
...^...^.M{"type":"login","uid":783700053,"name":"mynick","time":"2014-08-12 17:50:30"}
/*
* 닉네임 입력 요청 완료
* 브라우저가 ACK를 반환하여 로그인 결과 데이터 패킷을 수신했음을 나타냄
*/
17:50:30.653695 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [.], ack 346, win 256, options [nop,nop,TS val 28687198 ecr 28687198], length 0
E..4.n@.@.HS...........h..l.)I.......(.....
...^...^
/*
* 서버端 7272 포트가 다른 브라우저에 새 사용자가 로그인했음을 알림
*/
17:50:30.653749 IP 127.0.0.1.7272 > 127.0.0.1.60584: Flags [P.], seq 436:515, ack 816, win 256, options [nop,nop, TS val 28687198 ecr 28577913], length 79
E.....@.@.3..........h..f....G.......w.....
...^...y.M{"type":"login","uid":783700053,"name":"mynick","time":"2014-08-12 17:50:30"}
/*
* 다른 브라우저가 ACK를 반환하여 새 사용자 로그인 알림 요청을 수신했음을 나타냄
*/
17:50:30.653755 IP 127.0.0.1.60584 > 127.0.0.1.7272: Flags [.], ack 515, win 256, options [nop,nop,TS val 28687198 ecr 28687198], length 0
E..4.X@.@.#j...........h.G..f..$.....(.....
...^...^
/*
* mynick 사용자가 발언 hi, all !
* 브라우저가 서버 7272 포트에 발언 데이터를 전송 {"type":"say","to_uid":"all","content":"hi, all !"}
* 브라우저가 서버에 전송한 데이터는 websocket 프로토콜 마스크 처리가 된 데이터이므로 원문을 확인할 수 없음
*/
17:51:02.775205 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [P.], seq 754:812, ack 346, win 256, options [nop,nop,TS val 28695228 ecr 28687198], length 58
E..n.o@.@.H............h..l.)I.......b.....
fTX.d.P[(...9H..C=LT.~.BV=...0SnB-X.
/*
* mynick 사용자가 발언 hi, all !
* 7272 포트가 모든 브라우저 클라이언트 중 하나에 발언 데이터를 전달 {"type":"say","from_uid":....
*/
17:51:02.776785 IP 127.0.0.1.7272 > 127.0.0.1.60653: Flags [P.], seq 346:448, ack 812, win 256, options [nop,nop,TS val 28695229 ecr 28695228], length 102
E...(y@.@............h..)I....l............
.........d{"type":"say","from_uid":783700053,"to_uid":"all","content":"hi, all !","time":"2014-08-12 :51:02"}
/*
* mynick 사용자가 발언 hi, all !
* 브라우저가 ACK를 응답하여 발언 데이터를 수신했음을 나타냄
*/
17:51:02.776808 IP 127.0.0.1.60653 > 127.0.0.1.7272: Flags [.], ack 448, win 256, options [nop,nop,TS val 28695229 ecr 28695229], length 0
E..4.p@.@.HQ...........h..l.)I.F.....(.....
........
/*
* mynick 사용자가 발언 hi, all !
* 7272 포트가 모든 브라우저 클라이언트 중 하나에 발언 데이터를 전달 {"type":"say","from_uid":....
*/
17:51:02.776827 IP 127.0.0.1.7272 > 127.0.0.1.60584: Flags [P.], seq 515:617, ack 816, win 256, options [nop,nop,TS val 28695229 ecr 28687198], length 102
E.....@.@.3g.........h..f..$.G.............
.......^.d{"type":"say","from_uid":783700053,"to_uid":"all","content":"hi, all !","time":"2014-08-12 :51:02"}
/*
* mynick 사용자가 발언 hi, all ! 모든 브라우저가 전달된 발언 데이터를 수신, 발언 완료
* 브라우저가 ACK를 응답하여 발언 데이터를 수신했음을 나타냄
*/
17:51:02.776842 IP 127.0.0.1.60584 > 127.0.0.1.7272: Flags [.], ack 617, win 256, options [nop,nop,TS val 28695229 ecr 28695229], length 0
E..4.Y@.@.#i...........h.G..f........(.....
........
이상은 로그인 + 발언의 모든 요청이며, 총 두 개의 브라우저 클라이언트가 있습니다.
패킷 데이터에서 [S]는 SYN 요청(연결 요청 시작)을 나타내고, [.]는 ACK 응답을 의미하며 요청 대상이 수신했음을 나타냅니다. [P]는 데이터 전송을 나타내며, P.는 [P] + [.]를 의미합니다.
포트에서 전송하는 데이터가 이진 데이터인 경우 16진수로 확인할 수 있습니다. tcpdump -XAns 4096 -iany port 7272