📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 29편
이전 글: 28. MTU와 IP 단편화 — 큰 패킷이 쪼개질 때 · 다음 글: 30. UDP Datagram
TCP Segment는 전송 계층(Transport Layer)에서 TCP가 만드는 데이터 단위입니다. 애플리케이션이 넘겨준 바이트 흐름(Byte Stream)을 적당한 크기로 잘라 앞에 TCP 헤더를 붙인 것이 Segment이며, 이 Segment가 다시 IP 패킷의 데이터 부분에 실려 전달됩니다. PDU 이름 체계(Frame · Packet · Segment)는 26. PDU란 무엇인가에서 다뤘습니다.
TCP Segment = TCP 헤더(20~60바이트) + TCP 페이로드(0바이트 이상)
이 글은 "Segment라는 단위"에 집중합니다. 헤더 각 필드의 의미는 40. TCP와 UDP 헤더 비교 — 신뢰성과 속도의 차이, 시퀀스 번호로 순서를 맞추는 원리는 46. 시퀀스 번호·ACK·윈도우 — TCP가 데이터를 빠짐없이 전달하는 방법에서 다룹니다.
| 용어 | 뜻 | 관계 |
|---|---|---|
| Byte Stream | 애플리케이션이 보내는 연속된 바이트 흐름 | TCP 입장에서는 메시지 경계가 없음 |
| Segment | 헤더 + 잘라낸 바이트 일부 | TCP가 만드는 전송 단위 |
| MSS (Maximum Segment Size) | Segment 한 개에 담을 수 있는 페이로드 최대 크기 | 헤더 크기는 포함하지 않음 |
| MTU | 링크 한 번에 보낼 수 있는 IP 패킷 최대 크기 | MSS는 보통 MTU에서 IP·TCP 헤더를 뺀 값 |
애플리케이션이 send()로 데이터를 넘기면 커널의 TCP는 이를 송신 버퍼에 쌓아 두었다가, 상대가 알려준 MSS와 윈도우 크기를 넘지 않도록 잘라 Segment를 만듭니다.
[애플리케이션] 4,000바이트 전송 요청
│
↓ (TCP 송신 버퍼에 저장)
[TCP] MSS 1460 기준으로 분할
│
├→ Segment 1: TCP 헤더 + 1,460바이트 (seq = N)
├→ Segment 2: TCP 헤더 + 1,460바이트 (seq = N+1460)
└→ Segment 3: TCP 헤더 + 1,080바이트 (seq = N+2920)
│
↓ (각 Segment가 IP 패킷 하나에 실림)
[IP] IP 헤더 20바이트 + Segment → 1,500바이트 이하 → 단편화 불필요
│
↓
[수신 측 TCP] seq 순서대로 이어 붙여 4,000바이트 스트림으로 복원
핵심은 두 가지입니다.
MSS는 SYN · SYN/ACK의 옵션으로 교환됩니다. 이더넷 + IPv4에서는 1500 − 20(IP) − 20(TCP) = 1460, IPv6는 1440이 흔하고, VPN·PPPoE 구간에서는 더 작아집니다.
| 특징 | 설명 | 분석 시 의미 |
|---|---|---|
| 페이로드 0바이트 가능 | SYN, 순수 ACK, FIN, RST는 데이터 없이 헤더만 있는 Segment인 경우가 많음 | 패킷 수는 많아도 실제 데이터는 적을 수 있음 |
| 길이 필드가 없음 | TCP 헤더에는 전체 길이 필드가 없음 | 페이로드 길이 = IP Total Length − IP 헤더 길이 − TCP 헤더 길이(Data Offset × 4) |
| 시퀀스 번호로 위치 표시 | 각 Segment는 "스트림의 몇 번째 바이트부터인지"를 seq로 표시 | 순서가 뒤바뀌어 도착해도 수신 측이 재정렬 |
| 재전송 단위 | 손실되면 해당 바이트 범위를 다시 보냄 | 같은 seq의 Segment가 반복되면 재전송 |
| 오프로딩 영향 | NIC가 분할을 대신하는 TSO/GSO, 수신 시 합치는 GRO/LRO | 송신 호스트나 수신 호스트에서 캡처하면 MSS보다 큰 "Segment"가 보일 수 있음 |
호스트 캡처는 커널이 NIC로 넘기기 전의 데이터를 보므로, 오프로딩 환경에서는 수만 바이트짜리 Segment가 보이기도 합니다. 이를 "비정상적으로 큰 패킷"으로 오판하지 않도록 캡처 위치를 먼저 확인합니다.
| 캡처 위치 | Segment 크기 관찰 | 비고 |
|---|---|---|
| 송신 호스트 자체 | MSS보다 클 수 있음 (TSO/GSO) | ethtool -k <인터페이스>로 오프로딩 설정 확인 가능 |
| 수신 호스트 자체 | 여러 Segment가 합쳐져 보일 수 있음 (GRO/LRO) | 동일 |
| 중간 선로 (미러 포트, TAP) | 실제 전송된 크기 | 네트워크 분석 기준으로 적합 |
실습 예시 — 본인 소유 VM 두 대(192.168.10.10 클라이언트, 192.168.10.20 서버)에서 Segment 크기를 확인하는 방법입니다. 인터페이스 이름 ens33은 예시입니다.
# 도구 설치
# Rocky Linux
sudo dnf install -y tcpdump ethtool
# Ubuntu
sudo apt install -y tcpdump ethtool
# [서버] 8080 포트로 오가는 TCP를 캡처 (페이로드 길이 표시)
sudo tcpdump -nn -i ens33 'tcp port 8080'
# 오프로딩 설정 확인 (tcp-segmentation-offload, generic-receive-offload 등)
ethtool -k ens33 | grep -E 'segmentation|receive-offload'
tcpdump 출력 형식 예시(값은 환경마다 다름):
IP 192.168.10.10.51000 > 192.168.10.20.8080: Flags [S], seq 1000, win 64240, options [mss 1460,...], length 0
IP 192.168.10.20.8080 > 192.168.10.10.51000: Flags [S.], seq 5000, ack 1001, win 65160, options [mss 1460,...], length 0
IP 192.168.10.20.8080 > 192.168.10.10.51000: Flags [.], seq 1:1461, ack 120, win 509, length 1460
IP 192.168.10.20.8080 > 192.168.10.10.51000: Flags [P.], seq 1461:2921, ack 120, win 509, length 1460
| 출력 요소 | 읽는 법 |
|---|---|
options [mss 1460,...] | Handshake에서 알려준 MSS |
length 0 | 페이로드가 없는 Segment (헤더만) |
seq 1:1461 | 상대 시퀀스 기준 1번부터 1460번 바이트까지 담은 Segment |
length 1460 | 이 Segment의 페이로드 크기. MSS와 같으면 "꽉 찬" Segment |
Wireshark에서는 tcp.len(페이로드 길이), tcp.hdr_len(헤더 길이) 필드로 같은 내용을 볼 수 있으며, 필드 단위 해석은 03. Wireshark 패킷 분석 영역 119. TCP 헤더와 Flag 분석 — 포트·시퀀스·Flag·옵션 필드 읽는 법에서 다룹니다.
Segment 경계가 애플리케이션 메시지와 무관하다는 사실은 탐지 측면에서 중요합니다.
| 흔적 위치 | 확인할 수 있는 것 |
|---|---|
| 패킷 캡처(PCAP) | Segment별 seq, 길이, 플래그, 재전송 여부 |
| IDS/IPS | 재조립된 스트림 기준 시그니처 매칭, 스트림 이상 이벤트(중첩, 재조립 실패 등) |
| 방화벽·세션 로그 | Segment 단위가 아니라 세션 단위의 패킷 수·바이트 수 |
관제자가 확인할 질문
오탐 주의: 호스트 캡처의 대형 Segment(오프로딩), 대화형 프로토콜의 작은 Segment, 네트워크 품질 저하로 인한 재전송은 정상 범주입니다. IDS의 스트림 관련 이벤트는 캡처 누락(센서 과부하, 비대칭 경로)으로도 발생하므로 센서 상태를 함께 확인합니다. IDS Alert 분석 방법은 06. 방화벽 · IDS 기초 영역 283. IDS Alert에서 다룹니다.