📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 127편
이전 글: 126. FIN Packet 분석 · 다음 글: 128. TCP Flag 분석
RST는 연결을 즉시 중단하거나 연결 요청을 거부하는 신호입니다. RST가 생기는 이유(닫힌 포트, 강제 종료, 방화벽 reject 등)와 RST가 받아들여지는 조건은 45. TCP 연결 종료 — FIN과 RST의 차이에서 다뤘습니다. 이 글은 패킷 안의 값으로 "어떤 상황의 RST인지", "누가 보낸 RST인지"를 판별하는 방법에 집중합니다.
| 확인 항목 | Wireshark 필드 | 분석 포인트 |
|---|---|---|
| Flag 조합 | tcp.flags | 0x004 (RST) / 0x014 (RST, ACK) |
| Expert Info | tcp.connection.rst | "Connection reset (RST)", Warning 등급 |
| seq / ack 원래 값 | tcp.seq_raw, tcp.ack_raw | 어떤 패킷에 대한 응답인지 역추적 |
| 데이터 | tcp.len | 대부분 0 (일부 스택은 진단 문자열을 싣기도 함) |
| Window | tcp.window_size_value | 0인 경우가 많음 (구현에 따라 다름) |
| TTL | ip.ttl | 같은 방향 다른 패킷의 TTL과 비교 |
| IP ID | ip.id | 같은 호스트의 앞뒤 패킷과 이어지는지 |
| 위치 | 스트림 내 순서 | SYN 직후 / 데이터 도중 / FIN 이후 |
RFC 793 규칙에 따라 RST의 seq·ack는 RST를 유발한 패킷에서 계산됩니다. 이 관계로 원인 패킷을 찾습니다.
[경우 1] 유발 패킷에 ACK 비트가 없음 (예: 닫힌 포트로 온 SYN)
SYN seq_raw = x
↓
RST/ACK (0x014) seq_raw = 0, ack_raw = x + 1 ← SYN을 확인하며 거부
[경우 2] 유발 패킷에 ACK 비트가 있음 (예: 연결이 없는데 온 데이터·ACK)
ACK ack_raw = z
↓
RST (0x004) seq_raw = z, ACK 비트 없음 ← 상대가 기대한 번호로 리셋
[경우 3] 성립된 연결의 강제 중단 (애플리케이션 abort, 장비 차단)
… 데이터 교환 중 …
↓
RST 또는 RST/ACK seq = 현재 보낼 차례의 번호 ← 이후 양쪽 모두 패킷 없음
수신 측은 seq가 기대 값과 정확히 같을 때만 RST를 즉시 받아들이고, 윈도우 안이지만 정확하지 않으면 확인용 ACK(Challenge ACK, RFC 5961)를 보냅니다. RST 직후 상대가 ACK를 보냈다면 이 동작일 수 있습니다.
RST 위치별 해석
| 스트림 안 위치 | 흔한 원인 | 판단 포인트 |
|---|---|---|
| SYN 직후 RST/ACK | 포트 닫힘, 방화벽 reject | 대상 호스트 TTL과 같은가 |
| SYN/ACK 직후 클라이언트 RST | SYN 스캔, 클라이언트 포기 | 같은 출발지의 다른 포트 |
| 데이터 교환 도중 | 애플리케이션 abort, IPS 차단 | 직전 페이로드 내용, RST TTL |
| FIN 교환 이후 | 종료 뒤 늦게 도착한 데이터 거부 | 대부분 정상 |
| 스트림에 RST만 | 캡처 전 연결, 스캔 응답 | 캡처 시작 시각 |
당사자 RST와 주입된 RST 비교 (일반적 경향)
| 항목 | 통신 당사자가 보낸 RST | 중간 장비가 주입한 RST |
|---|---|---|
| TTL | 같은 방향 다른 패킷과 같음 | 다른 경우가 많음 (장비 위치·초기값 차이) |
| IP ID | 앞뒤 패킷과 이어지는 흐름 | 흐름과 무관한 값 |
| 개수 | 대개 1개 | 여러 seq로 여러 개 보내는 경우 있음 |
| 이후 패킷 | 없음 | 원래 서버의 응답이 뒤늦게 도착하기도 함 |
실습 예시 — 본인 VM에서 닫힌 포트 접속(경우 1)의 RST를 추출하고, 스트림별 TTL을 비교합니다. 명령과 출력은 예시(값은 환경마다 다름)입니다.
sudo tshark -i ens33 -f "tcp and host 192.168.10.30" -w /tmp/rst.pcapng &
timeout 3 bash -c '</dev/tcp/192.168.10.30/8081' # 서비스가 없는 포트
curl -s -o /dev/null http://192.168.10.30/
sudo pkill -INT tshark
# RST 패킷의 원래 seq/ack와 TTL
tshark -r /tmp/rst.pcapng -Y 'tcp.flags.reset == 1' -T fields -E header=y \
-e frame.number -e tcp.stream -e ip.src -e ip.ttl -e ip.id -e tcp.flags.str \
-e tcp.seq_raw -e tcp.ack_raw -e tcp.window_size_value
# RST가 있는 스트림에서 방향별 TTL 분포 (다른 값이 섞이면 주입 의심)
for s in $(tshark -r /tmp/rst.pcapng -Y 'tcp.flags.reset == 1' -T fields -e tcp.stream | sort -u); do
echo "stream $s"; tshark -r /tmp/rst.pcapng -Y "tcp.stream == $s" -T fields -e ip.src -e ip.ttl | sort | uniq -c
done
형식 예시입니다.
frame stream ip.src ttl ip.id flags.str seq_raw ack_raw win
2 0 192.168.10.30 64 0x0000 ·······A·R·· 0 2210400001 0
| 확인 포인트 | 읽는 법 |
|---|---|
0x014(A·R), seq_raw 0 | 경우 1: ACK 없는 SYN에 대한 거부 |
| ack_raw = SYN seq_raw + 1 | 이 SYN에 대한 응답이 맞음 |
| TTL이 같은 서버의 다른 패킷과 동일 | 서버 커널이 직접 보낸 RST |
Linux는 DF가 설정된 일부 패킷에서 IP ID를 0으로 보내기도 하므로, IP ID 비교는 OS 특성을 먼저 확인한 뒤 참고 자료로만 씁니다.
📷 [실습 화면 삽입 위치] [RST, ACK] 패킷 Details에서 Flags의 Reset 비트, Sequence/Acknowledgment Number(raw), Expert Info Warning이 보이는 화면
📷 [실습 화면 삽입 위치] Analyze → Expert Information의 Warning 그룹에서 "Connection reset (RST)" 항목을 펼쳐 해당 프레임 목록이 보이는 화면
| 관찰 | 가능한 해석 | 확인할 것 |
|---|---|---|
| 한 출발지의 SYN에 여러 포트가 RST/ACK | 포트 스캔 결과 (닫힌 포트) | 소수 포트의 SYN/ACK 응답 (142. Port Scan Packet 분석) |
| 특정 요청 직후 TTL이 다른 RST | IPS·보안 장비의 세션 차단 | IPS 차단 로그와 시각 대조 |
| 성립된 연결에 seq가 조금씩 다른 RST 여러 개 | 외부의 RST 주입 시도 가능성 | Challenge ACK, 출발지 TTL |
| 연결 없는 우리 IP로 RST 다수 수신 | 우리 IP를 위조한 공격의 Backscatter | 원래 요청이 있었는지 |
| 흔적 위치 | 확인할 수 있는 것 |
|---|---|
| 패킷 캡처 | RST 종류, 원인 패킷, TTL·IP ID |
| 방화벽 로그 | reject 정책으로 보낸 RST, 세션 종료 사유 |
| IDS/IPS | 차단 동작(reset, reject 등 장비별 명칭)과 시그니처 |
| 서버 | nstat -az TcpOutRsts 등 RST 송신 카운터 |
관제자가 확인할 질문
오탐 주의: 브라우저·로드밸런서·앱 서버는 정상 동작 중에도 RST로 연결을 정리합니다. Expert Info에서 RST가 Warning으로 표시된다고 해서 이상이라는 뜻은 아니며, 위치와 반복 패턴으로 판단합니다.