Skip to content
오늘을살자
Go back

tcpdump 입문: 초보자를 위한 패킷 덤프 읽는 법

Edit page

네트워크 이슈를 디버깅하다 보면 이런 말을 자주 듣는다.

"덤프 떠서 확인해보세요."
"pcap 있나요?"
"SYN은 나갔는데 SYN/ACK가 돌아왔나요?"

처음 들으면 살짝 겁난다.
덤프라고 하니까 뭔가 커널 내부를 파헤쳐야 할 것 같고, 패킷이라고 하니까 TCP/IP 책을 다 외워야 할 것 같다.

하지만 시작은 그렇게 어렵지 않다.

tcpdump는 네트워크 인터페이스를 지나가는 패킷을 터미널에서 캡처하는 도구다. 화면에 바로 출력할 수도 있고, .pcap 파일로 저장해서 Wireshark 같은 도구로 다시 열어볼 수도 있다.

이 글은 tcpdump를 처음 쓰는 사람 기준으로,

를 정리한다.

패킷 덤프가 뭔가

패킷 덤프는 말 그대로 네트워크로 오간 패킷을 기록한 것이다.

애플리케이션 로그가 이렇게 말한다면:

connection timeout
connection reset by peer
read failed

패킷 덤프는 그 아래에서 실제로 무슨 일이 있었는지 보여준다.

내가 SYN을 보냈는가?
상대가 SYN/ACK를 보냈는가?
3-way handshake가 끝났는가?
데이터를 보냈는데 ACK가 왔는가?
누가 FIN 또는 RST를 보냈는가?

즉 로그가 “증상”에 가깝다면, 패킷 덤프는 대화 기록에 가깝다.

먼저 설치 확인

Linux에서는 이미 설치되어 있는 경우가 많다.

tcpdump --version

없다면 배포판에 맞게 설치한다.

# Ubuntu / Debian
sudo apt update
sudo apt install tcpdump

# RHEL / CentOS / Rocky
sudo dnf install tcpdump

패킷 캡처는 보통 관리자 권한이 필요하다. 그래서 예제는 대부분 sudo를 붙인다.

인터페이스부터 확인하기

패킷은 네트워크 인터페이스를 기준으로 캡처한다.

먼저 어떤 인터페이스가 있는지 본다.

ip addr

또는 tcpdump로 캡처 가능한 인터페이스 목록을 볼 수 있다.

sudo tcpdump -D

예를 들어 서버에 이런 인터페이스가 있다고 하자.

1.eth0
2.lo
3.any

의미는 대략 이렇다.

처음에는 any가 편하다.

sudo tcpdump -i any

다만 정확히 어느 물리 포트로 들어오고 나가는지 봐야 한다면 eth0, ens33, enp0s3 같은 실제 인터페이스를 지정하는 편이 좋다.

첫 번째 명령어

가장 기본은 이거다.

sudo tcpdump -i any -nn

여기서 옵션은 두 개만 보면 된다.

-i any  : 어떤 인터페이스에서 캡처할지 지정
-nn     : IP/port를 이름으로 바꾸지 말고 숫자로 보여줌

-nn은 거의 습관처럼 붙이는 편이 좋다.

이 옵션이 없으면 80http로 바꾸거나, IP를 hostname으로 바꾸려고 할 수 있다. 그러면 DNS 조회 때문에 출력이 느려지거나, 오히려 분석이 헷갈릴 수 있다.

출력 한 줄 읽기

예를 들어 이런 줄이 나왔다고 하자.

11:21:03.123456 IP 192.168.0.10.54321 > 93.184.216.34.80: Flags [S], seq 1000, win 64240, length 0

처음에는 길어 보이지만 쪼개면 단순하다.

11:21:03.123456             시간
IP                          IPv4 패킷
192.168.0.10.54321          출발지 IP와 port
>                           왼쪽에서 오른쪽으로 감
93.184.216.34.80            목적지 IP와 port
Flags [S]                   TCP SYN
seq 1000                    TCP sequence number
win 64240                   TCP receive window
length 0                    TCP payload 길이

초보 단계에서는 모든 필드를 다 이해하지 않아도 된다.

처음에는 이 네 가지만 봐도 충분하다.

누가 보냈나?       192.168.0.10
누구에게 보냈나?   93.184.216.34
어떤 포트인가?     80
TCP flag가 뭔가?   SYN

TCP flag 빠르게 보기

TCP 문제를 볼 때는 flag가 중요하다.

자주 보는 값은 이 정도다.

[S]    SYN        연결 시작 요청
[S.]   SYN/ACK    연결 요청에 대한 응답
[.]    ACK        확인 응답
[P.]   PSH/ACK    데이터 전송이 포함된 경우가 많음
[F.]   FIN/ACK    정상 종료 요청
[R]    RST        강제 종료

TCP 연결 시작은 보통 이렇게 보인다.

client > server: Flags [S]
server > client: Flags [S.]
client > server: Flags [.]

이게 흔히 말하는 3-way handshake다.

만약 클라이언트가 [S]를 여러 번 보내는데 [S.]가 안 돌아오면:

반대로 [S.]는 왔는데 마지막 ACK가 안 보이면 클라이언트 쪽이나 캡처 위치를 다시 봐야 한다.

너무 많이 보이면 필터를 건다

운영 서버에서 그냥 tcpdump -i any -nn을 치면 화면이 순식간에 지나간다.

그래서 필터를 걸어야 한다.

특정 host만 보고 싶으면:

sudo tcpdump -i any -nn host 192.168.0.10

특정 port만 보고 싶으면:

sudo tcpdump -i any -nn port 443

TCP만 보고 싶으면:

sudo tcpdump -i any -nn tcp

UDP 53번, 즉 DNS만 보고 싶으면:

sudo tcpdump -i any -nn udp port 53

조건은 조합할 수 있다.

sudo tcpdump -i any -nn 'host 192.168.0.10 and tcp port 443'

여기서 따옴표를 붙이는 이유는 and, or, 괄호 같은 표현이 shell에서 먼저 해석되지 않게 하기 위해서다.

방향까지 좁히기

출발지와 목적지를 나눠 보고 싶을 때가 있다.

특정 IP에서 나가는 패킷:

sudo tcpdump -i any -nn 'src host 192.168.0.10'

특정 IP로 들어오는 패킷:

sudo tcpdump -i any -nn 'dst host 192.168.0.10'

특정 서버의 443번 포트로 들어가는 TCP:

sudo tcpdump -i any -nn 'dst host 10.0.0.5 and tcp dst port 443'

필터는 영어 문장처럼 읽으면 된다.

dst host 10.0.0.5 and tcp dst port 443
= 목적지가 10.0.0.5이고, TCP 목적지 포트가 443인 패킷

개수 제한하기

처음 연습할 때는 무한정 캡처하지 말고 개수를 제한하는 게 좋다.

sudo tcpdump -i any -nn -c 20
-c 20 : 20개 패킷만 캡처하고 종료

장애 재현이 짧다면 이렇게 잡아도 된다.

sudo tcpdump -i any -nn -c 100 'host 192.168.0.10 and port 443'

파일로 저장하기

화면 출력은 빠르게 보기에는 좋지만, 분석에는 파일 저장이 더 좋다.

sudo tcpdump -i any -nn -w capture.pcap 'host 192.168.0.10 and port 443'
-w capture.pcap : 화면에 풀어서 출력하지 않고 pcap 파일로 저장

이렇게 저장한 파일은 나중에 다시 읽을 수 있다.

tcpdump -nn -r capture.pcap

또는 Wireshark에서 열어도 된다.

File -> Open -> capture.pcap

실무에서는 보통 서버에서 tcpdump로 파일을 뜨고, 내 PC로 가져와서 Wireshark로 자세히 본다.

payload까지 저장하고 싶을 때

예전 자료를 보면 -s 0 옵션이 자주 나온다.

sudo tcpdump -i any -nn -s 0 -w capture.pcap 'host 192.168.0.10'

-s는 snap length, 즉 패킷 하나에서 몇 바이트까지 캡처할지 정하는 옵션이다.

현대 tcpdump에서는 기본 snap length가 충분히 큰 경우가 많지만, 환경마다 다를 수 있다. 초보자 입장에서는 “payload가 잘려 보이면 -s 0 또는 충분히 큰 값으로 캡처한다” 정도로 기억하면 된다.

단, payload까지 저장하면 민감한 정보가 들어갈 수 있다.

HTTPS처럼 암호화된 트래픽은 내용이 바로 보이지 않지만, IP/port/연결 패턴 같은 메타데이터는 여전히 남는다.

tcpdump와 Wireshark 역할 나누기

둘 중 하나만 써야 하는 건 아니다.

tcpdump는 서버에서 캡처하기 좋다.

Wireshark는 캡처 후 분석하기 좋다.

흐름은 보통 이렇다.

서버에서 tcpdump로 pcap 저장
        |
        v
로컬 PC로 pcap 복사
        |
        v
Wireshark로 열어서 상세 분석

장애 상황별로 먼저 볼 것

1. connection timeout

timeout은 “응답을 기다렸는데 안 왔다”에 가깝다.

먼저 SYN 흐름을 본다.

sudo tcpdump -i any -nn 'host 10.0.0.5 and tcp port 443'

볼 포인트:

클라이언트가 SYN을 보내는가?
서버가 SYN/ACK를 보내는가?
SYN이 같은 간격으로 재전송되는가?

예를 들어 이런 식이면 서버 응답이 안 보이는 상태다.

client > server: Flags [S]
client > server: Flags [S]
client > server: Flags [S]

이때는 서버 프로세스보다 먼저 네트워크 경로, 방화벽, 라우팅, 보안그룹을 의심한다.

2. connection refused

refused는 보통 상대가 RST를 돌려주는 상황이다.

client > server: Flags [S]
server > client: Flags [R.]

의미는 대략 이렇다.

서버까지는 갔다.
그런데 해당 port를 받아줄 프로세스가 없거나, OS/방화벽이 명시적으로 거절했다.

이때는 서버에서 프로세스가 listen 중인지 본다.

ss -lntp

3. 중간에 끊김

연결이 되었다가 중간에 끊기면 FIN/RST를 본다.

sudo tcpdump -i any -nn 'host 10.0.0.5 and tcp port 443'

볼 포인트:

누가 FIN을 먼저 보냈나?
누가 RST를 보냈나?
RST 직전에 재전송이나 window 문제가 있었나?

정상 종료는 대개 FIN이 오간다.

강제 종료나 비정상 종료는 RST가 보이는 경우가 많다.

4. DNS가 이상함

도메인 접속이 안 되면 DNS부터 따로 본다.

sudo tcpdump -i any -nn 'udp port 53'

볼 포인트:

DNS query가 나가는가?
DNS response가 돌아오는가?
응답 IP가 기대한 값인가?

DNS 문제가 있으면 TCP 연결 자체를 보기 전에 이미 목적지 IP를 못 찾고 있을 수 있다.

캡처 위치가 중요하다

같은 장애라도 어디서 캡처하느냐에 따라 보이는 것이 다르다.

Client ---- Firewall ---- Server

클라이언트에서 보면 SYN이 나갔다.

Client capture:
client > server: SYN
client > server: SYN retransmission

서버에서 보면 아무것도 안 보인다.

Server capture:
no packet

이 경우 서버 애플리케이션 문제가 아니라 중간 경로 문제일 가능성이 커진다.

반대로 서버에서는 SYN이 보이고 SYN/ACK도 나갔는데, 클라이언트에서는 SYN/ACK가 안 보일 수 있다.

Server capture:
client > server: SYN
server > client: SYN/ACK

Client capture:
client > server: SYN
client > server: SYN retransmission

이 경우는 돌아오는 경로를 봐야 한다.

패킷 덤프의 핵심은 “한 곳에서만 보고 단정하지 않는 것”이다.

운영 서버에서 조심할 점

패킷 캡처는 생각보다 민감하다.

운영 서버에서는 아래를 조심한다.

파일 크기가 걱정되면 port와 host를 최대한 좁힌다.

sudo tcpdump -i any -nn -s 0 -w api-443.pcap \
  'host 10.0.0.5 and tcp port 443'

오래 떠야 한다면 파일 회전 옵션을 검토한다.

sudo tcpdump -i any -nn -s 0 \
  -C 100 -W 5 -w capture.pcap \
  'host 10.0.0.5 and tcp port 443'
-C 100 : 파일 하나를 약 100MB 단위로 회전
-W 5   : 최대 5개 파일 유지

초보자용 치트시트

처음에는 아래만 기억해도 충분하다.

# 전체를 빠르게 보기
sudo tcpdump -i any -nn

# 20개만 보고 종료
sudo tcpdump -i any -nn -c 20

# 특정 IP만 보기
sudo tcpdump -i any -nn host 192.168.0.10

# 특정 port만 보기
sudo tcpdump -i any -nn port 443

# 특정 IP + TCP port
sudo tcpdump -i any -nn 'host 192.168.0.10 and tcp port 443'

# DNS 보기
sudo tcpdump -i any -nn 'udp port 53'

# pcap 저장
sudo tcpdump -i any -nn -s 0 -w capture.pcap 'host 192.168.0.10'

# pcap 다시 읽기
tcpdump -nn -r capture.pcap

처음 분석할 때의 순서

패킷을 열었는데 어디서부터 봐야 할지 모르겠다면 이 순서로 보면 된다.

1. 내가 캡처한 위치가 맞는가?
2. 대상 IP와 port가 맞는가?
3. DNS query/response는 정상인가?
4. TCP SYN이 나가는가?
5. SYN/ACK가 돌아오는가?
6. 누가 FIN/RST를 먼저 보내는가?
7. retransmission이 반복되는 구간이 있는가?
8. window size가 0으로 막히는 구간이 있는가?

이 순서만 따라가도 “애플리케이션 문제인지, 네트워크 경로 문제인지, 상대 서버 문제인지”를 꽤 많이 좁힐 수 있다.

정리

tcpdump는 어렵게 보이지만, 처음에는 몇 가지 패턴만 익히면 된다.

중요한 건 모든 패킷을 다 해석하는 능력이 아니다.

처음에는 이 질문에 답하는 것만으로도 충분하다.

내 패킷은 나갔나?
상대 응답은 돌아왔나?
누가 먼저 끊었나?
어디까지는 보이고, 어디부터 안 보이나?

네트워크 디버깅은 이 질문들을 하나씩 지워가는 작업이다.

참고 자료


Edit page
Share this post on:

Previous Post
Wireshark 사용 팁: pcap을 처음 열었을 때 어디부터 봐야 할까
Next Post
lwIP RAW TCP가 '가끔 멈춘다': tcp_recved() 안 치면 윈도우가 안 열린다