요약

  • 초기 텔넷은 바이트 공간의 상위 절반을 제어에 할당했습니다. 이후 프로토콜은 명령 권한을 값 255인 IAC 하나에 집중시켜, 나머지 255개 값이 독립 명령 코드와 충돌하지 않고 통과할 수 있도록 했습니다.
  • 리터럴 데이터 값 255는IAC IAC로 인코딩됩니다. 협상된 이진 전송은 전체 8비트 데이터 범위를 열지만 텔넷 제어를 끄지는 않습니다. 수신자는 여전히 IAC와 내장된 명령을 탐색합니다.

빨간 타일 하나는 명령이 될 수 있고, 둘은 데이터 한 조각이 된다

단말 프로토콜을 통해 이진 파일을 보내는 상상을 해봅시다. 파일의 다음 바이트가 우연히 십진수 값 255를 가집니다. 이 값을 “다음 바이트를 명령으로 해석하라”로 취급하는 수신자는 파일의 일부를 프로토콜 구문으로 소모해 버립니다. 항상 파일 데이터로 취급하는 수신자는 옵션을 변경하라는 진짜 명령을 놓칩니다. 회선에는 두 경우 모두 같은 숫자가 흐르고 있습니다.

텔넷은 작은 문법으로 이 모호성을 해결했습니다. 단일 IAC(Interpret As Command)는 제어를 시작합니다. IAC 뒤에 정의된 명령 코드가 오면 그 명령을 호출하며, 때로는 명령을 완성하기 위한 추가 바이트가 따릅니다. IAC 뒤에 IAC가 오면 값이 255인 하나의 평범한 데이터 바이트를 나타냅니다. 송신자는 값을 두 배로 만들고, 수신자는 그 쌍을 인식해 프레이밍 사본을 제거합니다.

이것은 “뒤따르는 것은 무엇이든 리터럴이다”라고 말하는 일반적인 이스케이프가 아닙니다. 두 번째 IAC는 그 위치에서 정확히 하나의 의미만 가집니다. 그 밖의 뒤따르는 값은 여전히 텔넷 명령이거나 텔넷 명령 구문의 일부입니다. 두 바이트짜리 회선 시퀀스가 하나의 애플리케이션 데이터 바이트가 되는 이유는 양쪽 끝점이 동일한 파서 상태를 공유하기 때문입니다.

이 규칙은 한 개의 애매한 바이트 이상을 얻어냈습니다. 8비트 값 공간의 큰 부분을 영구히 희생하지 않고도 단일 연결 안에서 데이터와 제어가 순서대로 공존할 수 있게 되었습니다.

최초의 텔넷은 공간의 절반을 제어에 사용했다

1972년 4월의RFC 318은 네트워크 가상 단말(NVT)을 중심으로 공식 ARPANET 텔넷 프로토콜을 기술했습니다. 값 0부터 127까지는 USASCII를 담았고, 값 128부터 255까지는 특수 제어 신호에 할당되었습니다.

공통 작업이 서로 다른 텍스트 단말기의 연결이던 시절에는 이 구분이 이해할 만했습니다. 상위 값 바이트는 모호함 없이 프로토콜 동작이 될 수 있었고, 7비트 ASCII도 표준 표시 영역을 여전히 다룰 수 있었습니다. 그러나 이 구분은 더 풍부한 문자 집합과 임의의 이진 데이터를 번거롭게 만들었습니다. 가능한 값의 절반이 애플리케이션에 단순히 사용 가능하지 않았습니다.

RFC 318은 투명(Transparent) 모드를 포함해 다른 코드 집합으로 이스케이프하는 방법을 명명했지만, 그런 이스케이프 이후에는 텔넷 신호의 의미와 심지어 ASCII로 되돌아가는 경로조차 정의되지 않을 수 있음을 인정했습니다. 데이터 알파벳을 바꾸는 일은 프로토콜이 자신의 제어를 인식하는 능력을 위협했습니다.

문제는 구조적인 것이었습니다. 제어 권한이 많은 나머지 바이트 값에 붙어 있다면, 데이터 어휘를 확장하는 순간 그 권한들이 새 데이터와 충돌하게 됩니다.

QUOTE 제안이 해법의 형태를 드러냈다

1973년 1월의 텔넷 이슈 논의인RFC 435는 순수 이진을 기본값으로 만드는 방안을 검토했습니다. 저자들은 프로토콜에 QUOTE 문자를 보강해, 그 뒤의 바이트가 항상 데이터로 해석되도록 제안했습니다. 그러면 상위 값 바이트는 명령 공간으로 남으면서, 인용된 발생만이 리터럴로 전달될 수 있었습니다.

이 제안은 훗날의 IAC 규칙이 아니며, 배치된 것처럼 다시 쓰여서는 안 됩니다. 그것의 가치는 설계 압박을 지목했다는 점에 있습니다. 텔넷에는 데이터 해석이 바뀌더라도 살아남는 이스케이프 경계가 필요했습니다.

넓게 보아 두 가지 선택지가 있었습니다. 많은 값을 제어에 예약하고 수많은 데이터 충돌을 인용 처리하는 것. 아니면 하나의 구별된 값을 제어로 가는 관문으로 예약해, 데이터로 나타날 때 비용을 지불하는 값을 그 하나로 한정하는 것. 인터넷 텔넷 규격은 결국 후자를 선택했습니다.

IAC는 명령 권한을 하나의 접두어로 압축했다

1980년 6월에 발표된RFC 764는 텔넷을 하나의 TCP 연결 위에서 동작하는 8비트 바이트 지향 설비로, 제어 정보가 데이터 사이에 섞여 들어가는 것으로 기술했습니다. 1983년 5월의 기본 표준RFC 854는 이 구조를 유지했습니다.

모든 텔넷 명령은 값 255인 IAC로 시작하고 뒤에 명령 코드가 따릅니다. WILL, WON'T, DO, DON'T 같은 협상 명령은 옵션을 지명하는 세 번째 바이트를 가집니다. 다른 코드들은 서브협상 종료, 노옵션, Data Mark, 인터럽트, 출력 중단, 문자 지우기 등의 기본 기능을 의미합니다.

표준은 이 절충을 명시적으로 서술합니다. 협상이 데이터 공간을 더 포괄적으로 사용할 수 있게 되면서, 명령 충돌은 최소화되어야 했습니다. IAC 설계에서는 데이터로서의 IAC 자체만 두 배로 만들면 되고, 나머지 255개 바이트 값은 기본 명령 프레이밍에 대해 투명하게 통과할 수 있습니다.

여기서 “투명”은 좁은 프로토콜 의미를 갖습니다. NVT 모드가 모든 값을 의미론적으로 그대로 유지한다는 약속이 아닙니다. NVT에는 여전히 문자와 줄바꿈 관례이 있습니다. 이 말은 다른 값들이 숫자 값 때문에 독립적인 텔넷 명령으로 오인되지 않는다는 뜻입니다. 명령 권한은 나머지 바이트 값의 전체 영역에서, 하나의 관문에서 시작되는 시퀀스로 이동했습니다.

명령은 해석이 바뀌는 지점에 정확히 놓였다

데이터와 제어가 스트림을 공유하기 때문에 순서가 유용해집니다. RFC 854는 어떤 옵션이 명령 송신자의 데이터 처리 방식에 영향을 미친다면, 그 협상 명령은 송신자가 새 해석이 효력을 갖기를 원하는 지점에 삽입되어야 한다고 말합니다.

수신자는 “특정되지 않은 미래의 데이터가 새 관례이용 처리된다”고 말하는 분리된 제어 메시지를 받지 않습니다. 수신자는 앞선 바이트와 뒤따르는 바이트 사이에서 명령을 만나게 됩니다. 따라서 프로토콜은 하나의 순서 있는 대화 안에 경계를 그릴 수 있습니다.

그 경계는 파서에도 의무를 부과합니다. TCP는 지금 하나의 IAC를 전달하고 다음 바이트를 나중에 전달할 수 있습니다. 세그먼트 경계는 텔넷 레코드가 아닙니다. 구현은 스트림이 접두어 뒤에서 일시적으로 끝났음을 알 만큼의 상태를 유지해야 합니다. 또한 두 배 형태를 정확히 한 번만 디코딩해야 합니다. 두 바이트를 모두 남기면 데이터가 훼손되고, IAC 명령 쌍을 마치 데이터인 것처럼 접으면 제어가 사라집니다.

전송 계층은 순서를 보존합니다. 텔넷이 문법을 공급합니다. 어느 쪽도 스트림을 저절로 메시지로 바꾸지 않습니다.

서브협상은 같은 이스케이프 규칙을 중첩했다

옵션은 때때로 예 아니오 이상을 필요로 합니다.RFC 855는 서브협상을IAC SB, 옵션 코드와 매개변수, 그리고IAC SE로 종료되는 형태로 정의합니다. 매개변수 형식을 이해하지 못하는 수신자도 프레이밍 시퀀스를 찾음으로써 끝을 찾을 수 있습니다.

그런데 매개변수 자체에 값 255가 들어 있으면 어떻게 할까요? RFC 855는 일반 규칙을 적용합니다. 두 배로 만드십시오. 그렇지 않으면 매개변수가 텔넷 구문의 시작처럼 보이는 것을, 혹은 다음 값과 결합해 가짜 종료 표식을 만들어 낼 수 있습니다.

이것은 재귀적 프레이밍 규율의 간결한 예입니다. 옵션이 자신의 매개변수 의미를 제어하지만, 기본 텔넷 계층은 IAC의 보호권을 유지합니다. 확장은 공유 스트림을 지키는 바이트를 재정의할 권한을 받지 않습니다.

그 경계는 무지가 생존 가능하게 만들었습니다. 송신자가 리터럴 255를 올바르게 이스케이프했다면, 기본 파서는 옵션 페이로드가 불투명하더라도 진짜IAC SE로 건너뛸 수 있었습니다.

이진 모드는 제어를 끄지 않은 채 8비트를 열었다

결정적인 시험은 임의의 이진 데이터였습니다.RFC 856은 이진 전송 옵션 0을 정의합니다. 이것은 각 방향마다 별도로 협상됩니다. 한쪽이 8비트 이진 수신에 동의하는 동안 반대 방향은 이전 해석 아래에 남을 수 있습니다.

활성화되면 IAC가 앞서지 않는 바이트는 8비트 이진 데이터로 해석됩니다. 그러나IAC IAC는 여전히 데이터 값 255를 의미하고, IAC 뒤에 유효한 텔넷 명령이 오면 여전히 명령입니다. 이진 모드는 데이터의 처리를 바꾸지만, TCP 스트림 전체를 텔넷에게 불투명하게 만들지는 않습니다.

여기서 접두어 설계가 그 가치를 입증합니다. 제어가 여전히 128부터 255까지의 모든 값을 차지했다면, 이진 모드는 알파벳의 절반을 인용하거나 명령을 포기해야 했을 것입니다. 제어를 하나의 값에 집중함으로써 거의 모든 이진 값이 직접 전송될 수 있고, 같은 연결 안에서 옵션 변경이 보존됩니다.

따라서 이진 모드는 “협상 이후의 날 TCP”가 아닙니다. 그것은 텔넷 프레이밍 불변식 아래 놓인 텔넷 데이터 관례입니다.

호스트 요구사항은 예외를 잊을 수 없게 만들었다

1989년 10월까지RFC 1123은 이 동작을 명시적인 호스트 요구사항으로 만들었습니다. 텔넷 옵션은 데이터 스트림 어디에나 나타날 수 있으므로, 데이터로서 보내지는 IAC는 반드시 두 배가 되어야 합니다. 이진 협상이 성공한 후에도 수신자는 여전히 IAC를 탐색하고, 내장된 명령을 따르며, 두 배가 된 데이터 값 255를 요구해야 합니다.

다른 변환은 바뀝니다. 이진 모드는 일반적인 캐리지 리턴 치환이나 줄 끝 관례를 적용해서는 안 됩니다. 그러나 제어 이스케이프는 남습니다. 이 대조는 흔한 구현 지름길을 막습니다. “이진” 모드는 텍스트 정규화를 끌 수 있지만, 텔넷 파서를 끌 수는 없습니다.

현재의IANA 텔넷 옵션 레지스트리는 옵션 0인 이진 전송을 포함해 옵션 네임스페이스와 그 참조를 유지합니다. 그 레지스트리는 배치 규모 조사가 아닙니다. 그것은 또한 범위 구분을 보여줍니다. 번호 255인 옵션은 값이 255인 데이터 스트림의 IAC 바이트와 같은 대상이 아닙니다. 숫자의 일치가 프로토콜 역할을 하나로 합치지는 않습니다.

반복된 하나의 바이트가 하나의 순서 있는 대화를 지켰다

텔넷의 이스케이프 규칙은 회선 잡학으로 쉽게 치부될 수 있습니다. 그러나 실제로 그것은 세 가지 권한을 분리합니다. 애플리케이션은 데이터를 선택하며, 그 데이터가 값 255를 포함할지 여부도 포함됩니다. 텔넷 송신자는 그 값이 우연히 명령 의미를 얻지 못하도록 인코딩합니다. 텔넷 수신자는 두 배 표현과 진짜 명령을 구별하는 파서를 소유합니다.

중앙 서비스가 세션을 검사할 필요가 없습니다. 어떤 명령도 두 번째 연결을 요구하지 않습니다. 공통 계층은 모든 옵션과 데이터 모드가 존중해야 하는 하나의 작은 불변식을 정의합니다. 확장은 에코, 단말 유형, 문자 해석, 레코드 경계를 바꿀 수 있지만, IAC를 몰래 가져갈 수는 없습니다.

비용은 영구적입니다. 모든 구현은 탐색해야 하고, 모든 리터럴 255는 회선 바이트를 하나 더 소비하며, 불완전한 접두어는 상태를 요구하고, 잘못된 이스케이프는 이후의 모든 해석을 어긋나게 할 수 있습니다. 이득도 영구적입니다. 데이터와 제어가 데이터 값을 권한으로 혼동하지 않으면서 함께 진화할 수 있습니다.

그 바이트가 자신을 반복해야 했던 이유는 중복이 더 강하게 만들었기 때문이 아니라, 첫 번째 사본이 명령 의미를 내어놓아 두 번째 사본이 데이터로 남을 수 있었기 때문입니다.

출처와 한계

초기 절반 공간 설계는RFC 318에서, QUOTE 논의는RFC 435에서 나옵니다.RFC 764와RFC 854는 섞인 스트림과 IAC 문법을 제공합니다.RFC 855는 서브협상 이스케이프를,RFC 856은 이진 동작을,RFC 1123은 호스트 요구사항을, 그리고IANA 레지스트리는 옵션 네임스페이스를 제공합니다. 이 출처들은 현재 배치 점유율, 제품 준수성, 파서 안전성, 암호화, 인증, 그리고 모든 호스트에 대한 단일 역사적 구현 시점을 확립하지 않습니다.