본문으로 건너뛰기
고급약 28분

Wireshark·tcpdump 실전: 프록시로 안 될 때 패킷을 본다

"가끔 연결이 끊긴다", "인증서 오류가 난다" 같은 문제는 애플리케이션 로그에 흔적이 없다. 패킷 레벨에서 원인을 좁히는 최소한의 기술을 익힌다.

  • #Wireshark
  • #tcpdump
  • #패킷분석
  • #TCP
  • #TLS
  • #네트워크진단

개념

프록시가 답을 못 주는 순간

앞 레슨에서 프록시로 트래픽을 보고 조작하는 법을 익혔다. 대부분의 API 문제는 거기서 끝난다. 그런데 프록시가 아무 도움이 안 되는 상황이 있다.

증상프록시로 안 되는 이유
앱이 인증서 피닝을 써서 프록시를 거부한다트래픽 자체가 안 흐른다
"가끔" 연결이 끊긴다요청 자체가 성립하지 않아 목록에 안 뜬다
HTTP가 아닌 통신(gRPC 스트림, WebSocket, DB, MQTT)프록시가 다루는 계층이 아니다
서버에서만 재현된다서버에 GUI 프록시를 띄울 수 없다
방화벽·라우팅 문제로 의심된다연결 이전 단계의 문제다

공통점은 "요청이 성립하기 전 또는 바깥"에서 문제가 난다는 것 이다. 모듈 9(레슨 6)에서 배운 DNS·TCP/IP·포트 지식이 여기서 도구를 만난다.

이 레슨의 목표는 패킷 분석 전문가가 되는 것이 아니다. QA가 원인을 한 단계 좁혀 "네트워크 계층 문제로 보인다"까지 말할 수 있게 되는 것 이 목표다. 그 한 단계가 인프라팀과의 대화를 완전히 바꾼다.

두 도구의 역할 분담

tcpdump      터미널에서 캡처한다.  서버·CI·원격 장비에서 쓴다.
   │         GUI가 없는 곳에서 유일한 선택지다.
   │
   └─▶ .pcap 파일 ──▶  Wireshark    받아서 분석한다. GUI로 읽는다.
                        필터·통계·흐름 추적이 강하다.

실무의 정석 조합 은 이것이다 — 서버에서 tcpdump로 캡처해 파일로 남기고, 그 파일을 내 PC로 가져와 Wireshark로 분석한다. 서버에 Wireshark를 설치할 일은 거의 없다.

tcpdump — 캡처하는 쪽

기본 형태는 단순하다.

# eth0 인터페이스에서 80·443 포트 트래픽을 파일로 저장
sudo tcpdump -i eth0 -w capture.pcap 'port 80 or port 443'
 
# 특정 호스트와의 통신만
sudo tcpdump -i any -w capture.pcap 'host api.example.com'
 
# 화면에서 바로 보기 (-n: 이름 해석 안 함, 빠르다)
sudo tcpdump -i any -n 'port 443'

QA가 알아둘 옵션은 몇 개 안 된다.

옵션의미왜 필요한가
-i any모든 인터페이스어느 인터페이스인지 모를 때
-w 파일파일로 저장Wireshark로 넘기려면 필수
-nDNS 역조회 안 함캡처가 느려지는 것을 막는다
-s 0패킷 전체 저장잘린 패킷은 분석이 안 된다
-C 100 -W 5100MB씩 5개 순환장시간 캡처의 필수 옵션
-c 10001,000개만 잡고 종료짧게 확인할 때

-C·-W 조합이 실무에서 중요하다. "가끔 발생하는" 문제를 잡으려면 몇 시간을 켜둬야 하는데, 옵션 없이 두면 디스크가 가득 찬다. 순환 저장으로 최근 N개 파일만 남긴다.

캡처 필터와 디스플레이 필터는 다르다 — 이걸 헷갈리면 계속 막힌다.

캡처 필터(tcpdump·Wireshark 캡처 시)디스플레이 필터(Wireshark 분석 시)
적용 시점잡을 때 — 안 잡힌 건 영원히 없다잡은 것 중에서 보여줄 것만
문법BPF (port 443, host x)Wireshark 문법 (tcp.port == 443)
실수하면필요한 패킷을 못 잡는다다시 필터만 바꾸면 된다

캡처 필터는 넓게, 디스플레이 필터로 좁힌다. 처음에는 host 정도만 걸고 넓게 잡는 편이 안전하다.

Wireshark — 분석하는 쪽

파일을 열면 패킷 수만 개가 쏟아진다. 여기서 필요한 것은 디스플레이 필터 다. QA가 쓸 것은 열 개 남짓이다.

ip.addr == 10.0.1.5            특정 IP와 오간 것
tcp.port == 443                포트
http                           HTTP만
tls.handshake.type == 1        TLS Client Hello (연결 시작)
tcp.flags.reset == 1           RST — 연결이 강제로 끊긴 지점
tcp.analysis.retransmission    재전송 — 네트워크 불안정 신호
tcp.analysis.flags             TCP 이상 징후 전체
dns                            DNS 질의·응답
frame contains "orderId"       내용에 특정 문자열 포함
http.response.code >= 500      5xx 응답만

tcp.flags.reset == 1 과 tcp.analysis.retransmission 두 개만 알아도 절반은 해결된다. "연결이 끊긴다", "가끔 느리다"의 직접 증거이기 때문이다.

메뉴에서 알아둘 것도 셋뿐이다.

  • Statistics → Conversations — 어느 상대와 얼마나 주고받았는지. 예상 밖의 서버와 통신하고 있는지 확인할 때
  • Statistics → Protocol Hierarchy — 프로토콜 비중. "이게 전부 TLS인가, 아니면 평문이 섞여 있나"
  • 우클릭 → Follow → TCP Stream — 한 연결의 대화를 처음부터 끝까지 이어서 본다. 가장 자주 쓰게 된다

읽어야 할 세 가지 패턴

패킷을 다 이해할 필요는 없다. QA가 알아볼 패턴은 셋이다.

1) 연결이 안 맺어진다 — 핸드셰이크가 안 끝남

정상적인 TCP 연결은 세 단계로 시작한다.

정상
   클라이언트 ── SYN ──▶ 서버
   클라이언트 ◀─ SYN,ACK ── 서버
   클라이언트 ── ACK ──▶ 서버      → 연결 성립
 
문제 A: SYN만 반복
   클라이언트 ── SYN ──▶ (응답 없음)
   클라이언트 ── SYN ──▶ (응답 없음)   → 방화벽 차단, 잘못된 IP/포트,
   클라이언트 ── SYN ──▶ (응답 없음)     서버가 안 떠 있음
 
문제 B: SYN에 RST로 응답
   클라이언트 ── SYN ──▶ 서버
   클라이언트 ◀─── RST ── 서버        → 그 포트에 아무도 안 듣고 있음

A와 B의 구분이 실무에서 값을 한다. A는 패킷이 사라진 것(방화벽· 라우팅)이고, B는 서버까지 도달했는데 거절당한 것(프로세스 미기동·포트 불일치)이다. 원인 범위와 담당 팀이 다르다.

2) 연결은 됐는데 중간에 끊긴다 — RST

   ... 정상 통신 ...
   클라이언트 ◀─── RST ── 서버      → 서버가 연결을 끊었다

RST가 어느 쪽에서, 언제 나왔는지가 단서다. 흔한 원인들이다.

RST 발생 지점흔한 원인
일정 시간 무통신 후유휴 타임아웃(로드밸런서·방화벽)
대용량 전송 중크기 제한, 타임아웃
특정 요청에서만서버 애플리케이션이 예외로 연결 종료
TLS 핸드셰이크 직후인증서·프로토콜 버전 불일치

"가끔 연결이 끊깁니다"라는 리포트에 RST 발생 시점 정보가 붙으면 인프라팀이 볼 곳이 정해진다.

3) 느리다 — 재전송과 지연

tcp.analysis.retransmission 이 많이 보이면 패킷이 유실되고 있다는 뜻이다. 애플리케이션 로그에는 "응답이 느림"으로만 보이는 현상의 실제 원인일 수 있다.

Wireshark의 시간 열을 Time since previous displayed packet 으로 바꾸면 어디서 시간이 비는지 바로 보인다. 요청을 보내고 응답까지 3초가 비었다면 그건 서버 처리 시간이고, 재전송이 반복되며 3초가 갔다면 네트워크 문제다. 같은 "3초"인데 원인이 완전히 다르다.

TLS 문제 진단 — 인증서 오류의 실제 원인 찾기

"인증서 오류가 납니다"는 QA가 자주 만나는데 원인이 여럿이다. 패킷을 보면 좁혀진다.

tls.handshake.type == 1     Client Hello — 클라이언트가 제안한 것
tls.handshake.type == 2     Server Hello — 서버가 고른 것
tls.alert_message           경고·오류 메시지
Client Hello 이후 상황추정 원인
Server Hello 없이 끊김프로토콜 버전 불일치(구형 TLS 지원 중단 등)
Alert: certificate_expired서버 인증서 만료
Alert: unknown_ca클라이언트가 그 CA를 모름 — 중간 인증서 누락이 흔하다
Alert: handshake_failure암호 스위트 협상 실패
Client Hello의 SNI가 예상과 다름요청이 엉뚱한 호스트로 가고 있다

'중간 인증서 누락'이 실무에서 자주 나온다. 브라우저에서는 잘 되는데 모바일 앱이나 서버 간 통신에서만 실패하는 전형적 패턴이다. 브라우저는 중간 인증서를 캐시해두는 경우가 있어 문제를 가리기 때문이다. 이 차이를 알고 있으면 "브라우저에서는 되는데요"라는 반론에 답할 수 있다.

실무 시나리오 — 어떤 문제에 어디를 보나

증상먼저 볼 것
앱이 서버에 아예 못 붙는다SYN 재시도 / RST 여부, DNS 응답
로그인은 되는데 특정 API만 실패그 요청의 TCP 스트림, HTTP 응답 코드
간헐적 타임아웃재전송, RST 발생 시점, 유휴 시간 패턴
인증서 오류TLS Alert 메시지, 인증서 체인
응답이 느리다시간 열을 delta로, 서버 처리 시간과 네트워크 시간 분리
앱이 예상 밖 서버와 통신Statistics → Conversations
데이터가 깨져서 도착Follow TCP Stream으로 원본 확인

마지막 줄이 QA에게 유용하다. "한글이 깨진다"는 문제가 서버가 잘못 보낸 것인지, 클라이언트가 잘못 해석한 것인지를 패킷의 원본 바이트로 가릴 수 있다. 이건 프록시로도 되지만, 프록시가 못 붙는 상황이면 여기가 답이다.

캡처는 그 자체로 민감 정보다

앞 레슨의 원칙이 여기서는 더 강하게 적용된다.

패킷 캡처에는 그 시간 동안의 모든 통신이 들어 있다. 우리 서비스 트래픽만이 아니라, 같은 기기에서 나간 다른 통신, 다른 사용자의 세션(서버에서 캡처한 경우)까지 들어갈 수 있다.

원칙이유
캡처 필터로 대상을 좁힌다애초에 무관한 것을 안 담는다
필요 시간만 캡처한다장시간 캡처는 그만큼 위험이 크다
pcap 파일을 이슈에 그대로 첨부하지 않는다토큰·개인정보·타 사용자 세션 포함
공유해야 하면 해당 스트림만 내보낸다Wireshark의 Export Specified Packets
운영 서버 캡처는 승인을 받는다성능 영향 + 개인정보 처리 문제
분석 후 파일을 삭제한다남겨두면 잊는다

운영 서버에서의 캡처는 특히 신중해야 한다. 성능에 영향을 주고, 개인정보 처리 방침에 걸릴 수 있다. 반드시 인프라·보안 담당과 합의하고, 캡처 범위와 보관 기간을 정해두고 시작한다.

어디까지가 QA의 일인가

패킷 분석은 깊게 들어가면 네트워크 엔지니어의 영역이다. QA가 여기서 목표로 삼을 것은 명확하다.

   "안 됩니다"
        ↓
   "앱에서 서버로 SYN을 보내는데 응답이 없습니다.
    3회 재시도 후 타임아웃입니다. 캡처 첨부합니다."
        ↓
   → 인프라팀이 방화벽·라우팅을 보면 되는 상태

원인을 규명하는 것이 아니라 범위를 좁혀 넘기는 것 이 목표다. 그리고 그 한 단계가 문제 해결 시간을 크게 줄인다. 모듈 6(레슨 2)에서 배운 좋은 결함 리포트의 원칙이 네트워크 계층으로 확장되는 셈이다.

실무에서 왜 필요한가

QA가 마주치는 문제 중 애플리케이션 로그에 아무 흔적이 없는 것들이 있다. "가끔 끊긴다", "특정 통신사에서만 안 된다", "사무실에서는 되는데 고객사 망에서는 안 된다" 같은 것들이다. 이런 문제는 재현 조건을 못 잡으면 영원히 미해결로 남는다.

패킷 캡처는 그 재현을 증거로 고정 한다. 한 번만 잡아두면 그 파일을 가지고 몇 번이고 분석할 수 있고, 담당 팀에 넘길 수도 있다. 모듈 5 (레슨 12)에서 다룬 "재현 불가능한 버그"에 대한 가장 강력한 대응 수단 중 하나다.

그리고 이 능력은 QA의 범위를 넓힌다. 대부분의 QA가 애플리케이션 계층에서 멈추기 때문에, "네트워크 계층 문제로 보입니다"까지 말할 수 있는 QA는 드물다. 임베디드·IoT·B2B 솔루션처럼 네트워크 환경이 다양한 도메인에서는 특히 그렇다.

실습 과제

과제 1 — 캡처하고 열어보기 (20분)

  1. tcpdump(또는 Wireshark)로 특정 호스트와의 통신을 캡처한다
  2. 브라우저에서 그 사이트를 한 번 방문한다
  3. 캡처를 멈추고 Wireshark로 연다
  4. 다음 필터를 각각 적용하고 몇 개가 남는지 기록한다
필터패킷 수무엇이 보이나
(필터 없음)
tcp.flags.syn == 1
tls.handshake.type == 1
dns
해설 보기

필터 없이 열었을 때의 숫자가 이 과제의 첫 발견이다. 사이트 한 번 방문에 수천 개의 패킷이 오간다. 필터 없이는 아무것도 못 본다 는 것을 체감하는 것이 목적이다.

dns 필터도 흥미롭다. 한 페이지를 여는 데 얼마나 많은 도메인을 조회하는지 보이고, 그중 우리 서비스와 무관한 것(광고·분석 도구)이 얼마나 되는지도 드러난다. 성능 문제를 볼 때 이 관점이 쓰인다.

과제 2 — 연결 실패 세 가지 구분하기 (20분)

의도적으로 실패 상황을 만들고 패킷 패턴을 관찰한다.

상황만드는 방법관찰된 패턴
없는 포트로 연결curl http://localhost:59999
응답 없는 주소존재하지 않는 사설 IP로 연결
정상 연결아무 사이트

RST가 오는 경우와 아무 응답이 없는 경우의 차이 를 한 줄로 정리한다.

해설 보기

없는 포트로 연결하면 대개 즉시 RST 가 온다 — 서버 호스트까지는 도달했고, 그 포트에 아무도 안 듣고 있다는 뜻이다.

존재하지 않는 주소로 보내면 응답 없이 SYN이 몇 번 재전송되다 타임아웃 된다. 패킷이 어딘가에서 사라진 것이다.

이 구분이 실무에서 왜 중요한가 — "서버가 안 떠 있다"와 "방화벽이 막는다"를 가르기 때문이다. RST면 대개 프로세스 문제, 무응답이면 네트워크 경로 문제로 1차 추정할 수 있다. 그 한 문장이 담당 팀을 정한다.

과제 3 — TCP 스트림 따라가기 (15분)

캡처에서 HTTP 요청 하나를 찾아 Follow → TCP Stream 으로 연다.

  • 요청과 응답이 어떻게 이어지는지 확인한다
  • 헤더와 본문이 어디서 나뉘는지 본다
  • HTTPS라면 어떻게 보이는지 확인한다(암호문)

그리고 답한다 — HTTPS 트래픽의 내용을 보려면 무엇이 필요한가? (앞 레슨의 프록시가 왜 필요한지가 여기서 연결된다)

과제 4 — 캡처 공유 규칙 만들기 (12분)

팀에서 쓸 패킷 캡처 취급 규칙을 한 장으로 만든다.

  • 운영 환경 캡처의 승인 절차
  • 캡처 필터로 반드시 좁힐 것
  • 파일 공유 시 처리 방법
  • 보관 기간과 삭제 책임
  • 이슈 트래커 첨부 시 주의사항

자가 체크리스트

  • 프록시로 해결되지 않는 상황 다섯 가지를 들 수 있다
  • tcpdump와 Wireshark의 역할 분담과 실무 조합을 설명할 수 있다
  • tcpdump의 주요 옵션과, 장시간 캡처에 -C·-W가 필요한 이유를 안다
  • 캡처 필터와 디스플레이 필터의 차이를 설명하고, 왜 캡처는 넓게 잡는지 말할 수 있다
  • QA가 자주 쓰는 디스플레이 필터를 다섯 개 이상 쓸 수 있다
  • Follow TCP Stream이 무엇을 보여주는지 안다
  • TCP 3-way 핸드셰이크의 정상 흐름을 그릴 수 있다
  • SYN 무응답과 SYN에 RST 응답의 차이가 무엇을 뜻하는지 설명할 수 있다
  • RST 발생 시점별 흔한 원인을 세 가지 이상 들 수 있다
  • 재전송이 많을 때와 서버 처리가 느릴 때를 시간 열로 구분할 수 있다
  • TLS Alert 메시지로 인증서 문제의 원인을 좁힐 수 있다
  • 중간 인증서 누락이 왜 "브라우저에서는 되는데" 상황을 만드는지 설명할 수 있다
  • 패킷 캡처를 다룰 때의 원칙 여섯 가지를 말할 수 있다
  • QA가 패킷 분석에서 목표로 삼을 지점(범위를 좁혀 넘기기)을 설명할 수 있다

흔한 실수

  • 캡처 필터를 너무 좁게 건다. 안 잡힌 패킷은 영원히 없다. 캡처는 넓게, 분석에서 좁힌다.
  • -w 없이 캡처한다. 화면에 흘러가는 것으로는 나중에 분석할 수 없다.
  • 순환 저장 옵션 없이 장시간 캡처한다. 디스크가 가득 차고, 그것 자체가 장애가 된다.
  • 캡처 필터와 디스플레이 필터 문법을 섞어 쓴다. tcp.port == 443은 tcpdump에서 동작하지 않는다.
  • 패킷을 전부 이해하려 한다. RST·재전송·TLS Alert 세 가지만 봐도 대부분 좁혀진다.
  • 연결 실패의 두 유형을 구분하지 않는다. RST와 무응답은 원인도 담당 팀도 다르다.
  • "느리다"를 하나로 본다. 재전송으로 인한 지연과 서버 처리 지연은 다른 문제다.
  • pcap 파일을 이슈에 그대로 첨부한다. 타 사용자 세션까지 들어 있을 수 있다.
  • 운영 서버에서 승인 없이 캡처한다. 성능 영향과 개인정보 처리 문제가 있다.
  • 분석 후 캡처 파일을 지우지 않는다. 남겨두면 잊고, 잊으면 유출 경로가 된다.
  • 원인 규명까지 하려 한다. 범위를 좁혀 담당 팀에 넘기는 것이 QA의 목표다.

참고 자료

낯선 말 풀이

이 레슨에 나온 약어입니다. 본문에서도 처음 나올 때 점선으로 표시해 두었습니다 (제목과 링크 글자는 그대로 둡니다).

API — 응용 프로그램 인터페이스
프로그램끼리 주고받는 창구. 사람이 화면 버튼을 누르는 대신, 프로그램이 정해진 주소로 요청을 보내 답을 받는다.
HTTP — 하이퍼텍스트 전송 규약
웹에서 요청과 응답을 주고받는 약속. "무엇을 달라"고 보내면 "여기 있다" 또는 "그런 건 없다"가 돌아온다.
DB — 데이터베이스
데이터를 넣어 두고 꺼내 쓰는 저장소. 보통 표 여러 개가 서로 연결된 형태다.
GUI — 그래픽 사용자 인터페이스
글자만 있는 화면이 아니라 그림·버튼·창으로 조작하는 화면. 보통 말하는 "화면"이 이것이다.
DNS — 도메인 이름 체계
사람이 읽는 주소를 컴퓨터가 쓰는 번호로 바꿔 주는 전화번호부.
QA — 품질보증
만든 것이 쓸 만한지 확인하고, 애초에 덜 망가지게 만드는 방법을 정하는 일. "테스트"는 그 일의 일부다.
TLS — 전송 계층 보안
통신을 암호로 감싸는 기술 그 자체. 웹에서 쓰면 주소가 https로 시작한다.
TCP — 전송 제어 규약
데이터를 빠뜨리지 않고 순서대로 보내는 약속. 웹도 이 위에서 돌아간다.
IP — 아이피 주소
인터넷에 연결된 기기마다 붙는 번호.
HTTPS — 암호화된 웹 전송
웹 통신을 암호로 감싼 것. 중간에서 누가 들여다봐도 내용을 못 읽는다.

용어집 전체 보기

이 레슨의 실습

실습은 별도 저장소에서 진행합니다. 새 탭으로 열립니다.