📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 129편
이전 글: 128. TCP Flag 분석 · 다음 글: 130. ACK Number 분석
Sequence Number(시퀀스 번호) 는 "이 세그먼트의 첫 데이터 바이트가 전체 바이트 흐름에서 몇 번째인가"를 나타내는 32비트 값입니다. 개념과 재전송의 원리는 01 영역 46. 시퀀스 번호·ACK·윈도우 — TCP가 데이터를 빠짐없이 전달하는 방법에서, 상대값과 절대값의 차이는 119. TCP 헤더와 Flag 분석 — 포트·시퀀스·Flag·옵션 필드 읽는 법에서 다뤘습니다.
이 글은 Wireshark에서 시퀀스 번호로 ① 흐름이 빠짐없이 이어지는가, ② 연결의 시작값(ISN)이 자연스러운가, ③ 끼어든 패킷이 창 안에 있는가를 확인하는 방법에 집중합니다.
| 필드 | 의미 | 분석에서 쓰는 곳 |
|---|---|---|
tcp.seq | 상대 시퀀스 번호(ISN을 0으로 본 값) | 연결 내 위치 파악 |
tcp.seq_raw | 헤더에 실제로 적힌 32비트 값 | ISN 비교, 다른 도구 로그와 대조 |
tcp.len | 이 세그먼트의 데이터 길이 | 다음 번호 계산 |
tcp.nxtseq | Wireshark가 계산한 "다음에 와야 할 번호" | 연속성 검증 |
tcp.analysis.* | 시퀀스 흐름에서 찾아낸 이상 표시 | 누락·재전송·순서 문제 선별 |
한 방향의 시퀀스 번호는 보낸 데이터 바이트 수만큼 늘어납니다. SYN과 FIN은 데이터가 없어도 번호를 1씩 소비합니다.
(클라이언트 → 서버 방향, 상대값)
SYN seq=0 len=0 → nxtseq=1 (SYN이 1 소비)
ACK seq=1 len=0 → 번호 변화 없음
PSH/ACK seq=1 len=300 → nxtseq=301
PSH/ACK seq=301 len=500 → nxtseq=801
FIN/ACK seq=801 len=0 → nxtseq=802 (FIN이 1 소비)
↓
검증 규칙: 다음 세그먼트의 seq == 직전 세그먼트의 nxtseq ?
├─ 같음 → 정상 연속
├─ 더 큼 → 중간 구간 누락 (Previous segment not captured)
└─ 더 작음 → 이미 보낸 구간 재전송 또는 순서 뒤바뀜
받는 쪽은 도착한 세그먼트의 번호가 수신 창(Window) 범위 안에 있을 때만 받아들입니다. 특히 RST는 RFC 5961 이후 번호가 정확히 기대값(RCV.NXT)일 때만 즉시 연결을 끊고, 창 안이지만 정확하지 않으면 확인용 ACK(Challenge ACK)를 보내도록 권고됩니다. 그래서 끼어든 RST를 분석할 때는 "그 시점 상대방이 기대하던 번호와 얼마나 떨어져 있는가"가 핵심 단서입니다.
시퀀스 흐름의 이상이 Wireshark에서 표시되는 방식입니다.
| 시퀀스 모양 | Wireshark 표시 (필터) | 먼저 떠올릴 원인 |
|---|---|---|
| seq가 직전 nxtseq보다 큼 | Previous segment not captured (tcp.analysis.lost_segment) | 캡처 누락(센서 과부하, SPAN 손실) |
| 이미 본 seq를 다시 보냄 | Retransmission (tcp.analysis.retransmission) | 손실 후 재전송 (131. TCP Retransmission) |
| 더 작은 seq가 짧은 간격으로 뒤늦게 도착 | Out-Of-Order (tcp.analysis.out_of_order) | 다중 경로, 캡처 지점 특성 |
| seq = nxtseq − 1, 데이터 0~1바이트 | Keep-Alive (tcp.analysis.keep_alive) | 유휴 연결 유지 신호(정상) |
| 같은 방향에서 이전 연결과 같은 포트 쌍으로 새 SYN | Reused Ports (tcp.analysis.reused_ports) | 포트 재사용, 고정 출발지 포트 도구 |
ISN(Initial Sequence Number) 도 확인 대상입니다. 현대 운영체제는 RFC 6528 방식으로 연결마다 예측하기 어려운 ISN을 만듭니다.
ISN 관찰 (tcp.seq_raw, SYN만) | 해석 |
|---|---|
| 연결마다 넓게 흩어짐 | 일반 OS 스택의 정상 모습 |
| 여러 SYN이 같은 값이거나 단순 증가 | 패킷 생성 도구·특수 장비 가능성 → 123. SYN Packet 분석의 다른 필드와 함께 확인 |
| SYN/ACK의 ISN이 장비마다 규칙적 | 중간 장비(SYN 프록시·로드밸런서)가 대신 응답했을 가능성 |
분석 방법 예시 — 이미 확보한 캡처 파일에서 연결 하나의 한 방향 시퀀스 흐름을 표로 뽑아 연속성을 확인합니다. 명령과 출력은 예시(값은 환경마다 다름)입니다.
# 스트림 3의 서버 → 클라이언트 방향 흐름
tshark -r sample.pcapng -Y 'tcp.stream eq 3 && ip.src == 192.168.10.20' \
-T fields -e frame.number -e tcp.seq -e tcp.len -e tcp.nxtseq \
-E header=y
# 캡처 전체에서 시퀀스 이상 표시가 붙은 패킷 수
for f in lost_segment retransmission out_of_order keep_alive; do
printf '%-16s %s\n' $f "$(tshark -r sample.pcapng -Y "tcp.analysis.$f" | wc -l)"
done
첫 명령의 출력 형식 예시:
frame.number tcp.seq tcp.len tcp.nxtseq
14 1 1448 1449
15 1449 1448 2897
17 4345 1448 5793
프레임 17의 seq(4345)가 직전 nxtseq(2897)보다 커서 2897~4344 구간이 이 캡처에 없습니다. 이후 해당 구간의 재전송이 보이면 실제 손실, 끝내 보이지 않고 수신 측 ACK가 이 구간을 이미 확인했다면 캡처 누락으로 판단합니다(130. ACK Number 분석).
주입 RST 검토 예시 — RST 하나의 tcp.seq_raw를, 같은 시점 반대 방향 패킷의 tcp.ack_raw(상대가 기대하는 번호)와 비교합니다.
tshark -r sample.pcapng -Y 'tcp.stream eq 7' \
-T fields -e frame.number -e ip.src -e tcp.flags.str -e tcp.seq_raw -e tcp.ack_raw -e ip.ttl
RST의 seq_raw가 기대값과 정확히 같으면 당사자의 정상 RST일 가능성이 높고, 크게 벗어나 있거나 TTL이 같은 연결의 다른 패킷과 다르면 제3자가 끼워 넣은 패킷인지 검토합니다(127. RST Packet 분석).
Wireshark 화면에서는 Edit → Preferences → Protocols → TCP의 Relative sequence numbers 옵션으로 상대값·절대값 표시를 바꿀 수 있고, tcp.seq_raw를 열로 추가하면 두 값을 나란히 볼 수 있습니다.
📷 [실습 화면 삽입 위치] Packet List에
tcp.seq,tcp.len,tcp.nxtseq열을 추가해 한 방향 흐름에서 seq가 이전 nxtseq와 이어지는 모습(또는 "Previous segment not captured" 표시)이 보이는 화면
| 흔적 위치 | 시퀀스 번호로 확인할 수 있는 것 |
|---|---|
| 패킷 캡처 | 연속성, ISN, 주입 의심 패킷의 창 안 여부 |
| IDS/IPS | 스트림 재조립 이벤트(겹침·창 밖 패킷 관련 이벤트, 엔진별 명칭 상이) |
| 방화벽 | 창 밖 패킷을 invalid로 차단한 기록(시퀀스 검사 기능이 있는 경우) |
| 센서 상태 | 드롭 통계 — lost_segment 급증 시 센서 손실 여부 |
관제자가 확인할 질문
오탐 주의: 송신 호스트에서 캡처하면 TSO(세그먼트 오프로드) 때문에 MTU보다 훨씬 큰 tcp.len이 보여 흐름이 어색해 보일 수 있습니다. 또 캡처 시작 전에 열린 연결은 ISN을 알 수 없어 상대값이 큰 수에서 시작합니다.
tcp.seq와 직전 tcp.nxtseq를 비교해 누락·재전송·순서 뒤바뀜을 구분합니다.tcp.seq_raw로 ISN을 비교하면 OS 스택이 아닌 도구·장비가 만든 패킷의 단서를 얻을 수 있습니다.