요약

  • 원래의 TFTP 문구는 양쪽이 이전 중복 패킷을 수신한 후 현재 패킷을 재전송할 수 있도록 허용했습니다. 따라서 지연된 ACK 하나만으로 이후의 모든 DATA와 ACK 패킷이 쌍으로 나타나고, 그 지연을 초래한 혼잡을 심화시킬 수 있었습니다.
  • RFC 1123은 DATA 발신자가 중복 ACK가 도착했다는 이유만으로 현재 DATA를 재전송하는 것을 금지함으로써 이 루프를 끊었습니다. Karen Sollins가 집필한 RFC 1350은 1992년 수정을 Noel Chiappa에게 명시적으로 인정하면서 수정된 프로토콜을 그대로 이어 갔습니다.

바이트 단위로 완전히 올바른 전송을 상상해 보십시오. 블록 번호는 순서대로 도착하고, 최종 파일은 원본과 일치하며, 아무것도 손상되지 않았습니다. 그런데 어느 순간부터 모든 데이터 패킷이 네트워크를 두 번 건너고 모든 승인도 두 번 돌아옵니다. 이 추가 트래픽은 그것을 촉발한 지연을 더 길게 만들고, 더 많은 늦은 패킷을 낳으며, 끝내 정상적인 전송조차 시간 초과에 빠지게 할 수 있습니다.

그래서 ‘마법사의 제자 증후군(Sorcerer’s Apprentice syndrome)’은 평범한 패킷 손실 버그보다 더 많은 것을 드러냅니다. 이 결함에는 악의적인 상대방도, 손상된 페이로드도, 불가능한 상태도 필요하지 않았습니다. 양쪽 엔드포인트는 겉보기에는 합리적인 복구 규칙을 따랐습니다. 그러나 이런 국소적 조심이 서로 더해져 스스로 지속되는 전역적 오류를 만들어 낸 것입니다.

Karen Sollins는 1981년에 발표된 RFC 783과 1992년에 발표된 TFTP Revision 2 사양인 RFC 1350 두 문서의 이름이 올라간 저자입니다. 그러나 이 프로토콜 자체는 한 사람의 발명이 아니었습니다. RFC 1350은 TFTP가 원래 Noel Chiappa가 설계했으며 Bob Baldwin과 Dave Clark과 함께 재설계했고 Steve Szymanski의 의견을 받았다고 밝히고, 이후 수정에 더 넓은 참여자 그룹을 명시하며, 특히 1992년 5월 수정에서 마법사의 제자 버그와 다른 문서 문제를 고친 것은 Chiappa였다고 기록합니다.

이 귀속이 중요합니다. 이 이야기에서 Sollins의 위치는 결함 하나를 발견한 홀로 프로그래밍한 사람이 아닙니다. 그것은 시간에 걸쳐 이어지는 프로토콜 저술의 작업입니다. 의도적으로 작게 만든 시스템을 보존하고, 그것이 왜 작은지 설명하며, 구현 경험을 흡수하고, 호환되는 기기들이 서로의 조심을 증폭시키지 못하도록 할 만큼 정밀한 규칙을 발행한 것입니다.

하나의 지연된 승인이면 패턴을 시작하기에 충분했습니다

TFTP는 UDP를 사용하며 자체적인 신뢰성을 갖춥니다. 기본 교환에서 발신자는 하나의 DATA 블록을 보내고 기다립니다. 수신자는 발신자가 다음으로 진행하기 전에 그 블록을 승인합니다. RFC 1123은 이 유효 윈도우를 512옥텟 세그먼트 하나로 기술했습니다. 이 정지-대기 방식은 대역폭-지연 곱이 큰 경로에서는 느리지만 이해하기 쉽고 부트스트랩 프로그램에 넣을 만큼 작습니다.

낡은 결함은 손실이 아니라 타이밍에서 시작됩니다. 엔드포인트 A가 DATA 블록 X를 보냅니다. 엔드포인트 B가 이를 받고 ACK X를 보내지만, 그 승인이 네트워크에서 지연됩니다. A의 타이머가 만료되어 A는 DATA X를 다시 보냅니다. B는 중복을 수신하고 ACK X를 다시 보냅니다.

이제 원래의 ACK가 먼저 A에 도착합니다. A는 정상적으로 진행하여 DATA X+1을 보냅니다. 그다음 두 번째 ACK X가 도착합니다. 잘못된 규칙 아래에서 A는 오래된 중복을 현재 패킷인 DATA X+1을 재전송할 이유로 취급합니다. B는 두 복사본을 모두 승인합니다. 첫 번째 ACK X+1이 A를 DATA X+2로 진행시키고, 두 번째는 DATA X+2를 다시 보내게 만듭니다. 패킷이 패턴을 끊을 적절한 위치에서 손실되지 않는 한, 나머지 전송은 쌍으로 진행됩니다.

파일은 여전히 올바를 수 있습니다. 중복된 블록 번호를 식별할 수 있기 때문입니다. 그러나 운영적으로는 전송이 틀려 있습니다. RFC 1123은 과도한 재전송이 시간 초과로 이어질 수 있다고 경고했고, 적대적인 피드백 메커니즘도 지적했습니다. 지연은 흔히 혼잡으로 인해 발생하는데, 중복 트래픽은 더 많은 혼잡을 만듭니다. 불확실성에서 벗어나기 위한 규칙이 불확실성을 부하로 바꾸어 버린 것입니다.

이 이름은 제자가 물을 나르도록 빗자루에 생명을 불어넣었으나 그 증식을 멈추지 못하는 장면에서 옵니다. 이 은유가 적절한 이유는 어떤 단일 패킷도 치명적이지 않기 때문입니다. 피해는 그 규칙을 정당화했던 상태가 이미 지나간 뒤에도 규칙에 반복적으로 복종하는 데 있습니다.

수정은 복구를 비대칭으로 만들었습니다

RFC 1123은 이 교정을 요구사항으로 만들었습니다. DATA를 보내는 쪽은 중복 ACK를 받았다는 이유만으로 현재 DATA 패킷을 재전송해서는 안 됩니다. 발신자에게는 여전히 재전송 타이머가 필요합니다. 기대한 승인이 결코 도착하지 않는다면, 시간은 여전히 다시 시도할 타당한 이유입니다. 사라지는 것은 오래된 상태에 대한 승인과 현재 상태의 새 전송 사이의 인과 연결입니다.

수신자는 중복 DATA 블록에 또 하나의 ACK로 답할 수 있습니다. 앞선 ACK가 실제로 손실된 경우 이 응답은 유용할 수 있습니다. 다만 반복된 ACK는 발신자에게 무해해야 합니다. 따라서 이 수정은 모든 곳에서 중복을 금지하지 않습니다. 권한을 할당합니다. 미결 DATA를 관장하는 타이머는 복구를 시작할 수 있지만, 오래된 ACK는 새로운 DATA 작업을 만들어 낼 수 없습니다.

이것은 작은 상태 머신 변경이지만 넓은 공학적 교훈을 줍니다. 한 엔드포인트의 멱등성만으로는 충분하지 않습니다. 그 중복 응답이 반대쪽에서 멱등하지 않은 동작을 촉발할 수 있기 때문입니다. 어떤 메시지는 국소적으로 반복하기에 안전하고, 원격에서는 새 명령으로 다루기에 안전하지 않을 수 있습니다. 분산 프로토콜은 이 진술의 양쪽 절반을 모두 필요로 합니다.

RFC 1123은 중복 수정 외에 적응적 타임아웃과 최소한 지수적 백오프를 함께 두었습니다. 이 메커니즘들은 관련되어 있으나 서로 다른 문제를 다룹니다. 더 나은 타이머는 조기 재전송을 줄이고 문제 상황에서 물러서지만, 그것만으로는 지연된 패킷이 중복을 만들어 낸 뒤의 루프를 끊지 못합니다. 상태 전이 역시 함께 수정되어야 합니다.

‘Trivial’은 제약된다는 뜻이지 버려도 된다는 뜻이 아니었습니다

RFC 1350은 TFTP의 이름을 변명 없이 설명합니다. 매우 단순한 파일 전송 프로토콜이라는 뜻입니다. 파일을 읽고 쓸 수 있지만, 디렉터리 목록을 표시할 수 없고 기본 설계에서는 사용자 인증을 제공하지 않습니다. 단순성은 프로토콜의 작업이 중요하지 않다는 주장이 아니라 자원 결정이었습니다.

RFC 906은 부트스트랩 로딩을 위해 TFTP를 제안했습니다. 부팅 중인 기기와 그 서버 모두 쉽게 구현할 수 있었기 때문입니다. 작은 클라이언트는 ROM이나 EPROM 안에 존재하며, 첫 프로그램 이미지를 얻어 더 풍부한 구성이 가능한 소프트웨어에 제어를 넘길 수 있었습니다. 이 프로토콜의 낮은 성능은 그 일이 다음 계층을 가능하게 하는 것이었을 때 덜 중요했습니다.

이 환경은 정확한 사양의 가치를 증폭시킵니다. 펌웨어에 구워진 코드는 평범한 애플리케이션보다 검사하거나 교체하기 어려울 수 있습니다. 모호한 복구 규칙은 공급업체와 기기 세대를 넘어 살아남을 수 있습니다. 상호운용성은 기능을 보존하는 만큼 효율적으로 결함도 보존할 수 있습니다.

이후의 TFTP 작업은 옵션 협상, 블록 크기 제어, 타임아웃·전송 크기 옵션을 추가했습니다. 예컨대 RFC 2347은 별도의 옵션 승인 패킷을 정의하고, 지원되지 않는 옵션은 기본 교환을 몰래 바꾸는 대신 생략하도록 요구했습니다. 확장은 유용성을 높였지만, 기대한 블록과 오래된 중복을 구분해야 한다는 근본 의무를 폐지하지는 않았습니다.

표준 지위는 TFTP를 일반적인 보안 파일 서비스로 바꾸지도 않았습니다. RFC 1350은 사용자 인증이 없음을 기록합니다. RFC 1123은 구성 가능한 경로명 접근 제어를 권고하고, 약한 접근 제어가 심각한 보안 구멍을 만들 수 있으므로 브로드캐스트 TFTP 요청은 무시해야 한다고 말합니다. 프로토콜은 통제된 부트 경로 안에서는 적절히 최소적이고, 그 밖에서는 위험할 만큼 노출되어 있을 수 있습니다.

Sollins의 더 넓은 업적은 유지보수 역할을 드러냅니다

MIT CSAIL의 Sollins 약력은 TFTP를 네트워크 기반 시스템에 관한 더 긴 연구 경력 안에 놓습니다. 약력은 Swarthmore의 수학 학위, MIT에서의 컴퓨터 과학 대학원 학위, 그리고 분산 이름 관리, 인증, 전역 명명, 장수명 정보 시스템, 극한 규모 확장에 관한 연구를 기록하고, 1999년과 2000년에 미국 국립과학재단(National Science Foundation)의 네트워킹 연구 수석 프로그램 디렉터로 재직했음을 밝힙니다.

이 주제들은 중복 패킷 루프가 구체적으로 만들어 내는 하나의 질문을 공유합니다. 메시지, 구현, 제도가 설계 당시의 순간보다 오래 살아남을 때, 분산 시스템은 어떻게 의미를 보존하는가? 답은 단순히 기능을 추가하는 것이 아닙니다. 때로 내구성은 하나의 모호한 허용을 제거하는 데 달려 있습니다.

역사 기록은 또한 깔끔한 영웅 서사를 거부합니다. Chiappa는 최초 설계와 1992년 5월 버그 수정을 인정받습니다. Baldwin, Clark, Szymanski와 많은 검토자가 프로토콜을 다듬었습니다. Robert Braden은 RFC 1123을 편집했으며, 그곳에서 실패 시퀀스와 의무 수정이 보기 드문 명확성으로 제시되었습니다. Sollins는 이 집단적 설계를 인터넷 표준까지 이어 간 내구성 있는 TFTP 사양을 집필했습니다.

이 공적의 분배 자체가 유용합니다. 인프라는 흔히 저자, 원 설계자, 버그 발견자, 구현자, 운영자가 서로 다른 문서를 통해 유지됩니다. 중요한 것은 문서가 규칙이 존재하는 이유를 보여 줄 만큼 충분한 출처를 보존하는지입니다. 그 설명이 없으면, 미래의 단순화는 호환성이 막으려 했던 바로 그 행동을 다시 도입할 수 있습니다.

올바른 결과만으로는 충분한 근거가 없습니다

마법사의 제자 전송은 올바른 파일을 만들어 낼 수 있습니다. 그렇기 때문에 최종 체크섬은 건전한 구현의 필요조건이지만 충분조건은 아닙니다. 검증은 생성된 트래픽의 양, 어떤 상태 전이가 발생했는지, 그리고 지연이나 재정렬이 하나의 복구 사건을 지속적인 패턴으로 바꾸었는지도 살펴야 합니다.

실용적인 시험은 말하기가 간단합니다. 발신자가 대응하는 DATA를 재전송한 뒤에 ACK를 지연시켜 도착하게 하십시오. 두 승인을 모두 전달하십시오. 다음 DATA 블록은 한 번만 전송되어야 하며, 오래된 ACK 복사본마다 한 번씩 전송되어서는 안 됩니다. 중복 DATA, 손실 ACK, 옵션 협상, 경계 블록 번호로 이 실험을 반복하십시오. 타임아웃 알고리즘은 독립적으로 관찰하십시오.

운영자에게 오늘의 관련성은 보편적이기보다 조건적입니다. 어떤 기기는 제조 중, 긴급 복구 중 또는 네트워크 부팅 중에만 TFTP를 사용할 수 있습니다. 다른 기기는 이를 제거했을 수 있습니다. 세 번째는 부팅 기능에 필요한 것보다 넓은 권한으로 서버를 노출하고 있을 수 있습니다. 제품 시트에 적힌 프로토콜 이름은 어느 코드 경로가 실행되는지, 수정된 상태 머신이 존재하는지 알려 주지 않습니다.

따라서 Sollins의 TFTP 기록은 현대 인프라에 절제된 질문 하나를 남깁니다. 오래된 메시지가 돌아왔을 때, 시스템은 그것을 오래된 작업에 대한 증거로 인식합니까, 아니면 새 작업을 만들 권한으로 착각합니까? 그 차이는 작은 프로토콜 안의 한 번의 비교입니다. 지연 아래에서 그것은 복구와 증식의 차이가 됩니다.

출처