요약

  • TCP는 SYN과 FIN에 각각 시퀀스 공간에서 한 자리씩을 암묵적으로 부여하여, 이 제어 이벤트가 두 번 처리되지 않으면서도 확인 응답과 재전송이 가능하도록 한다.
  • SYN은 해당 세그먼트의 첫 데이터 옥텟 앞에 위치하고, FIN은 마지막 데이터 옥텟 뒤에 위치한다.
  • 차지된 이 자리들은 프로토콜 장부 기록일 뿐 애플리케이션 바이트가 아니며, ACK, PSH, RST 같은 다른 플래그에는 동일한 한 자리 처리가 적용되지 않는다.
  • 각 방향마다 독립적인 시퀀스 공간이 있으므로, FIN은 자신의 송신자 스트림 방향만을 종료하며 그 방향에서만 하나의 번호를 소모한다.

이벤트를 위한 시퀀스 번호

TCP의 신뢰성 서비스는 단순해 보이는 도구에서 시작한다. 옥텟에 번호를 붙이고, 다음에 기대하는 번호를 확인 응답하며, 아직 확인되지 않은 부분을 재전송한다. 그러나 연결의 열기와 닫기는 더 어려운 문제를 만든다. SYN과 FIN은 페이로드가 아니라 제어 이벤트이지만, 어느 하나가 손실되거나 중복되면 연결의 의미가 달라질 수 있다.

RFC 793은 번호 매기기 체계를 선별된 제어 정보까지 확장함으로써 이 문제를 해결했다. 그 근거는 명시적이다. 순서가 매겨진 제어 정보는 혼란 없이 재전송되고 확인 응답될 수 있으므로, 단 하나의 사본만이 처리된다. 현재 표준인 RFC 9293도 이 메커니즘과 그 이유를 모두 유지하고 있다.

그 결과 SYN이나 FIN이 옥텟이 되는 것은 아니다. 플래그는 세그먼트의 데이터 공간 밖, TCP 헤더에 그대로 남는다. TCP는 도착 순서를 정하고, 확인 응답을 진행하며, 재전송 큐 항목을 정리하는 산술 안에서 이 플래그를 위한 논리적 자리 하나를 예약할 뿐이다.

SYN은 바이트 앞에 온다

일반적인 데이터 세그먼트에서 시퀀스 번호 필드는 첫 데이터 옥텟을 가리킨다. SYN은 그 예외다. SYN이 설정되면 이 필드는 초기 시퀀스 번호(ISN)를 담고, 첫 데이터 옥텟은ISN+1로 번호가 매겨진다.

이 순서는 SYN이 애플리케이션 데이터를 함께 실어 보내는 경우(TCP가 허용한다)에도 중요하다. 제어 이벤트가 첫 자리를 차지하고 데이터가 그 뒤를 따른다. SYN을 확인 응답하는 수신자는 첨부된 데이터를 세기 전에 먼저 다음 기대 경계를 하나 진행시킨다. 재전송된 SYN은 두 번째 열기 이벤트를 알리는 대신 같은 자리를 재사용한다.

이 글에서는 ISN이 어떻게 선택되는지, 그리고 경로 밖 공격자가 예측하기 어려워야 하는 이유는 다루지 않는다. 그것은 별개의 문제다. 여기서 중요한 점은 선택된 ISN 바로 다음에 무엇이 오는가이다. SYN 자체가 신뢰 가능한 순서 처리를 받아야 하기 때문에 시퀀스 공간이 하나 진행된다.

FIN은 바이트 뒤에 온다

FIN은 반대쪽 끝을 사용한다. TCP는 FIN이 자신을 운반하는 세그먼트의 마지막 실제 데이터 옥텟 뒤에서 발생한다고 본다. 어떤 세그먼트가 시퀀스 번호 S에서 시작하고 N개의 애플리케이션 옥텟을 담은 채 FIN을 함께 운반한다면, 그 논리적 시퀀스 길이는 N+1이다. FIN은 N개의 바이트 뒤 자리를 차지한다.

이 배치 덕분에 닫기 이벤트가 같은 방향의 데이터를 추월하지 않는다. 수신자는 하나의 누적 경계를 통해 바이트를 지나 FIN까지 확인 응답할 수 있다. FIN을 재전송해야 하는 경우에도 그 반복 사본은 동일한 시퀀스 자리를 가리키며, 또 다른 스트림의 끝을 만들지 않는다.

FIN은 송신자가 더 이상 보낼 데이터가 없다는 뜻이다. 그것만으로 역방향이 닫히지 않으며, 역방향의 시퀀스 공간과 닫기 이벤트는 반대쪽 끝점에 속한다. 따라서 FIN의 계수는 TCP의 방향별 닫기 의미론을 뒷받침할 뿐, 그것을 하나의 공유 스위치로 통합하지 않는다.

SEG.LEN이 실제로 세는 것

두 표준 모두SEG.LEN을 데이터 옥텟뿐 아니라 SYN과 FIN까지 세도록 정의한다. 마지막으로 차지된 시퀀스 번호의 공식, 수신 창 검사, 재전송 큐 항목이 완전히 확인되었는지 판단하는 규칙은 모두 이 논리적 길이를 사용한다.

따라서 페이로드 길이를 시퀀스 공간 진행량 전체로 취급하면 패킷 캡처가 혼란스러워 보일 수 있다. 데이터가 없는 SYN이나 FIN도 다음 기대 번호를 하나 진행시킨다. N개의 데이터 옥텟과 그 플래그 중 하나를 담은 세그먼트는 N+1만큼 진행시킨다. 만약 SYN과 FIN이 산술에서 함께 고려된다면 각각 자기 자리를 기여할 것이지만, 두 플래그의 평소 역할은 여전히 열기와 닫기다.

논리적 길이와 물리적 페이로드의 구분이 이 설계의 핵심이다. TCP는 애플리케이션 스트림에 가상의 바이트를 넣지 않았다. 신뢰 가능하고 순서가 매겨진 처리가 필요한 두 제어 이벤트를 포함하도록 회계 범위를 넓힌 것이다.

다른 플래그가 가세하지 않는 이유

RFC 9293은 SYN과 FIN만이 이러한 보호를 필요로 하는 제어 정보라고 말한다. ACK는 확인 응답 필드가 유효함을 표시하고, PSH는 푸시 기능을 표현하며, RST는 수락될 때 연결 상태를 삭제한다. 이들 플래그는 단지 설정되었다고 해서SEG.LEN에 하나를 더하지 않는다.

이 비대칭은 시퀀스 공간의 역할을 따른다. SYN은 스트림의 시작 끝을 정하고, FIN은 끝 끝을 정한다. 둘 다 데이터를 기준으로 한 순서 지점을 차지해야 한다. 반면 확인 응답은 수신자의 경계를 보고할 뿐이고, PSH는 경계를 정의하지 않고 진행을 요청하며, RST는 시퀀스 공간을 차지하지 않는다고 명시적으로 기술되어 있다.

그러므로 이 규칙은 “TCP 플래그는 시퀀스 번호를 소모한다”는 구호보다 좁다. 대부분은 그렇지 않다. 정확한 서술은 이렇다. TCP는 열기와 닫기 제어가 스트림의 중복 보호, 순서 지정, 확인 응답 체계를 필요로 하기 때문에 SYN과 FIN을 암묵적으로 번호 매기는 것이다.

출처