요약
STOU는 FTP 클라이언트가 새 파일의 경로명을 제공하지 않고 바이트를 제출할 수 있게 했다. 서버는 현재 디렉터리 내에서 고유한 이름을 할당하고, 전송 전에 실제 경로명을 반환해야 했다.- RFC 1123은 RFC 959의 드러내는 오류를 바로잡았다. 잠정 응답인
125또는150 FILE:는 기록될 파일의 이름을 알려주고, 이후의226또는250은 파일 동작이 완료되었는지를 말한다. 할당과 결과는 별개의 근거다. - 이 설계는 하나의 네임스페이스 충돌을 해결했다. 그러나 전역적으로 안정적인 파일 식별자, 내구성 있는 보관, 권한 부여, 기밀성, 안전한 재시작 의미론, 현재의 배포 증거를 만들어내지는 않았다.
두 순간을 동시에 차지하려던 응답
1985년 10월 파일 전송 프로토콜 사양의 한 문장은 작은 모순을 담고 있으며, 그 결과는 컸다. 새로 도입된 Store Unique 명령은 서버의 현재 디렉터리에서 고유한 이름으로 파일을 만들도록 했다. 그리고 그 문장에 따르면 서버는 이 생성된 이름을 “250 Transfer Started” 응답에 반드시 포함해야 했다.
그러나 FTP의 응답 체계에서250은 다른 순간에 배정되어 있었다. 즉, 요청된 파일 동작이 성공하고 완료되었음을 나타내는 코드였다. 막 시작 중인 전송은 데이터 연결이 이미 열려 있는 경우125, 서버가 곧 연결을 열 예정인 경우150에 속했다. 같은 사양의 명령 표는 전송 전에125또는150을, 전송 후에226또는250을 배치했다. “250 Transfer Started”는 단순히 부정확한 문구가 아니었다. 완료 코드를 잠정적 영수증처럼 사용하려 한 것이다.
4년 뒤, 인터넷 호스트 요구사항 문서가 이 순서를 바로잡았다.STOU를 받은 서버는 전송 전에 정확히 두 가지 형식의 행 중 하나에서 실제 경로명을 공개해야 했다.
125 FILE: pppp
150 FILE: pppp
여기서pppp는 기록될 파일의 경로명이었다. 미래 시제가 중요했다. 이 응답은 서버가 할당한 이름이 무엇인지 확정하는 것이었다. 모든 바이트가 도착했다거나, 파일이 계속 이용 가능할 것이라거나, 나중의 읽는 이가 열 수 있을 것이라는 말은 아니었다. 그것들은 이후의 프로토콜 상태와 로컬 저장 정책에 속한다.
이 수정은 근거 설계의 간결한 역사다. 하나의 대화 안에서 요청, 할당, 완료된 동작이 모두 일어날 수 있지만, 그 셋은 서로 교환할 수 없다. 서버는 전송에 대해 진실을 말할 충분한 근거를 갖기 전에 이름에 대해서는 진실을 말할 수 있었다.
동작은 알았지만 이름은 몰랐던 프로토콜
FTP는 연결하는 컴퓨터들로부터 어려운 경계를 물려받았다. 1971년 프로토콜은 파일을 시스템 내에서 경로명으로 고유하게 식별되는 데이터로 기술했다. 네트워크 전반에 동작은 표준화했지만, 원격 파일 시스템의 명명 규칙은 표준화하지 않았다. 사용자는 서빙 호스트의 규칙을 따라야 했다.
그것은 문자열로 위장한 상당한 부담이었다. 경로명에는 수신 시스템에서만 의미를 갖는 디렉터리, 장치, 파일 구성 요소가 들어갈 수 있었다. 송신자는 목적지를 식별하기 위해 그 낯선 네임스페이스에 대해 충분히 알아야 했다. 일반적인 저장 요청에서는 기존의 이름 있는 파일이 대체될 수 있고, 그렇지 않으면 새 파일이 만들어질 수 있었다. 따라서 이름 선택은 미관상의 문제가 아니었다. 어떤 로컬 파일이 변경되는지를 결정할 수 있었다.
초기 프로토콜은 파일 보호도 관련 지식이 있는 곳에 남겨두었다. 상주하는 파일 시스템이 선택적 접근을 결정했다. FTP는 식별자와 비밀번호를 전달했지만, 원격 경로명을 쓰기 권한으로 바꾸지는 않았다. 이름 문법, 충돌 동작, 권한 부여는 서로 연관되어 있으면서도 별개의 표면에 속했다.
이 배치는 클라이언트가 원하는 원격 파일을 실제로 알고 있을 때는 잘 작동했다. 그러나 수신 풀, 즉 독립적인 송신자들이 저장 시스템의 내부 구조를 알지 못한 채 작업을 올리면서 서로를 덮어쓰지 않아야 하는 곳에는 설득력이 떨어졌다.
명령 이전에 존재했던 풀
1973년 RFC 505는 곤란한 형태의 파일 전달을 다루었다. 비밀번호를 모르는 상태에서 어떻게 한 사람이 다른 호스트에게 파일을 보낼 수 있을까? 한 가지 답은 방향을 뒤집는 것이었다. 의도된 수신자가 자신의 권한으로 파일을 가져오게 하는 것이다. 이는 접근 제어를 유지했지만, 원본이 이용 가능한 동안 수신자가 접속해 있어야 했다.
다른 답은 Multics의 관행을 빌렸다. 요청되지 않은 입력은 가칭 수신자의 디렉터리에 직접 들어가는 대신 풀 디렉터리로 갈 수 있었다. 수신자에게 통지가 전달되고, 나중에 파일을 복사할 수 있었다. 풀은 두 가지 위험을 동시에 제한했다. 외부인이 다른 사용자의 디렉터리 할당량을 소모해서는 안 되고, 올려진 파일이 기존 개인 파일을 덮어써서도 안 되었다.
RFC 505는POOL id name명령을 제안했다. 송신자는 여전히 원하는 이름을 제시했지만, 서버는 그 이름을 풀 내에서 고유하게 만들기 위해 필요한 접두사나 접미사를 붙였다. 수신자 통지에는 적절히 수정된 로컬 경로명이 담겼다. 이 문서는 더 깊은 이식성 문제도 인식했다. 명시적인 수신자 식별자가 없으면 서버는 경로명에서 수신자를 추론해야 할 수 있고, 그러면 송신자가 내부 구조를 너무 많이 알아야 한다.
이 제안은 배포 역사를 확립하지 않았고,POOL이 그대로STOU가 된 것도 아니다. 그 가치는 더 정밀하다. Store Unique가 나중에 좁혀들인 문제를 드러냈다는 점이다. 파일을 받는 쪽이 충돌 도메인을 통제하기 때문에, 그 도메인 안에서 이름을 할당하거나 조정하고 그 결과를 도메인 밖의 당사자들에게 보고해야 했다.
새 동사가 덜 지닌 권한
RFC 949는 1985년 7월, 지금 보면 분산 시스템의 물리적 은유처럼 느껴지는 예시들과 함께 나왔다. 프린터 데몬, 팩스 데몬, 심지어 카드 펀치 대기열을 공급하는 풀 디렉터리들. 여러 송신자가 작업을 올릴 수 있었지만, 이미 대기 중인 작업과 충돌하는 이름을 반드시 골라야 하는 사람은 없어야 했다.
이 제안은STOR를 수정하거나, 제어 인수를 추가하거나, 인수 없는 저장을 특수 사례로 다루는 방안을 검토했다. 대신 별도의 명령을 택했다. 기존STOR처리를 다시 여는 것은 바람직하지 않아 보였고, 구현체들이 명령 이름 기준으로 분기한다는 가정 하에서는 새 동사가 상대적으로 다루기 쉬웠다. 여러 어색한 약어를 거친 뒤 문서는STOU로 정했다.
의미상의 변화는 의도적으로 작았다.STOU는STOR처럼 동작하되, 결과 파일이 현재 디렉터리에 그 디렉터리에서만 고유한 이름으로 만들어진다는 점이 달랐다. 송신자는 더 이상 최종 경로명을 제공하지 않았다. 서버는 그 이름이 무엇이 되었는지 송신자에게 알려야 했다.
이것은 넓은 서버 권한의 창설이 아니었다. 서버는 이미 원격 네임스페이스와 파일 시스템을 통제하고 있었다.STOU는 기존의 하나의 제어 표면을 명시적이고 책임 가능하게 만든 것이다. 어떤 이름이 비어 있는지는 서버만 볼 수 있다면, 서버가 하나를 골라 그 선택의 근거를 반환해야 한다. RFC 949는 새 명령이 접근 제어, 인증, 회계를 우회하지 않는다는 점을 명시적으로 경고했다. 비어 있는 이름을 할당할 권한이 임의의 내용을 저장할 권한을 부여하지는 않았다.
STOU 이후에 남은 부재
RFC 959는 단 3개월 뒤STOU를 일곱 개의 새 선택적 명령 중 하나로 편입했다. 형식 문법은 그 구분을 보여주었다.
STOR <pathname> <CRLF>
STOU <CRLF>
빠져 있는 경로명이 핵심이었다. 클라이언트는 세션 앞 단계에서 현재 디렉터리를 선택할 수는 있었지만, 그 디렉터리 안에서 새 파일의 이름을 지정하지는 않았다. 이 좁아진 요청은 경합을 줄였다. 클라이언트가 디렉터리를 살펴보고 쓸모 없어 보이는 이름을 만들어, 저장이 시작되기 전에 다른 클라이언트가 그 이름을 택하지 않기를 바라는 일은 없어졌다.
보장도 “고유”라는 단어가 암시하는 것보다 좁았다. RFC 959는 현재 디렉터리에 대해 고유하다고만 말했다. 모든 서버에서 고유하거나, 영원히 고유하거나, 디렉터리들에 걸쳐 고유하거나, 특정 바이트 열에 고유하다는 약속이 아니었다. 그 이름이 나중에 다시 쓰일 수 없다는 말도 없었다. 범위는 서버가 할당을 수행한 네임스페이스였다.
명령은 선택적으로 남았다. 표준에 있었다는 것이 보편적 지원을 만들지 않았다. 인수 목록에 없다는 것이 세션 문맥을 지우지 않았다. 잠정 응답의 성공이 전송 상태 기계를 지우지도 않았다. 이러한 한계 각각은 편의 메커니즘이 프로토콜이 제공하는 것보다 큰 주장으로 확대되는 것을 막는다.
사람을 위한 텍스트 속의 기계 판독 가능한 예외
FTP 응답은 두 독자를 위해 설계되었다. 세 자리 숫자는 프로그램에 다음 상태를 알려주었고, 뒤따르는 텍스트는 보통 사람을 위한 것이며 서버마다 달라질 수 있었다. 이 구분 때문에 원래의 STOU 문구는 특히 취약했다. 경로명이 지정되지 않은 산문 속에 살아 있다면, 클라이언트는 프로토콜이 서버에게 다르게 표현할 여지를 주는 텍스트에서 기계의 결정을 복원해야 했다.
RFC 1123은 단계와 문법을 모두 고정해 이를 해결했다. 실제 경로명은 잠정적인125또는150행에 있어야 했고,FILE:이 안정적인 표식을 제공했다. 클라이언트 소프트웨어는 서버의 해설이 끝나고 이름이 시작되는 지점을 추측하지 않고도 원격 문자열을 보관할 수 있었다.
이 순서는 주장들에 대한 유용한 장부를 만들었다.
- 클라이언트는 어떤 현재 디렉터리와 접근 상태를 가진 세션에서
STOU를 요청했다. - 서버는 곧 기록할 파일의 이름을 밝힌 잠정 행을 반환했다.
- 데이터 연결은 일정량의 데이터를 전달하거나 실패했다.
- 최종 긍정 또는 부정 응답이 그 시점에서 서버가 아는 결과를 기술했다.
- 로컬 정책이 이후의 가시성, 보존, 회수, 이름 변경, 삭제를 결정했다.
이 항목들을 하나로 뭉개면 정보가 사라진다. 클라이언트가 최종250만 기록하면, 파일 동작이 완료되었다는 사실은 알되 할당된 경로명을 식별하는 유일한 프로토콜 필드를 잃는다.150 FILE:만 기록하면 계획된 이름은 알되 전송이 성공했는지는 모른 채 남는다. 좁은 영수증이 유용한 것은 바로 관할 범위가 명확하기 때문이다.
“기록될 것”은 “안전하게 보관되고 있음”이 아니다
전송 전의 이름은 운영상 가치를 가질 수 있다. 클라이언트는 이후의 사건들을 서버가 선택한 경로명과 연관 지을 수 있다. 대기열 운영자는 고아가 된 항목을 세션 기록과 대조할 수 있다. 수신자에게 어떤 원격 이름을 청구해야 하는지 알려줄 수 있다. 그러나 이 모든 용도는 할당과 보관의 구분을 유지하는 데 달려 있다.
긍정적인 잠정 응답은 데이터 연결이 성공적으로 열렸음을 증명하지 않는다. 송신자가 기대한 바이트 열을 전달했음을 증명하지 않는다. 이후 완료 응답이 도착했거나, 관찰자가 그것을 보관했음을 증명하지도 않는다. 심지어 최종 성공 응답조차 FTP와 서버 경계에서의 진술이며, 백업, 불변 보존, 지속 권한, 미래 가용성을 약속하지 않는다.
이것이 응답 코드 수정의 실용적 의미다. 서버는 이름이 이미 결정되어 있었기 때문에 최종 응답까지 이름 공개를 미루지 않았다. 완료는 아직 알 수 없었기 때문에 잠정 응답에 완료를 넣지 않았다. 프로토콜은 시간을 근거의 일부로 보존했다.
재시작이 같은 저장 파일을 가정할 수 없었던 이유
FTP의 스트림 모드 재시작이 더 구체적으로 규정되면서 이 경계는 다시 드러났다. 재시작은 양쪽이 알려진 위치에서 이전 전송을 이어가도록 요구한다.RETR이나STOR의 경우, 이전 전송의 대상 파일을 양쪽이 충분히 식별할 수 있는 기존 원본 또는 목적지 파일이 필요하다.
RFC 3659는 서버가REST이후 다른 명령을 받아들일 수 있다고 하면서도, 재시작을STOU와 결합하는 것은 권하지 않았다. 그 결과는 정의되지 않은 것으로 간주된다고 했다. 파일의 나머지를 새로 생성되는 고유 파일명에 저장하는 일은 거의 유용하지 않다는 것이다.
문제는 바이트 오프셋과 생성된 이름이 다른 문법을 쓴다는 데 있지 않다. 둘이 서로 다른 연속성 질문에 답한다는 데 있다. 재시작 마커는 부분 상태를 참조한다.STOU는 서버에 새 경로명을 할당하라고 요구한다. 새 이름은 그것이 이전 접두사를 받았던 같은 저장 파일을 지칭한다는 근거를 제공하지 않는다. 서버가 이 조합을 지원하기로 선택한다면, 그 로컬 동작은 일반 명령 쌍이 확립하지 않는 정보를 필요로 한다.
이는 FTP의 재시작 역사 자체와 실질적으로 다른 문제다. 여기서 중요한 점은 두 계약의 충돌이다. “새것을 할당하라”와 “이 특정 옛것을 계속하라.” 어느 메커니즘도 빠진 연속성 관계를 지니지 않으면 조합은 실패한다.
고유함의 두 번째 의미
RFC 3659는 나중에 FTP의 또 다른 메커니즘에서 이 단어를 사용했다. 기계 판독 가능한 목록은Unique=팩트를 담을 수 있었다. 즉, 서로 다른 두 경로명이 같은 저장 파일을 지칭할 때 동일해야 하는 불투명 토큰이다. 이 토큰은 서로 다른 저장 파일에 대해서는 달라야 하고, 최소한 제어 연결의 수명 동안은 일관되어야 한다.
이 근거는STOU와 반대 방향으로 흐른다. Store Unique는 현재 디렉터리 내에서 충돌하지 않는 경로명을 요청한다. 목록 팩트는 클라이언트가 하드 링크처럼 서로 다른 두 경로명이 같은 저장 파일을 지칭할 수 있음을 인식하도록 돕는다. 하나는 이름 할당에 관한 것이고, 다른 하나는 동일 파일 비교에 관한 것이다.
RFC는 후자를 신중하게 제한했다. 토큰은 불투명하며 대소문자를 구분했다. 값이 같으면 하나의 결론만 허용된다. 그 이름들이 같은 저장 파일을 지칭한다는 것이다. 서버는 공개될 경우 보호 메커니즘을 우회할 수 있는 파일 시스템 식별자를 노출해서는 안 되었다. 비교를 위해 설계된 식별자조차 접근 권한(capability)보다 약하게 유지되어야 했다.
두 형태의 고유함을 나란히 놓으면 흔한 모델링 오류를 막는다. 고유한 경로명이 영구히 구별되는 저장 파일을 지칭할 필요는 없다. 하나의 저장 파일은 두 개 이상의 경로명을 가질 수 있다. 어느 사실도 소유권, 내용 무결성, 내구성을 증명하지 않는다.
충돌 제어는 결코 보안 계층이 아니었다
RFC 949는STOU가 인증, 회계, 접근 제어를 대체하지 않는다는 점을 분명히 했다. 이후의 FTP 보안 지침은 남은 간극을 놓치기 어렵게 만든다. 표준 FTP는 암호화 없이 비밀번호, 제어 정보, 데이터를 전송했다. 분리된 데이터 연결은 더 강한 보호와 상대 검증을 쓰지 않는 한 연결 탈취나 위조 데이터 삽입의 기회를 만들었다.
서버는 잘못된 상대로부터 데이터를 받아들이면서 두 개의 서로 다른 이름을 할당할 수 있다. 하나의 경로명 충돌은 막으면서 제어 대화를 노출할 수 있다. 정확한 원격 이름을 반환하면서 로컬 권한이 나중에 그 파일을 읽을 수 없게 만들 수 있다. 이 모든 진술은 동시에 참일 수 있다. 명명과 보안이 서로 다른 근거 위에서 작동하기 때문이다.
이 좁음은 명확히 유지될 때 강점이다.STOU는 자신의 충돌 문제를 해결하기 위해 영구적인 파일 식별 시스템이 될 필요가 없었다. 틀린 길은, 자신이 시도하지도 않은 보안 주장의 근거로 올바른 로컬 할당을 내보내는 것이다.
레지스트리가 보존하는 것—그리고 보여줄 수 없는 것
RFC 5797과 현재의 IANA FTP Commands and Extensions 레지스트리는STOU를 선택적 기본 명령으로 계속 실어 놓고 있으며, RFC 959와 RFC 1123을 가리킨다. 이는 유용한 역사적이자 네임스페이스 근거다. 같은 명령 레이블이 상충하는 의미로 배정되는 것을 막고, 구현자를 명령과 그 수정을 정의하는 문서들로 안내한다.
레지스트리 사양은 그러한 행에서 더 많은 것을 읽어내지 말라고 경고한다. 그 일차 목적은 명령과 확장 이름의 상충하는 사용을 피하는 것이다. 등재는 어떤 기능이 승인되었거나, 널리 구현되었거나, 특정 환경에서 안전하거나, 현재 사용 중이라는 선언이 아니다. 소문자base항목은 레지스트리 조직을 위한 자리표시자이며, 서버가 반드시 반환해야 하는FEAT광고가 아니다.
따라서 프로토콜 역사에는 두 개의 서로 다른 진실 원천이 있다. 레지스트리는STOU에 어떤 의미가 배정되어 있는지 말해줄 수 있다. 특정 구현과 세션의 관찰만이 그것이 지원되거나 사용되는지 말해줄 수 있다. 이 글은 배포 조사를 담고 있지 않으며 그런 주장도 하지 않는다.
작은 명령이 남긴 내구성 있는 제도적 교훈
Store Unique는 세계의 경로명들을 표준화하지 않았다. 오히려 반대 방향을 택했다. 원격 시스템은 자신의 명명 규칙, 현재 디렉터리, 접근 정책을 유지했다. 공통 프로토콜은 외부 클라이언트가 충돌 없는 할당을 요청하고 그 결과 원격 이름을 받을 수 있도록 하는 데 필요한 만큼의 구조만 추가했다.
그것은 얇은 계약이다. 결정을 실제로 충돌 도메인을 볼 수 있는 시스템에 위치시킨다. 그 시스템이 자동화된 상대가 사용할 수 있는 근거를 반환하도록 요구한다. 별개의 완료 단계를 보존한다. 생략과 명시적 경고를 통해 명명을 보안이나 영구 보관으로 바꾸는 것을 거부한다.
교훈은 중앙화된 할당이 항상 바람직하다는 것이 아니다. 통제와 증명은 가장 작은 관련 경계에 함께 놓여야 한다는 것이다. 클라이언트는 어떤 원격 이름이 비어 있는지 아는 척해서는 안 된다. 서버는 하나를 골랐다는 사실이 전송 완료를 증명한다고 여겨서는 안 된다. 레지스트리는 명령을 기록했다는 사실이 배포를 증명한다고 여겨서는 안 된다. 각 주체는 하나의 제한된 사실을 제공하고, 자신만이 알 수 있는 것에 대해 책임을 진다.
출처
- RFC 172 — The File Transfer Protocol
- RFC 505 — Two Solutions to a File Transfer Access Problem
- RFC 949 — FTP Unique-Named Store Command
- RFC 959 — File Transfer Protocol
- RFC 1123 — Requirements for Internet Hosts — Application and Support
- RFC 2577 — FTP Security Considerations
- RFC 3659 — Extensions to FTP
- RFC 5797 — FTP Command and Extension Registry
- IANA FTP Commands and Extensions registry
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





