Skip to main content
Nowa Zhu

:: Telnet Protocol Specification

··4 mins

Reference #

Telnet Protocol Specification (Request for Comments RFC 854). (1983). Internet Engineering Task Force. https://doi.org/10.17487/RFC0854

Read notes #

Telnet 的设计目的 #

  • 提供一个标准的方法,定义了 terminal 设备的接口和处理进程。并远期希望该协议可以用于 terminal-terminal 和 process-process 通讯;
  • 提供一个公平的、直接的、8 位字节的通讯能力;

基本设计 #

  • The concept of a “Network Virtual Terminal”
  • The principle of negotiated options
  • A symmetric view of terminals and processes.

以上是设计主要考虑的三个部分。

Network Virtual Terminal #

  • 什么是 NVT

    所有 Telnet 连接方都被看作是一个 Network Virtual Terminal (NVT)。NVT 是一个虚拟设备,它定义了终端设备标准的网络范围内的规范中间表现,即上述的「定义了 terminal 设备的接口和处理进程」,从而减少甚至消除 serveruser 主机 (host) 要保留双方终端特性、处理约定的需求。

    • user host 是物理终端连接的主机
    • server host 是提供特定服务的主机
    • user 是物理终端和本地主机组成的
    • server 是远程主机和特定服务程序组成的
    • serveruser 既可以是一个物理连接的设备,也可以是 terminal-terminal / process-process,此时 user host 是一个初始化了连接的 host

Negotiated options 使用方法和原则 #

之所以要设计 principle of negotiated options 是因为事实上很多主机都希望提供额外的服务,终端用户也希望有强大优雅的终端,而不是一个最低限度可用的终端。在当时大型主机才拥有足够的计算能力来运行各种服务,个人终端则既没有足够的算力只能远程登录主机运行服务,而且因为终端设备制造商的多样化,功能也是层次不齐的。当一个 Telnet 连接在初始化时,option request 可能会来回反复创建,因为每一方都会希望获得来自另一方提供的最佳服务。另一方面来说,在连接建立后,也需要可以动态调整连接的特性(模式)以适应变化的服务运行需求,不同的程序会有其所需的最佳运行模式环境。

独立但又结构化设计在 Telnet 协议内的 options 是类似 "DO, DON'T, WILL, WON'T" 这样的结构用于允许 serveruser 使用一组约定用于当前的 Telnet 连接,比如约定字符集、回显模式等。

  • options 基本使用方法

    • 连接的其中一方或者双方在连接初始化时都用上述的结构提出了 option negotiation request
    • 连接的任何一方在收到 option negotiation request 后,都必须发送同意或者拒绝回应
    • 对请求同意的回应语法被设计为:发送同样 option 的请求,这称为 The symmetry of the negotiation syntax
    • 如果同意了该 option,则立即对该连接生效;如果拒绝了,也应该继续保持该连接是一个没有应用该 option 的标准 Telnet 连接 (NVT)
    • 有可能的情况是,某个连接方会持续拒绝某些 options 的使用,也会持续拒绝某些 options 的关闭,但不管怎样,这都不影响连接和通讯的继续
  • The symmetry of the negotiation syntax

    因为对 option 请求的回应都设计为:发送回同样的 option 请求,如果把每个请求视作是新的连接请求,而不是 option 的 acknowledgment,会产生 nonterminating acknowledgment loops. 为了避免产生这样的 loop,option request 要遵循这些规则:

    1. option request 必须用来请求更改状态,而不能仅仅用来告知连接的另一方当前自己是在什么模式
    2. 如果连接一方收到了一个 option request 要求进入一个已经进入的状态,此时不应发送回应,以避免潜在的 endless loop in negotiation
    3. 在被拒绝后,最好不要再次连续自动重新发送 option request,以避免潜在的 nonterminating request loop 。此时用户可能已经给出了另一个命令或者在上下文中给出了有意义的信息,一个好的原则是,仅当来自另一端的后续信息或者用户干预时才再次重新发送 option request
    4. 每当一方向另一方发送 option request 时,不管是作为请求还是回应,不管应用该 option 可能对即将发送的数据造成什么影响,都应该立即插入该 option 对应的影响到即将发送的数据中,以使得该 option 的影响被立即应用。这可能是负面的,因为如果 option request 是一个请求的话,此时还不确定是否会被同意。所以通常在发送了 option 请求后,会先暂时缓冲数据,收到明确的回应后再 flush 数据
    5. 扩展的 option negotiation 需要在标准的或更高优先级的 option request 上连接双方达成一致后再开始,以确保连接双方具备解析扩展语法的能力。

    option negotiation syntax 设计成比较简单的原因是为了让 option 的成本降低,虽然这样也会带来滥用的风险。如果一个特定的 option 需要比 "DO, DON'T, WILL, WON'T" 更为复杂的语法结构,那么更合适的做法是先用 "DO, DON'T, WILL, WON'T" 这样的语法让连接双方都了解 option,然后再进一步自由使用各种奇特的语法。

    比如连接的其中一方希望更改行的长度,如果这个 option request 被接受了,一个不同的语法可以被用来协商行的长度是多少,这可能是一个 sub option negotiation request 包含了最小、最大行长度的字段。

  • 所以总结 option request 的语法和流程:

    • 任何一方发送 WILL XXX 以表明该方希望(提议)开始执行 option XXX~,~DO XXXDON'T XXX 作为其积极和消极的确认(同意和拒绝)
    • 类似地,发送 DO XXX 以指示对方(即 DO 的接收者)开始执行 option XXX 的请求,将 XXXWON'T XXX 作为肯定和否定确认(同意和拒绝)
    • 由于 NVT 是一个未开启 option 的定义,因此可以保证即便在 DON’T 和 WON’T 响应下使连接处于两端都可以处理的状态
    • 也因此所有主机都可以实现其 TELNET 进程以完全不知道不支持的选项,可以简单地返回拒绝任何无法理解的选项请求

    Telent 协议被尽可能地设计为一个 server-user 对称的协议,所以它可以自然地、简单地覆盖 user-user(linking) / server-server(cooperating process) 场景。当然,对称只是一个原则,而不是必须执行的铁律。

    关于建立新的 option 的流程,可以参阅 RFC 文档:Telnet Option Specifications (Request for Comments RFC 855). (1983). Internet Engineering Task Force. https://doi.org/10.17487/RFC0855

NVT 详细设计 #

NVT 是一个双向字符设备,它有一个 printer 和一个 keyboard 设备。

  • printer 响应接受到的数据(incoming data)并输出
  • keyboard 生产要通过 Telnet 连接发出的数据(outgoing data)
  • echoes 如果要求回显,则数据会如 incoming data 一样在 printer 输出

通常情况下,本地 keyboard 产生的数据会直接在本地 printer 输出,而不经过 Telnet 连接传输。更多关于 echo 的规范,可以参见 RFC: Telnet Echo Option (Request for Comments RFC 857). (1983). Internet Engineering Task Force. https://doi.org/10.17487/RFC0857

TRANSMISSION OF DATA - 数据传输 #

虽然 Telnet 连接本质上是全双工 full duplex 的,但 NVT 被视作为运行在行缓冲 line-buffered 模式下的半双工设备。也就是说,除非相反的 option 协商一致,否则 Telnet 连接双方的数据传输遵循以下默认的规则:

  1. 只要本地缓冲空间允许,数据应该在处理它的 host 中累积,直到完整的行数据准备好传输,或者除非本地定义的明确的信号触发了传输。这样的信号可以由进程或者用户创建。之所以有这一条规则,是因为对于某些主机或服务来说,处理网络中断的成本很高,再加上默认的 NVT 规范中,=echoes= 不会经过网络,因此在本地缓冲数据是合理的。

  2. host 完成了向 NVT printer 发送数据打印,并且输入队列中没有来自 NVT keyboard 的待处理输入时,该进程应该传输 Telnet Go Ahead (GA) 命令。不过这也不意味着要求每一行的信息结束都需要加上 GA 命令,通常 server 不需要一个特定的信号才能开始处理数据(除了 EOL 或者其他自定义的字符)。相反,GA 命令被设计用于帮助用户本地主机操作 A physically half duplex terminal which has a "lockable" keyboard such as the [[http://www.columbia.edu/cu/computinghistory/2741.html][IBM 2741]].

    在当年使用物理终端的年代,除了 user-server 连接之外,还有 terminal-computer (Local Computer / user host) 连接,即本地终端到本地计算机的连接。而 terminal-computer 之间的连接始终处于 terminalcomputer 的控制下,双方都不能单方面抢占连接控制权,即任何一方需要在处理数据后放弃控制权。对于 terminal 来说,它被设计为在每个行结束时 (如输入新的一行时) 交出控制权。当 computer (Local) 接受到输入的数据后,对数据进行处理并决定是否要输出数据,如果不需要输出,则将控制权交回给 terminal; 如果需要输出,则控制权继续保留在 computer 直到所有的数据输出完毕。这也是上述为什么 echo 不需要经过网络的原因,本地 keyboard 输入的字符经过本地计算机的处理后可以直接输出到本地终端的 printer.

    通过网络使用这种终端的困难是显而易见的: computer (Local / user host) 在看到 EOL 时不再能决定是否保留控制权,而是取决于处理数据的 server 。因此,GA 命令提供了一种机制,通过该机制 server (Remote Computer / server host) 可以向 user (Local Computer / user host) 发送信号,表明是时候该将控制权交给 user 了。需要注意的是,GA 命令的过早传输可能导致输出阻塞,因为 user 会认为数据输出传输已经完成。

    当然,上述内容不适用于 user-to-sever 这个方向的通讯,只适用于 server-to-user 方向。在 user-to-server 方向上,GA 可以随时发送,但是没有必要发送。如果 Telnet 应用于进程间通讯,也不需要向任何一方发送 GA。最后,如果应用于 terminal-terminal 通讯,GA 可能在任何一个、一个或两个方向都不需要 GA。如果 host 计划支持 terminal-terminal 的通讯,则建议 host 在需要发送 GA 时手动向用户发送一种信号提醒用户,但这个不是对 Telnet 进程实现者的要求。

    Telnet 的对称性设计要求在 Telnet 连接的每个端都必须有一个 NVT,至少在概念上是这样。

STANDARD REPRESENTATION OF CONTROL FUNCTIONS - 控制功能的标准展示 #

如在前文「设计目的」中所述,Telnet 是为了提供一个标准的方法,该方法定义了 terminal 设备的接口和处理进程。在 Telnet 之前,早期的互联网络经验表明,特定的功能往往由 server 实现,但调用这些方法的差异很大,体验是令人沮丧的。因此 Telnet 定义了其中五个功能的标准表示,这些标准展示定义了标准,但不是必须的(除了 IP 进程中断)。

  • Iterrupt Process (IP)

    user 确定用户进程处于无休止的循环中,或者无意中激活了不需要的进程时,需要使用此功能。IP 是调用此函数的标准表示。

  • Abort Output (AO)

    该功能允许产生输出数据的进程继续运行到完成但是不将输出发送到任何用户终端,所以其实该功能也可以用于清除已经产生但还没有打印到用户终端的任何输出。AO 是调用此函数的标准表示。

    例如,某些子系统通常会接受用户的命令,向用户的终端发送一个长文本字符串作为响应,最后通过发送 “prompt” 字符(以 <CR><LF> 开头)表示准备好接受下一个命令到用户的终端。如果在文本串的传输过程中收到了 AO ,一个合理的实现是抑制文本串的其余部分,但传输 prompt 字符和前面的 <CR><LF> 。 (这可能与收到 IP 时可能采取的行动有所不同; IP 可能会导致文本字符串被抑制并退出子系统)

    需要注意的是,如果是 server 提供了 AO 功能,可能存在外部缓冲区 (in the network and the user’s local host) 需要被清除。执行此操作的合适方式是传输 Synch 信号到用户系统。

  • Are You There (AYT)

    该功能为用户提供了一个可见的(可打印)表现方式证明系统仍然在运行。当系统意外静默很长时间时(可能因为意外的长时间的计算、负载过高等原因)用户可能会调用此功能。AYT 是调用此函数的标准表示。

  • Erase Character (EC)

    该功能提供了从用户的输入数据中删除最后一个未删除字符(或打印位置)的功能,这个功能通常用于编辑错误的键盘输入。 RC 是调用此函数的标准表示。

    打印位置 可能包含多个字符,这些字符是 overstrikes 的结果,或者是 <char1> BS <char2>… 等序列的结果。

  • Erase Line (EL)

    该功提供了可以删除当前输入行中所有数据的功能,通常用于编辑键盘输入。EL 是调用此函数的标准表示。

THE TELNET “SYNCH” SIGNAL - 同步信号 #

大多数分时系统都提供允许终端用户重新控制失控进程的机制,上述 IPAO 功能就是这些机制的示例。此类系统在本地使用时,可以访问用户提供的所有信号,无论是普通字符还是特殊的 out-of-band 信号,例如由电传 “BREAK” 键或 IBM 2741 “ATTN” 键提供的信号。当终端通过网络连接到系统时,情况不一定如此;网络的流量控制机制可能会导致这种信号在其他地方缓冲,例如在 userhost 中。

为了解决这个问题,Telnet 引入了 Synch 机制。~Synch~ 信号由 TCP Urgent notification 和 Telnet 命令 DATA MARK 组成。Urgent notification 不受与 Telnet 连接有关的流控制的约束,用于接收它的进程调用对数据流的特殊处理。在这种模式下,接受到 Urgent notification 的进程需要立即扫描数据流中定义的 “interesting” 信号,丢弃中间数据。Telnet 命令 DATA MARK (DM) 是数据流中的同步标记,表示任何特殊信号已经发生,紧急处理已经结束,接收方可以返回数据流的正常处理。

  1. 通过 TCP 发送 Urgent notification
  2. Urgent notification 接受者立即扫描数据,找到数据流中定义的 "interesting" 信号,并对数据做对应的特殊处理
  3. 持续特殊处理数据,直到收到 Telnet DATA MARK 命令

注意: Synch 是通过 TCP 发送的,设置了 Urgent flag, DM 作为最后一个(或唯一的)八位字节数据。

一些 Synch 处理的注意事项:

  • 当多个 Synch 快速连续发送时,Urgent notification 可能会合并。由于收到的数量将小于或等于发送的数量,因此无法计算 Urgent notification 的数量。在正常模式下 DM 为无操作;当处于紧急模式时,它表示紧急处理的结束
  • 如果在接受到 DM 之前 TCP 标记 Urgent 数据结束,Telnet 应该继续对数据流进行特殊处理,直到接受到 DM
  • 如果接受到 DM 后 TCP 标记更多的 Urgent 数据,那只能是因为后续的 Synch, Telnet 应该继续对数据流进行特殊处理,直到接受到另一个 DM

Interesting 信号的定义是:

  • 标准控制功能,IP、AO 和 AYT(但不是 EC 或 EL)
  • 实现了类似控制功能的类似表示物
  • 所有其他 Telnet 命令
  • 可以在不延迟数据流扫描的情况下对其进行操作的其他 site-defined signals (新名词真多,但又不解释)

由于 Synch 机制的一个效果是丢弃同步发送者与其接收者之间的所有字符(Telnet 命令除外),因此该机制被指定为在需要时清除数据路径的标准方法。例如,如果终端上的用户导致传输 AO, 则接收 AOserver (如果它提供该功能) 应该向 user 返回 Synch.

最后,正如在 Telnet 级别需要 TCP Urgent notification 作为 out-of-band 信号一样,使用 Telnet 的其他协议可能需要 Telnet 命令,该命令在不同的层次可以被视为 out-of-band 信号。按照惯例,序列 [IP, Synch] 将用作为这样的信号。例如,假设某个使用 Telnet 的其他协议将字符串 STOP 定义为类似于 Telnet 命令 AO 。想象一下,这个协议的用户希望服务器处理 STOP 字符串,但连接被阻止,因为服务器正在处理其他命令。用户应指示他的系统:

  1. Send the Telnet IP character;
  2. Send the Telnet Synch sequence, that is: Send the DM as the only character in a TCP urgent mode send operation;
  3. Send the character string STOP;
  4. Send the other protocol’s analog of the TELNET DM, if any.

用户(或代表他的进程)必须传输上面第 2 步的 Telnet Synch 序列,以确保 Telnet IP 能够通过服务器的 Telnet 解释器。