분할된 Tcp 패킷 재조립

안녕하세요. 몇 개월 동안 다른 분들의 글만 봐오면서 지식을 쌓고 있다가 한가지 여쭈고자 새로 가입하고 질문글을 올리게 됐습니다.

현재 저는 PacketDotNet과 SharpPcap 라이브러리를 사용하며 pcap 파일을 불러와 패킷을 하나씩 읽으며 데이터의 정합성 등을 확인하는 작업을 하고 있습니다.

제가 궁금한 것은 상위 프로토콜의 메시지 길이가 MTU 혹은 MSS 보다 커서 Tcp의 Segmentation이 발생하여 여러개의 Tcp 패킷으로 쪼개져 수신되었을 때 상위 프로토콜의 메시지, 즉 원본 데이터를 어떻게 재조립할 수 있을까요?
상위 프로토콜에서 메시지의 경계를 구분하는 방법이 정의되어 있다 해도 Tcp 입장에서는 그것이 뭔지도 모르는 단순한 페이로드일 뿐이라 어떤 방법이 있을지 한번 여쭤봅니다.

2 Likes

Tcp 들어오는 bytes를 들어올 때마다 ConcurrentQueue에 넣고, 들어올 때마다 ConcurrentQueue에서 bytes들을 Peek하고 조합하여 메세지 경계를 조사하고, 메시지가 있다면 그 부분만을 Dequeue야 합니다. 이렇게 해야 Tcp 데이터를 온전하게 받을 수 있습니다.

1 Like

Sequence number, Acknowledge number로 확인하셔야 할텐데요.

1 Like

image

TCP 레벨에서 Segment들을 직접 합체하려면 TCP의 동작에 대한 이해가 필요하겠죠. 이는 TCP 헤더에 포함된 정보를 보면 알 수 있을 것입니다. Sequence Number 필드와 Acknowledge Number 필드의 정보로 핑퐁치면서 순차적으로 수신되거나 재전송이 발생할텐데요, 결국 각 Sequence에 해당하는 마지막 마지막에 Segment의 Data를 취하면 될 것 같습니다.

조립 완료된 데이터도 단편화가 발생할 것이므로 이 부분은 상위 프로토콜과 동일한 로직으로 처리하시면 될 것입니다.

Sequence Number 계산 방법

Segment n+1의 Sequence Number는 (Sequence Number of Segment N + Length of Segment N) 으로 계산할 수 있습니다.

참고

TCP Sequence and Acknowledgement Numbers Explained – MadPackets

4 Likes

답변 정말 감사드립니다.
Seq Number와 Ack Number는 Tcp의 특성인 신뢰성과 순서를 보장해주는 역할을 해주고 있는 것으로 알고 있습니다. Seq Number와 Ack Number 만으로는 해당 Tcp 패킷이 segmentation이 발생해 원본 데이터가 쪼개져 여러개의 Tcp 패킷으로 들어온건지, 본래 하나의 원본 데이터를 담고 있는Tcp 패킷인지 알 수 있기에는 한계가 있지 않을까요?

1 Like

답변 정말 감사드립니다.
그렇다면 Segmentation 발생 여부와 상관없이 우선 들어오는대로 큐에 넣고 검사를 한다는 말씀이신가요?

2 Likes

네. Tcp는 데이터가 보낸 순서대로 들어옵니다. 그러나 보낸 데이터가 늘 한 번에 다 가지는 않습니다. 그래서 들어온 데이터를 모으고 보낸 메시지 경계를 조사하는 과정이 필요합니다.

1 Like

이 문제는 TCP 상위 레이어에서 조차도 지금 TCP 레이어에서 올라온 데이터가 하나의 원본 패킷인지 단편화 된 패킷인지 알 수 없습니다.

이러한 한계 때문에 TCP/IP 윗단의 프로토콜에서도 Header에 Premable 또는 Sync Bytes와 Length를 포함하도록 설계하는 것이죠.

2 Likes

그렇군요. 답변 감사합니다:)

2 Likes