📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 124편
이전 글: 123. SYN Packet 분석 · 다음 글: 125. ACK Packet 분석
SYN/ACK는 서버가 "요청을 받았고 연결을 받아들이겠다"고 답하는 패킷입니다. Handshake 전체 흐름은 121. TCP 3-Way Handshake 분석, 개념은 44. SYN, SYN/ACK, ACK에서 다뤘습니다. 관제 관점에서 SYN/ACK의 가치는 분명합니다. SYN/ACK가 나갔다는 것은 그 포트에서 서비스가 실제로 대기(LISTEN) 중이고, 방화벽이 그 연결을 통과시켰다는 증거입니다.
| 확인 항목 | Wireshark 필드 | 정상 모습 |
|---|---|---|
| Flag | tcp.flags == 0x012 | SYN + ACK (ECN 수락 시 0x052) |
| 서버 ISN | tcp.seq_raw | 무작위에 가까운 값, 상대값 0 |
| 확인 번호 | tcp.ack_raw | 대응하는 SYN의 tcp.seq_raw + 1 |
| 옵션 | tcp.options.* | 클라이언트가 제안한 옵션 중 서버가 지원하는 것만 |
| MSS | tcp.options.mss_val | 서버 쪽 경로 MSS (양쪽 값이 다를 수 있음) |
| TTL | ip.ttl | 서버 OS 초기값 − 경유 홉 |
| 응답 시간 | frame.time_delta_displayed | SYN과 SYN/ACK만 필터했을 때 두 패킷 간격 |
SYN/ACK를 SYN과 짝지어 검증하는 과정입니다.
SYN client:51030 → server:22 seq_raw = 4100000000
↓ 서버: LISTEN 소켓 확인 → SYN 대기열 등록
SYN/ACK server:22 → client:51030 seq_raw = y, ack_raw = 4100000001
↓ 검증 ① 포트 쌍이 SYN의 역방향인가
↓ 검증 ② ack_raw = SYN seq_raw + 1 인가
↓ 검증 ③ 옵션이 SYN의 제안 범위 안인가 (예: SYN에 WS 없으면 SYN/ACK에도 없음)
ACK 도착 → 연결 성립
ACK 미도착 → 서버가 SYN/ACK 재전송 (Linux net.ipv4.tcp_synack_retries 기본 5)
tcp.seq_raw의 SYN/ACK가 반복되고 tcp.analysis.retransmission이 붙는 모습으로 나타납니다.nstat 의 SyncookiesSent)로 확인합니다.SYN/ACK가 보이는 방식별 해석
| 보이는 모습 | 해석 | 비고 |
|---|---|---|
| SYN 직후 SYN/ACK, 이어서 ACK | 정상 성립 | — |
| SYN/ACK 후 클라이언트가 RST | 클라이언트가 수립 포기 | SYN 스캔, 또는 클라이언트 타임아웃 |
| 같은 SYN/ACK가 1초·2초… 간격으로 반복 | 세 번째 ACK 미도착 | 위조 출발지 SYN, 반환 경로 차단 |
| 우리 쪽 SYN 없이 외부에서 SYN/ACK만 수신 | Backscatter 또는 비대칭 경로 | 캡처 지점이 한 방향만 보는지 확인 |
| 한 서버가 다수 외부 IP로 SYN/ACK 재전송 | SYN Flood 대상 가능성 | SYN 출발지 분포 |
| SYN/ACK의 ack가 SYN seq + 1과 다름 | 다른 연결의 응답, 조작 패킷 | tcp.stream과 4-tuple 재확인 |
옵션 협상 결과 읽기
| SYN 쪽 | SYN/ACK 쪽 | 결과 |
|---|---|---|
| Window Scale 7 | Window Scale 7 | 양방향 스케일 적용 (각자 자기 값) |
| Window Scale 있음 | Window Scale 없음 | 양방향 모두 스케일 미사용 |
| SACK 허용 | SACK 허용 | SACK 블록 사용 가능 |
| Timestamps | Timestamps 없음 | 이후 패킷에 Timestamps 없음 |
| MSS 1460 | MSS 1400 | 각 방향 송신자는 상대가 알린 MSS를 따름 |
실습 예시 — 본인 VM의 SSH 서버(192.168.10.30:22)에 접속해 SYN과 SYN/ACK를 짝지어 봅니다. 명령과 출력은 예시(값은 환경마다 다름)입니다.
sudo tshark -i ens33 -f "tcp port 22 and host 192.168.10.30" -w /tmp/synack.pcapng &
ssh -o BatchMode=yes -o ConnectTimeout=3 user@192.168.10.30 exit 2>/dev/null
sudo pkill -INT tshark
# SYN과 SYN/ACK를 나란히 (두 번째 줄 ack_raw = 첫 줄 seq_raw + 1)
tshark -r /tmp/synack.pcapng -Y 'tcp.flags.syn == 1' -T fields -E header=y \
-e tcp.stream -e ip.src -e ip.ttl -e tcp.flags.str -e tcp.seq_raw -e tcp.ack_raw \
-e tcp.window_size_value -e tcp.options.mss_val -e tcp.options.wscale.shift -e frame.time_relative
# SYN/ACK 재전송만
tshark -r /tmp/synack.pcapng -Y 'tcp.flags == 0x012 && tcp.analysis.retransmission'
형식 예시입니다.
stream ip.src ttl flags.str seq_raw ack_raw win mss ws time
0 192.168.10.20 64 ··········S· 4100000000 0 64240 1460 7 0.000000
0 192.168.10.30 64 ·······A··S· 3301200000 4100000001 65160 1460 7 0.000380
| 확인 포인트 | 읽는 법 |
|---|---|
| ack_raw 4100000001 | SYN seq_raw + 1 → 이 SYN에 대한 응답이 맞음 |
| 서버 TTL 64 | 같은 대역. 외부 서버라면 초기값에서 홉 수만큼 줄어든 값 |
| 응답 간격 0.38ms | 서버 앞 캡처라면 서버 처리 시간, 클라이언트 앞이면 왕복 시간 포함 |
📷 [실습 화면 삽입 위치] SYN/ACK 패킷 Details에서 Acknowledgment Number(raw)와
[This is an ACK to the segment in frame: N], Options가 보이는 화면
| 관찰 | 가능한 해석 | 확인할 것 |
|---|---|---|
| 외부 스캔 SYN에 내부 서버가 SYN/ACK로 응답 | 해당 포트가 외부에 실제로 노출됨 | 노출 정책 (98. 포트·프로토콜 보안 점검 체크리스트) |
| 예상하지 못한 포트에서 SYN/ACK | 허가되지 않은 서비스·백도어 리스너 가능성 | 서버의 ss -tlnp 결과 |
| SYN/ACK TTL이 같은 서버의 평소 값과 다름 | 중간 장비(프록시·IPS)의 대리 응답 | 다른 연결의 TTL |
| 요청 없는 SYN/ACK 대량 수신 | 우리 IP를 위조한 공격의 Backscatter | 출발지·포트 분포 |
| 서버의 SYN/ACK 재전송 급증 | SYN Flood, 반환 경로 문제 | 서버 SYN-RECV 수 |
| 흔적 위치 | 확인할 수 있는 것 |
|---|---|
| 패킷 캡처 | 응답 여부, ack 검증, 서버 TTL·옵션 |
| 방화벽 로그 | 세션 허용 후 서버 응답 패킷 수 (1 이상이면 응답 존재) |
| IDS/IPS | 스캔 이벤트의 "응답 있음" 여부로 노출 판단 |
| 서버 | LISTEN 포트 목록, SYN 대기열 상태 |
관제자가 확인할 질문
오탐 주의: 캡처 지점이 한 방향만 보는 구성(비대칭 라우팅, 단방향 TAP)에서는 SYN 없는 SYN/ACK가 정상적으로 보입니다. 센서 구성부터 확인합니다.
tcp.flags == 0x012이며, tcp.ack_raw가 SYN의 tcp.seq_raw + 1이어야 같은 연결의 응답입니다.