요약

  • RFC 7413은 재접속 클라이언트가 서버가 발급한 쿠키를 SYN에 담아 애플리케이션 데이터를 보낼 수 있게 하여, 서버가 TCP의 3방향 핸드셰이크가 끝나기 전에 요청을 처리할 수 있도록 했습니다.
  • 이 메커니즘은 최대 한 번의 왕복을 절약할 수 있었지만, SYN 데이터는 리플레이될 수 있었고, 중복된 첫 요청을 감당할 수 없는 애플리케이션은 명시적으로 제외되었습니다.
  • 따라서 Fast Open은 단순한 스위치 켜고 끄기 이상에 의존했습니다. 쿠키 키 운영, 미완료 작업 상한, 경로별 부정적 캐싱, 일반 핸드셰이크 폴백이 모두 설계의 일부였습니다.

첫 패킷은 평소에 TCP만이 답할 수 있는 질문을 던집니다. 이 연결을 시작해도 되는가? TCP Fast Open에서는 그 패킷이 애플리케이션의 첫 요청까지 담을 수 있었습니다. 사용 가능한 쿠키가 있는 경로에서 서버는 세 번째 핸드셰이크 패킷을 기다리지 않고 그 바이트들을 애플리케이션 앞에 놓을 수 있었습니다. 연결이 완전히 확인되기 전에 요청이 도착한 것입니다.

이 변화는 패킷 수에서는 작았지만 의미상으로는 컸습니다. TCP의 3방향 핸드셰이크는 시퀀스 번호를 동기화하고, 상태를 확립하고, 새 연결을 오래된 중복 패킷과 구분하는 데 도움을 줍니다. 2014년 12월에 실험적(Experimental) 사양으로 발표된 RFC 7413은 그 경계가 만드는 결과 중 하나를 의도적으로 완화했습니다. SYN 안의 데이터를 핸드셰이크 중에 소비할 수 있게 한 것입니다. 짧은 교환의 경우, 긴 연결의 안정 상태를 최적화하는 것보다 유용한 작업을 왕복 한 번 앞당기는 편이 더 중요할 수 있었습니다.

Fast Open은 그 첫 비행을 무조건 허용하지 않았습니다. 클라이언트는 먼저 일반 연결로 쿠키를 요청합니다. 서버는 SYN-ACK에 불투명한 메시지 인증 태그를 돌려보내고, 클라이언트는 이를 캐시합니다. 이후 연결에서 클라이언트는 쿠키와 애플리케이션 데이터를 SYN에 넣습니다. 쿠키를 검증한 서버는 SYN과 데이터를 확인 응답하고, 데이터를 애플리케이션에 전달하며, 핸드셰이크가 완료되기 전에 응답 바이트까지 보낼 수 있습니다. 쿠키를 거절한 서버는 조기 데이터를 무시하고 일반 핸드셰이크로 진행합니다.

쿠키는 최근 도달 가능성의 증명이지, 애플리케이션 신원이나 인가 토큰이 아닙니다. RFC 7413은 이를 일반적으로 발신 IP 주소에 묶인 서버 생성 MAC으로 기술합니다. TCP 옵션은 4바이트에서 16바이트의 쿠키를 담을 수 있습니다. 클라이언트는 이를 불투명한 값으로 취급하고, 서버가 생성, 검증, 만료를 통제합니다. 비밀 키를 교체하면 기존 쿠키가 무효화되며, 전환 기간에 임시로 둘 이상의 키를 수용하면 교체 경계를 완화할 수 있습니다. 이는 키 수명과 겹침 기간이 단순한 암호학적 세부사항이 아니라 운영상의 선택임을 의미합니다.

핵심 비용은 리플레이였습니다. 일반 TCP는 오래되거나 중복된 SYN이 자신을 설명하던 상태보다 오래 살아남을 수 있기 때문에, 핸드셰이크가 끝나기 전에는 SYN 데이터를 애플리케이션에 전달하지 않습니다. Fast Open은 첫 애플리케이션 바이트가 가끔 두 번 이상 전달될 수 있음을 수용했습니다. 그래서 RFC는 TFO를 기본으로 활성화해서는 안 되며 서비스 포트별로 요청해야 한다고 규정합니다. 중복된 SYN 데이터를 감당할 수 없는 클라이언트나 서버는 이를 사용해서는 안 됩니다.

이것이 멱등성(idempotency)이 전송 계층 이야기에 속하는 이유입니다. 읽기 성격의 요청은 내구 상태를 바꾸지 않고 반복될 수 있는 경우가 많습니다. 결제, 변경 작업, 보호되지 않은 POST는 한 번 도착이 곧 한 번 실행이라고 안전하게 가정할 수 없습니다. 애플리케이션 수준의 트랜잭션 식별자는 반복을 감지 가능하게 만들 수 있지만, 쿠키 자체는 정확히 한 번(exactly-once) 처리를 보장하지 않습니다. 절약된 왕복은 애플리케이션이 자신이 앞당기는 바이트의 의미를 이해할 때만 얻어집니다.

사전 핸드셰이크 작업은 서버의 노출도도 바꿉니다. 유효한 쿠키는 클라이언트가 핸드셰이크를 완료하기 전에 애플리케이션 처리를 허용합니다. 이는 일반 TCP보다 일찍 CPU, 메모리, 응답 대역폭을 소모할 수 있습니다. 그래서 RFC 7413은 대기 중인 Fast Open 요청 수를 정의하고, 설정된 상한을 초과하면 새 요청에 대해 Fast Open을 비활성화하도록 요구합니다. 폴백은 의도적으로 보수적입니다. 조기 데이터를 버리고, SYN을 확인 응답하고, 평소의 SYN 플러드 방어와 정상 핸드셰이크가 통제권을 되찾게 두는 것입니다.

종단 간 네트워크는 그 메커니즘을 이해하지 못한 채 이 최적화를 거부권으로 막을 수 있습니다. 일부 미들박스는 페이로드나 낯선 옵션을 담은 SYN 패킷을 드롭합니다. RFC 7413은 SYN 타이머가 만료된 클라이언트에게 데이터와 Fast Open 옵션 없이 재전송하라고 지시합니다. 또한 부정적 응답을 캐시하도록 요구하고, 영향을 받은 발신 주소·목적지 주소·포트 경로에서 일시적으로 TFO를 비활성화할 것을 권고합니다. 타임아웃을 반복해서 치르는 고속 경로는 고속이 아닙니다. 실패를 기억하는 것도 이 기능의 일부입니다.

호환되는 경로에서도 최대 효과를 얻으려면 첫 애플리케이션 단위가 사용 가능한 초기 세그먼트에 들어가야 합니다. TCP 옵션 공간, 캐시된 최대 세그먼트 크기, 요청의 크기가 얼마나 앞당길 수 있는지를 제한합니다. 큰 첫 메시지는 여전히 이후 패킷을 기다립니다. 확립된 연결을 재사용하는 것은 여전히 가치가 있습니다. 너무 많은 짧은 연결로 구성된 서비스는 설정 비용이 커지고, 각 연결 개설이 개별적으로는 빨라 보여도 혼잡 피드백을 약화시킬 수 있기 때문입니다.

따라서 이 프로토콜의 역사는 단순한 왕복 절감의 승리가 아닙니다. Fast Open은 애플리케이션의 결정을 전송 계층의 경계 너머로 옮겼습니다. 더 빠른 작업을 얻는 대가로, 서비스는 어떤 요청이 반복될 수 있는지, 쿠키 비밀 키가 어떻게 바뀌는지, 확인되지 않은 작업을 얼마나 받아들일지, 경로가 이 실험을 거부했는지 언제 알아차릴지, 얼마나 빨리 일반 TCP로 돌아갈지를 알아야 했습니다. RFC 7413의 지속적인 기여는 바로 이 거래를 명시적으로 만든 것입니다.

출처