📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 121편
이전 글: 120. UDP Header 분석 · 다음 글: 122. TCP Connection 종료 분석

1. 개념

3-Way Handshake가 왜 세 단계인지, 서버의 SYN 대기열이 어떻게 동작하는지는 41. TCP 3-Way Handshake — 연결이 성립했다는 증거과 44. SYN, SYN/ACK, ACK에서 다뤘습니다. 이 글은 캡처 파일 안에서 Handshake를 찾아내고, 성립했는지·어디서 실패했는지를 Wireshark 필드로 판별하는 방법에 집중합니다. 개별 패킷(SYN, SYN/ACK, ACK)의 세부 필드는 123. SYN Packet 분석~125. ACK Packet 분석에서 따로 봅니다.

Handshake 분석에 쓰는 Wireshark 도구와 필드입니다.

도구·필드위치알 수 있는 것
tcp.streamTCP 트리 [Stream index]세 패킷이 같은 연결인지
tcp.flags.syn, tcp.flags.ackFlags 트리각 패킷의 역할
tcp.seq_raw, tcp.ack_rawSEQ 번호 원래 값SYN/ACK의 ack가 SYN seq + 1인지
tcp.analysis.initial_rtt[SEQ/ACK analysis] → [iRTT]첫 SYN부터 세 번째 ACK까지 걸린 시간
tcp.completeness[Conversation completeness]연결에서 관찰된 단계의 합 (Wireshark 3.6 이후)
Statistics → Flow Graph메뉴방향과 순서를 화살표로 확인

2. 동작 원리

Wireshark가 Handshake를 인식하는 순서입니다.

패킷 A  SYN (0x002)        client:51000 → server:443   seq_raw = x
   ↓ 같은 4-tuple → tcp.stream = N 부여, 상대 seq 0 기준 설정
패킷 B  SYN/ACK (0x012)    server:443 → client:51000   seq_raw = y, ack_raw = x+1
   ↓ 반대 방향도 상대 seq 0 기준 설정
패킷 C  ACK (0x010)        client → server             seq = 1, ack = 1 (상대값)
   ↓ 세 패킷 확인
iRTT = C 시각 − A 시각  →  이후 패킷의 [SEQ/ACK analysis]에 표시
completeness 비트: SYN(1) + SYN-ACK(2) + ACK(4) = 7 누적
  • Wireshark는 SYN을 봐야 상대 번호의 기준과 Window Scale 배수를 정확히 잡습니다. 캡처가 연결 중간부터 시작되면 iRTT와 completeness도 계산되지 않습니다.
  • iRTT는 두 구간의 합입니다. 캡처 지점이 클라이언트 근처면 A→B 구간이 길고, 서버 근처면 B→C 구간이 깁니다. 이 차이로 센서가 경로의 어느 쪽에 있는지 추정할 수 있습니다.

3. 주요 특징

Handshake 결과 패턴 (같은 tcp.stream 안에서 보이는 패킷)

보이는 패킷판정비고
SYN → SYN/ACK → ACK → 데이터정상 성립iRTT 표시됨
SYN → RST/ACK포트 닫힘 또는 reject127. RST Packet 분석
SYN, SYN(재전송), SYN…응답 없음(drop·경로 문제)tcp.analysis.retransmission이 SYN에 붙음
SYN → SYN/ACK → RST클라이언트가 수립 거부SYN 스캔의 전형(143. SYN Scan Packet 분석)
SYN → SYN/ACK, SYN/ACK(재전송)…세 번째 ACK 미도착위조 출발지, 비대칭 경로
SYN/ACK 또는 ACK부터 시작캡처가 연결 도중 시작판정 보류

Conversation completeness 값 (비트 합산, 예시)

값포함된 단계해석
1SYN응답을 받지 못한 시도
3SYN + SYN-ACK수립 직전에서 멈춤
7SYN + SYN-ACK + ACK성립했지만 데이터·종료 없음
15위 + DATA(8)데이터 교환, 종료 미관찰
31위 + FIN(16)성립부터 정상 종료까지 전부 관찰
+32RST 포함RST가 한 번이라도 관찰됨

값은 Details에 [Conversation completeness: Complete, WITH_DATA (31)]처럼 문자열과 함께 표시됩니다. 세부 표기는 버전마다 조금씩 다르므로 문자열을 함께 확인합니다.


4. 예시

실습 예시 — 본인 소유 VM 두 대(클라이언트 192.168.10.20, 서버 192.168.10.30)에서 열린 포트와 닫힌 포트에 한 번씩 접속합니다. 명령과 출력은 예시(값은 환경마다 다름)입니다.

# 클라이언트: 캡처 시작 (Rocky: dnf install wireshark-cli / Ubuntu: apt install tshark)
sudo tshark -i ens33 -f "tcp and host 192.168.10.30" -w /tmp/hs.pcapng &
curl -s -o /dev/null http://192.168.10.30/              # 열린 포트(80)
timeout 3 bash -c '</dev/tcp/192.168.10.30/8081'         # 닫힌 포트
sudo pkill -INT tshark

# 연결 시도(SYN)와 수락(SYN/ACK)만 보기
tshark -r /tmp/hs.pcapng -Y 'tcp.flags.syn == 1' -T fields -E header=y \
  -e frame.number -e frame.time_relative -e tcp.stream -e ip.src -e tcp.srcport \
  -e tcp.dstport -e tcp.flags.str -e tcp.seq_raw -e tcp.ack_raw

# 연결별 iRTT (Handshake가 끝난 연결만 값이 있음)
tshark -r /tmp/hs.pcapng -Y 'tcp.analysis.initial_rtt' -T fields \
  -e tcp.stream -e tcp.analysis.initial_rtt | sort -u -k1,1n

# 연결별 completeness 최댓값 (-2: 두 번 읽어 누적 값을 반영)
tshark -r /tmp/hs.pcapng -2 -T fields -e tcp.stream -e tcp.completeness \
  | awk '$2 > m[$1] {m[$1] = $2} END {for (s in m) print s, m[s]}' | sort -n

첫 번째 추출 결과의 형식 예시입니다.

frame time      stream ip.src         srcport dstport flags.str     seq_raw     ack_raw
1     0.000000  0      192.168.10.20  51000   80      ··········S·  3055000100  0
2     0.000412  0      192.168.10.30  80      51000   ·······A··S·  1200500000  3055000101
7     0.051230  1      192.168.10.20  51002   8081    ··········S·  2210400000  0
확인 포인트읽는 법
frame 2의 ack_rawframe 1 seq_raw + 1 → 같은 연결의 정상 응답
stream 1에 SYN/ACK 없음8081은 수락되지 않음. 전체 패킷에서 RST/ACK 확인

📷 [실습 화면 삽입 위치] Statistics → Flow Graph에서 "Limit to display filter"와 Flow type "TCP Flows"를 선택해 stream 0(SYN → SYN/ACK → ACK)과 stream 1(SYN → RST/ACK)이 나란히 보이는 화면

📷 [실습 화면 삽입 위치] 세 번째 ACK 이후 패킷의 Details에서 [SEQ/ACK analysis] → [iRTT]와 [Conversation completeness]가 펼쳐진 화면


5. 보안 관점

관찰가능한 해석확인할 것
한 출발지에서 completeness가 1·3이거나 DATA 없이 RST만 더해진 스트림이 다수포트 스캔·접속 실패 반복목적지 포트 분포 (142. Port Scan Packet 분석)
서버로 SYN 급증, 대부분 SYN/ACK 뒤 ACK 없음SYN Flood 가능성출발지 수·TTL 분포
요청 없이 SYN/ACK만 대량 수신우리 IP가 위조 출발지로 쓰인 Backscatter우리 쪽 SYN 존재 여부
Handshake 성립 후 곧바로 RST애플리케이션 거부, IPS 차단RST의 TTL·출발지 (127. RST Packet 분석)

6. SOC 관점

흔적 위치확인할 수 있는 것
패킷 캡처세 패킷 존재 여부, iRTT, completeness
방화벽 세션 로그세션 생성·종료 사유, 패킷 수가 1~2개인 미성립 세션
IDS/IPSSuricata flow 이벤트의 tcp_flags, 스트림 이벤트

관제자가 확인할 질문

  • 알림이 가리키는 연결은 Handshake가 끝났는가(completeness 7 이상)? 끝나지 않았다면 데이터가 오갔을 수 없습니다.
  • 실패한 시도라면 응답이 없었는가(drop), 거부되었는가(RST)?
  • 성립한 연결의 출발지가 평소 이 서비스에 접속하던 대상인가?

오탐 주의: 캡처가 연결 도중에 시작되면 SYN이 없어 "비정상 연결"처럼 보입니다. 첫 패킷의 시각과 캡처 시작 시각을 먼저 비교합니다. 로드밸런서 헬스체크의 짧은 연결도 정상입니다.


7. 핵심 정리

  • Handshake는 같은 tcp.stream 안에서 SYN(0x002) → SYN/ACK(0x012) → ACK(0x010) 순서로 확인합니다.
  • SYN/ACK의 tcp.ack_raw가 SYN의 tcp.seq_raw + 1인지로 같은 연결의 응답인지 검증합니다.
  • tcp.analysis.initial_rtt는 연결 성립 시간이고, 구간 비율로 캡처 지점을 추정할 수 있습니다.
  • tcp.completeness(1·3·7·15·31, RST면 +32)로 연결이 어디까지 진행됐는지 한 번에 분류합니다.
  • 연결 도중 시작한 캡처는 SYN이 없으므로 성립 여부 판정을 보류합니다.
profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글