알아두면 좋은 IT 지식/Network

"그쪽 네트워크 문제 아니에요?" 네트워크 분쟁의 해결사 TCPDUMP 사용법 (생성~분석)

uutopia 2022. 11. 3. 13:01

서로 다른 시스템간에 인터페이스를 하다보면 가장 쉽게 발생하는 문제 중 하나가 바로 네트워크 오류인데,

잘 알지 못하면 또 이것만큼 해결이 어려운 문제가 없다.

왜냐? 서로 남탓을 하기 아주 딱 좋은 문제이기 때문이다.

그리고 서로 잘못이 없다고 우길 때, 이 분쟁의 해결사로 가장 먼저 등장하는 카드가 바로 tcp dump이다.


"아무리 봐도 우리쪽 시스템은 문제는 없는거 같은데 갑자기 연결이 끊겼어요. 그쪽 네트워크 문제 아니에요?"

"tcpdump를 떠보니 18시18분18초에 그쪽에서 Fin을 보낸게 확인 되네요. 확인 좀 해주세요."

같은 상황이지만 전자의 경우 갈등이 시작되고, 후자의 경우 갈등이 해결된다.

그럼 후자가 되기위해 리눅스에서 사용할 수 있는 가장 간단한 tcpdump 사용법과 분석법에 대해서 알아보자.

 

 

TCP DUMP 생성

 

먼저 내 서버에서 사용중인 네트워크 인터페이스명을 알아야 한다.

ifconfig

 

user@host:~$ ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        ...
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        ...
virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ...

 

 

ifconfig 명령어를 실행하면 아마 비슷한 결과가 나올 것이다.

현재 이 환경에서 lo(로컬)와 virbr0(가상머신)을 제외하고 외부 통신을 위해 사용중인 네트워크는 enp0s3이다.

이제 tcpdump를 생성해보자

tcpdump -i 네트워크명 tcp port 포트 -w 파일명

 

user@host:~$ sudo tcpdump -i enp0s3 -nn -vvv tcp port 30000 -w tcpdump.pcap
tcpdump: listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
Got 0

 

enp0s3 인터페이스를 통하는 네트워크 중 30000포트를 사용하는 패킷을 캡쳐한다.

많이 사용하는 옵션으로 -nn -vvv 를 추가하여 IP주소와 함께 상세 내용을 남기도록 한다.

패킷을 주고 받을 때마다 Got 뒤의 숫자가 증가한다.

원하는 만큼 패킷을 수집했다면 Ctrl + C 명령어를 통해서 dump를 종료하면서 tcpdump.pcap 파일에 내용을 저장한다.

 

 

TCP DUMP 분석

 

분석을 위해서 -r 옵션을 통해서 생성된 tcpdump.pcap파일을 읽는다.

tcpdump -r 파일명

 

user@host:~$ tcpdump -r tcpdump.pcap
reading from file tcpdump.pcap, link-type EN10MB (Ethernet)
10:18:28.202418 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [S], seq 1129860261, win 64240, options [mss 1460,sackOK,TS val 663111988 ecr 0,nop,wscale 7], length 0
10:18:28.202486 IP 10.0.2.15.30000 > 10.0.2.16.26570: Flags [S.], seq 903682989, ack 1129860262, win 28960, options [mss 1460,sackOK,TS val 778627761 ecr 663111988,nop,wscale 7], length 0
10:18:28.203045 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [.], ack 1, win 502, options [nop,nop,TS val 663111989 ecr 778627761], length 0
10:18:33.435463 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [P.], seq 1:5, ack 1, win 502, options [nop,nop,TS val 663117222 ecr 778627761], length 4
10:18:33.435553 IP 10.0.2.15.30000 > 10.0.2.16.26570: Flags [.], ack 5, win 227, options [nop,nop,TS val 778632994 ecr 663117222], length 0
10:18:36.754876 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [F.], seq 5, ack 1, win 502, options [nop,nop,TS val 663120541 ecr 778632994], length 0
10:18:36.755035 IP 10.0.2.15.30000 > 10.0.2.16.26570: Flags [F.], seq 1, ack 6, win 227, options [nop,nop,TS val 778636313 ecr 663120541], length 0
10:18:36.755368 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [.], ack 2, win 502, options [nop,nop,TS val 663120542 ecr 778636313], length 0

 

복잡해 보이지만 기본적인 내용을 제대로 한 번 숙지해 놓으면 분석이 그리 어렵진 않다.

위에서부터 차례대로 한줄씩 분석을 진행해 볼건데,

우선 첫 줄은 내용 하나하나 무엇을 의미하는지 자세히 한 번 알아보자.

 

 

 

10:18:28.202418 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [S], seq 1129860261, win 64240, options [mss 1460,sackOK,TS val 663111988 ecr 0,nop,wscale 7], length 0

  • 10:18:28.202418 : 패킷 발생 시간
  • 10.0.2.16:26570 : 출발지 주소
  • 10.0.2.15:30000 : 목적지 주소
  • Flags [S] : S=Syn / 연결 요청을 나타내는 신호
  • seq 1129860261 : 요청 sequence 번호 (고유 번호)
  • win 64240 : 수신측이 수신 가능한 버퍼 사이즈
  • mss 1460 : 한 패킷으로 전송할 수 있는 최대 크기
  • sackOK : 패킷 손실 추적 기능 사용 여부
  • TS val 663111988 : 송신자 자신의 TimeStamp 값
  • ecr 0 : 수신받은 패킷의 TimeStamp 값
  • nop : 4바이트 패딩 (필요시 송신측 필드를 4바이트 배수가 되도록 채움)
  • wscale 7 : win의 최대값을 증가
  • length 0 : 패킷의 길이

여기서 가장 기본이 되는 내용은? 10.0.2.16서버의 26570포트에서 10.0.2.15서버의 30000포트로 연결을 요청했다는 것!

사실 이정도 기본내용만 알고 있어도 많은 도움이 된다.

두번째 줄 부터는 중요한 내용만 알아보자.

 

 

 

10:18:28.202486 IP 10.0.2.15.30000 > 10.0.2.16.26570: Flags [S.], seq 903682989, ack 1129860262, win 28960, options [mss 1460,sackOK,TS val 778627761 ecr 663111988,nop,wscale 7], length 0

  • ack 1129860262 : 요청에 대한 응답 번호 (첫번째 줄의 seq 값 +1)
  • ecr 663111988 : 첫번째 줄의 TS val과 일치
  • 15서버가 16서버로 S. 신호를 보냄
  • S뒤에 붙은 .은 Ack패킷으로 응답을 의미
  • 16서버의 연결 요청에 대한 응답과 함께 15서버도 연결 요청을 시도

 

 

10:18:28.203045 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [.], ack 1, win 502, options [nop,nop,TS val 663111989 ecr 778627761], length 0

  • 15서버의 연결요청에 대해서 16서버가 응답을 보내고 연결이 정상적으로 맺어짐

 

 

10:18:33.435463 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [P.], seq 1:5, ack 1, win 502, options [nop,nop,TS val 663117222 ecr 778627761], length 4

  • length 4 : 패킷의 길의 = 4
  • P는 Push패킷으로 Data전송을 의미
  • 16서버가 length 4 만큼의 Data를 전송

 

 

10:18:33.435553 IP 10.0.2.15.30000 > 10.0.2.16.26570: Flags [.], ack 5, win 227, options [nop,nop,TS val 778632994 ecr 663117222], length 0

  • 15서버가 Data를 정상적으로 수신

 

 

10:18:36.754876 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [F.], seq 5, ack 1, win 502, options [nop,nop,TS val 663120541 ecr 778632994], length 0

  • F는 Fin패킷으로 연결 종료를 의미
  • 16서버가 연결 종료 시도

 

 

10:18:36.755035 IP 10.0.2.15.30000 > 10.0.2.16.26570: Flags [F.], seq 1, ack 6, win 227, options [nop,nop,TS val 778636313 ecr 663120541], length 0

  • 15서버가 연결 종료 응답과 함께 연결 종료 시도

 

 

10:18:36.755368 IP 10.0.2.16.26570 > 10.0.2.15.30000: Flags [.], ack 2, win 502, options [nop,nop,TS val 663120542 ecr 778636313], length 0

  • 16서버의 응답으로 정상적으로 연결 종료

 

 

이렇게 기본적인 tcp덤프 생성방법과 분석방법만 알고 있어도 웬만한 네트워크 문제 상황에 대응이 가능 하다.

반대로 이것도 모르면서 상대방 네트워크만 탓한다? 욕먹고 무시당하기 쉽상이다.