요약
- 지연된 TFTP 확인 응답(ACK)은 양쪽 끝점이 현재 보유한 패킷을 재전송하게 만들어, 한 번의 타임아웃을 지속적인 중복 트래픽으로 바꿀 수 있었다.
- RFC 1123은 DATA 전송 측이 중복 ACK를 무시하도록 요구했고, RFC 1350은 나중에 1992년의 수정을 기록했다. 이 버그가 위협한 것은 전달된 파일의 정확성이 아니라 혼잡을 통한 전송 완료였다.
한 패킷만 기억하는 프로토콜
1981년 6월, Karen Sollins가 Trivial File Transfer Protocol의 두 번째 개정판을 발표했다. “trivial(소박한)”이라는 말은 네트워크 환경이 아니라 인터페이스를 묘사한 것이다. 클라이언트는 파일명과 모드로 읽기 또는 쓰기를 요청할 수 있었다. TFTP는 디렉터리 목록을 제공하지 않았고, 그 명세에는 사용자 인증도 없었다. 매력은 구현을 작게 만들 수 있다는 점이었다. 각 데이터 패킷은 최대 512바이트를 담았고, 수신자는 한 블록을 확인 응답한 뒤에야 전송자가 다음 블록을 보냈다. 따라서 전송자는 재시도를 위해 현재 패킷만 보관하면 되었다. Stop-and-wait 방식은 흐름 제어도 함께 제공했고 데이터 블록 재정렬의 필요를 없앴다.
이런 절충은 큰 프로토콜 스택이 부담이 되는 환경에서 유용했다. 호스트는 완전히 구성된 기계처럼 동작하기 전에 자신의 운영체제를 먼저 받아야 했다. 1989년에 발표된 인터넷 호스트 요구사항은 TFTP의 주요 용도를 로컬 네트워크를 통한 부팅(bootstrapping)으로 기술한다: 이 프로토콜은 EPROM에 들어갈 만큼 작았다. BOOTP가 구성을 제공하고, TFTP가 이어서 이미지를 가져올 수 있었다. 두 프로토콜은 인접한 문제를 해결했지만, 파일 전송 단계는 여전히 타이밍과 확인 응답에 의존했다.
TFTP는 UDP 위에서 동작했으므로 자체적인 신뢰성을 제공했다. 손실된 패킷을 조용히 흡수하는 전송 계층 연결은 없었다. 예상된 응답이 타이머 만료 전에 도착하지 않으면 전송자는 기다리던 패킷을 재전송할 수 있었다. 패킷이 손실되기만 한다면 이것은 단순했다. 문제는 패킷이 손실이 아니라 지연될 때 시작됐다.
오래된 ACK 하나가 새로운 중복을 계속 만드는 방식
호스트 A가 확인 응답 X−1을 받고 DATA X를 보낸다고 하자. 호스트 B는 이를 받고 ACK X로 회신하지만, 이 확인 응답이 지연된다. A의 타이머가 만료되어 A는 DATA X를 재전송한다. B는 이미 X를 받아들였다. B는 반복된 블록을 인식하고 다시 ACK X를 보낸다. 지연된 첫 ACK가 마침내 도착하면 A는 진행해서 DATA X+1을 보낸다. 그다음 두 번째 ACK X가 도착한다. 원래 규칙 아래에서 A는 이 오래된 확인 응답에 응답해 현재 보유한 DATA 패킷, 즉 X+1을 재전송한다.
B는 X+1을 두 번 받고 ACK X+1을 두 번 보낸다. 그 확인 응답 중 하나가 A가 DATA X+2로 진행한 뒤에 도착하면, 남아 있던 오래된 ACK가 A로 하여금 X+2를 반복하게 만들 수 있다. 같은 패턴이 이어서 전송을 따라 앞으로 이동한다. 부실한(stale) 패킷은 오래된 블록을 홀로 재생하는 것이 아니라, 각 끝점의 현재 상태에 기반한 응답을 유발한다. 따라서 중복된 패킷이 상대 측에서 새로운 중복을 유도할 수 있다.
Robert Braden의 RFC 1123은 이것을 “마법사의 제자 증후군(Sorcerer’s Apprentice syndrome)”이라 불렀다. 그 예시는 데이터그램이 손실되어 반복이 끊기지 않는 한 전송의 나머지 부분이 중복으로 전달됨을 보여준다. 문제는 TFTP의 파일 내용이 잘못되는 것이 아니었다. RFC 1123은 완료된 전송은 여전히 정확하다고 말한다. 위험은 반복된 패킷이 전송이 완료되는 대신 타임아웃에 이를 때까지 시간과 용량을 소모한다는 점이었다.
이 구분이 중요한 이유는 “신뢰성(reliable)”이 “지연에 면역”과 같은 뜻이 아니기 때문이다. TFTP의 시퀀스 번호는 확인 응답되는 블록을 식별할 수 있었지만, 오래된 블록에 대한 모든 응답을 무해하게 만들지는 않았다. 이 프로토콜의 대칭적 동작은 DATA 전송자와 ACK 전송자 모두가 중복에 자신의 현재 패킷을 반복하는 방식으로 응답하도록 했다. 각 재시도는 로컬에서는 합리적으로 보였다. 그러나 합쳐지면 하나의 피드백 루프를 형성했다.
혼잡을 먹이로 삼는 지연
1989년 요구사항 문서는 이 실패 메커니즘을 명시적으로 만들었다. 지연된 확인 응답은 타임아웃이 이미 재전송을 일으킨 후에 도착할 수 있다. 반복된 DATA는 또 다른 ACK를 생성한다. 이전 ACK가 전송자가 진행한 뒤에 도착하면 전송자는 새 DATA 블록을 반복할 수 있고, 이는 더 많은 ACK를 낳는다. 패킷 손실이 이 연쇄를 끊지 않으면 이후 블록들이 중복으로 전달될 수 있다.
혼잡은 촉발 원인이자 결과가 될 수 있다. 혼잡한 경로는 패킷이 사이클을 시작할 만큼 오래 지연되게 만든다. 중복 DATA와 ACK는 그 경로를 더 많이 점유해 추가 지연을 더 가능하게 만든다. RFC는 이것이 추가 혼잡과 더 많은 지연 패킷을 낳을 수 있다고 경고한다. 이것은 느린 모든 TFTP 전송이 이 증후군에 들어갔다는 주장이나, 특정 과거 네트워크 장애가 이것으로 인해 발생했다는 주장이 아니다. 이는 호스트 요구사항에 문서화된 프로토콜 수준의 양의 피드백 메커니즘이다.
RFC 1123은 이 문제를 TFTP의 일반적인 타임아웃 정책과도 분리했다. 적응적 타임아웃이 요구되었고, 지수 백오프가 최소한으로 권장되었다. 더 나은 타이머 값은 전송자가 가변적 지연을 견디는 데 도움이 되지만, 오래된 ACK가 또 다른 DATA 패킷을 촉발하게 하는 규칙 자체를 제거하지는 않는다. 수정은 전송자가 중복 확인 응답을 본 뒤 무엇을 하는지를 바꿔야 했다.
새 개정판 이전의 작은 규칙
RFC 1123은 수정을 의무로 만들었다: DATA를 보내는 측은 중복 ACK를 받았을 때 현재의 DATA 패킷을 절대 재전송해서는 안 된다. 이 응답이 억제되면 반복된 ACK가 더 이상 다음 중복 DATA 패킷을 만들지 못하고, 루프는 스스로를 이어갈 수 없다. ACK를 재전송해도 아무 동작을 촉발하지 않게 되면, 수신 측 고유의 재전송 타이머는 제거할 수 있다. RFC 1123은 반복된 확인 응답이 진짜로 잃어버린 하나를 대체할 수 있는 경우에는 남아 있을 수 있다고 말하며, DATA 전송자에게는 여전히 재전송 타이머가 필요하다.
부팅 프로그램 안에 살도록 만들어진 프로토콜에게 이는 유용한 유지보수 결과였다. 전송자가 수정된 규칙을 따른다면 수신자는 타이머 없이 더 단순해질 수 있다. 수정은 패킷 창을 확대하거나, 512바이트 블록을 바꾸거나, UDP를 교체할 것을 요구하지 않았다. 한 패킷만 기억하는 모델을 유지하면서 위험한 피드백 경로를 끊었다.
1992년 7월, RFC 1350이 RFC 783을 대체하고 STD 33이 되었다. 그 사사(acknowledgements)는 Noel Chiappa의 1992년 5월 개정이 마법사의 제자 프로토콜 버그를 수정했다고 말한다. 이 순서는 쉽게 혼동된다: 1989년 호스트 요구사항이 이미 의무적인 구현 동작을 명시했고, 1992년 문서는 개정된 TFTP 명세에 그 수정을 기록했다. 명세 날짜가 늦다는 것이 1989년까지 모든 구현이 깨져 있었다거나, 모든 구현이 1989년에 이미 갱신되어 있었다는 증거는 아니다.
이후 TFTP 확장은 다른 경계를 추구했다. 1998년 blocksize 옵션은 더 큰 블록을 허용했고, 이후 옵션들은 전송 크기와 타임아웃 협상을 추가했다. 2015년 창(window) 옵션은 여러 개의 미완료 블록을 허용했다. 이 변경들은 stop-and-wait가 비효율적인 환경에서 성능을 개선했다. 그러나 이것을 중복-ACK 수정과 혼동해서는 안 된다. 하나는 처리량을 늘렸고, 다른 하나는 오래된 확인 응답이 현재 트래픽을 증폭하지 못하게 했다.
TFTP의 역사는 미니멀한 설계가 패킷 형식 대신 상태 전이에 복잡성을 두곤 한다는 점을 상기시킨다. 원래 프로토콜은 하나의 블록만 활성 상태로 유지함으로써 메모리와 구현 작업을 절약했다. 실패는 지연이 두 끝점의 “현재 패킷”에 대한 인식을 벌어지게 만들 때 드러났다. 수정 역시 똑같이 작았다: 중복 확인 응답이 DATA 전송자에게 지금 보내고 있는 것을 반복하도록 명령하지 못하게 하라. 신뢰성은 재시도에만 의존하지 않았다. 재시도가 언제 유용함을 잃는지 아는 데도 의존했다.
출처
- RFC 783 — The TFTP Protocol (Revision 2), 1981
- RFC 1123 — Requirements for Internet Hosts, 1989, §§4.2.1–4.2.3
- RFC 1350 — The TFTP Protocol (Revision 2), 1992
- RFC 768 — User Datagram Protocol
- RFC 951 — Bootstrap Protocol
- RFC 1542 — BOOTP Clarifications and Extensions
- RFC 2347 — TFTP Option Extension
- RFC 2348 — TFTP Blocksize Option
- RFC 2349 — TFTP Timeout and Transfer Size Options
- RFC 7440 — TFTP Windowsize Option
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





