Skip to main content

3. Remote Login - TELNET Protocol (远程登录 - TELNET协议)

3.1 引言 (INTRODUCTION)

Telnet是用于远程登录的标准互联网应用协议。它提供编码规则,将客户端("用户")系统上的用户键盘/显示器与远程服务器系统上的命令解释器链接起来。Telnet协议的子集也被纳入其他应用协议中,例如FTP和SMTP。

Telnet使用单个TCP连接,其正常数据流("网络虚拟终端"或"NVT"模式)是7位ASCII,带有嵌入控制功能的转义序列。Telnet还允许协商许多可选模式和功能。

主要的Telnet规范可在RFC-854 [TELNET:1]中找到,而选项在许多其他RFC中定义;参见第7节的参考文献。

3.2 协议详解 (PROTOCOL WALK-THROUGH)

3.2.1 选项协商 (Option Negotiation): RFC-854, pp. 2-3

每个Telnet实现都必须 (MUST) 包含选项协商和子协商机制 [TELNET:2]。

主机必须 (MUST) 仔细遵循RFC-854的规则以避免选项协商循环。主机必须 (MUST) 拒绝(即对DO/WILL回复WONT/DONT)不支持的选项。选项协商应该 (SHOULD) 在Telnet连接的整个生命周期内继续正常工作(即使所有请求都被拒绝)。

如果所有选项协商都失败,Telnet实现必须 (MUST) 默认并支持NVT。

讨论:

尽管更复杂的"终端"和支持选项协商正在成为常态,但所有实现都必须准备好为任何用户-服务器通信支持NVT。

3.2.2 Telnet前进功能 (Telnet Go-Ahead Function): RFC-854, p. 5, and RFC-858

在从不发送Telnet命令Go Ahead (GA)的主机上,Telnet服务器必须 (MUST) 尝试协商抑制前进选项(即发送"WILL Suppress Go Ahead")。用户或服务器Telnet必须 (MUST) 始终接受抑制前进选项的协商。

当它驱动GA对其没有意义的全双工终端时,用户Telnet实现可以 (MAY) 忽略GA命令。

讨论:

为其设计前进机制的半双工("锁定键盘")逐行终端已基本从场景中消失。事实证明,在许多操作系统中实现发送前进信号是困难的,即使是一些支持本地半双工终端的系统。困难通常在于Telnet服务器代码无法访问有关用户进程是否正在等待来自Telnet连接的输入的信息,即它无法可靠地确定何时发送GA命令。因此,大多数Telnet服务器主机不发送GA命令。

本节中规则的效果是允许Telnet连接的任一端否决GA命令的使用。

仍有一类半双工终端在商业上很重要:"数据输入终端",它以全屏方式进行交互。但是,使用Telnet协议支持数据输入终端不需要前进信号;参见第3.3.2节。

3.2.3 控制功能 (Control Functions): RFC-854, pp. 7-8

Telnet命令列表已扩展为包括EOR(记录结束),代码为239 [TELNET:9]。

用户和服务器Telnet都可以 (MAY) 支持控制功能EOR、EC、EL和Break,并且必须 (MUST) 支持AO、AYT、DM、IP、NOP、SB和SE。

主机必须 (MUST) 能够接收并忽略它不支持的任何Telnet控制功能。

讨论:

请注意,即使服务器主机具有等效的流内功能(例如许多系统中的Control-C),也要求服务器Telnet支持Telnet IP(中断进程)功能。由于TCP紧急数据的带外效果,Telnet IP功能可能比流内中断命令更强。

EOR控制功能可用于分隔流。一个重要的应用是数据输入终端支持(参见第3.3.2节)。有人担心由于EOR未在RFC-854中定义,未准备好正确忽略未知Telnet命令的主机可能会在收到EOR时崩溃。为了保护此类主机,引入了记录结束选项[TELNET:9];但是,正确实现的Telnet程序不需要此保护。

3.2.4 Telnet "同步"信号 (Telnet "Synch" Signal): RFC-854, pp. 8-10

当接收到"紧急"TCP数据时,用户或服务器Telnet必须 (MUST) 丢弃除Telnet命令之外的所有数据,直到到达DM(和紧急结束)。

当发送Telnet IP(中断进程)时,用户Telnet应该 (SHOULD) 在其后跟随Telnet"同步"序列,即将序列"IAC IP IAC DM"作为TCP紧急数据发送。TCP紧急指针指向DM八位字节。

当接收到Telnet IP命令时,服务器Telnet可以 (MAY) 向用户发送Telnet"同步"序列,以刷新输出流。该选择应与服务器操作系统在本地用户中断进程时的行为方式一致。

当接收到Telnet AO命令时,服务器Telnet必须 (MUST) 向用户发送Telnet"同步"序列,以刷新输出流。

用户Telnet应该 (SHOULD) 具有在发送Telnet IP时刷新输出的能力;另请参见第3.4.5节。

讨论:

用户Telnet刷新服务器输出数据流有三种可能的方法:

(1) 在IP之后发送AO。

这将导致服务器主机向其操作系统发送"刷新缓冲输出"信号。但是,AO可能不会在本地生效,即在用户Telnet端停止终端输出,直到服务器Telnet接收并处理AO并发回"同步"。

(2) 在IP之后发送DO TIMING-MARK [TELNET:7],并在本地丢弃所有输出,直到从服务器Telnet接收到WILL/WONT TIMING-MARK。

由于DO TIMING-MARK将在服务器上的IP之后处理,因此对它的回复应该在输出数据流中的正确位置。但是,TIMING-MARK不会向服务器操作系统发送"刷新缓冲输出"信号。是否需要这取决于服务器系统。

(3) 两者都做。

最佳方法并不完全清楚,因为它必须适应许多以各种方式不遵循Telnet标准的现有服务器主机。最安全的方法可能是提供用户可控的选项来选择(1)、(2)或(3)。

3.2.5 NVT打印机和键盘 (NVT Printer and Keyboard): RFC-854, p. 11

在NVT模式下,Telnet不应该 (SHOULD NOT) 发送高位为1的字符,并且不得 (MUST NOT) 将其作为奇偶校验位发送。将高位传递给应用程序的实现应该 (SHOULD) 协商二进制模式(参见第3.2.6节)。

讨论:

实现者应该意识到,严格阅读RFC-854允许期望NVT ASCII的客户端或服务器忽略设置了高位的字符。通常,二进制模式预期用于使用Telnet传输扩展(超过7位)字符集。

但是,确实存在真正需要8位NVT模式的应用程序,该模式当前未定义,这些现有应用程序确实在Telnet连接生命周期的部分或全部期间设置高位。请注意,二进制模式与8位NVT模式不同,因为二进制模式关闭行尾处理。因此,对高位的要求被声明为SHOULD,而不是MUST。

RFC-854定义了"网络虚拟终端"或NVT的最小属性集;这并不意味着排除真实终端中的其他功能。Telnet连接对所有7位ASCII字符(包括任意ASCII控制字符)完全透明。

例如,终端可能支持编码为ASCII转义序列的全屏命令;Telnet实现会将这些序列作为未解释的数据传递。因此,NVT不应被视为高度受限设备的终端类型。

3.2.6 Telnet命令结构 (Telnet Command Structure): RFC-854, p. 13

由于选项可能出现在数据流中的任何位置,因此要作为数据发送的Telnet转义字符(称为IAC,值为255)必须 (MUST) 加倍。

3.2.7 Telnet二进制选项 (Telnet Binary Option): RFC-856

当成功协商二进制选项时,允许任意8位字符。但是,仍然必须 (MUST) 扫描数据流以查找IAC字符,必须 (MUST) 遵守任何嵌入的Telnet命令,并且必须 (MUST) 将等于IAC的数据字节加倍。不得 (MUST NOT) 进行其他字符处理(例如,将CR替换为CR NUL或CR LF)。特别是,在二进制模式下没有行尾约定(参见第3.3.1节)。

讨论:

二进制选项通常在两个方向上协商,以将Telnet连接从NVT模式更改为"二进制模式"。

序列IAC EOR可用于在二进制模式Telnet流中分隔数据块。

3.2.8 Telnet终端类型选项 (Telnet Terminal-Type Option): RFC-1091

终端类型选项必须 (MUST) 使用已分配编号RFC [INTRO:5]中正式定义的终端类型名称,当它们可用于特定终端时。但是,终端类型选项的接收方必须 (MUST) 接受任何名称。

讨论:

RFC-1091 [TELNET:10]更新了RFC-930中定义的终端类型选项的早期版本。早期版本允许能够支持多种终端类型的服务器主机了解特定客户端终端的类型,假设每个物理终端都有一个固有类型。但是,今天的"终端"通常实际上是在PC中运行的终端仿真器程序,可能能够仿真一系列终端类型。因此,RFC-1091扩展了规范,以允许用户和服务器Telnet之间进行更通用的终端类型协商。

3.3 特定问题 (SPECIFIC ISSUES)

3.3.1 Telnet行尾约定 (Telnet End-of-Line Convention)

Telnet协议将序列CR LF定义为"行尾"。对于终端输入,这对应于在用户终端上按下命令完成或"行尾"键;在ASCII终端上,这是CR键,但它也可能标记为"Return"或"Enter"。

当服务器Telnet从远程终端接收Telnet行尾序列CR LF作为输入时,其效果必须 (MUST) 与用户在本地终端上按下"行尾"键的效果相同。特别是在使用ASCII的服务器主机上,接收Telnet序列CR LF必须导致与本地用户在本地终端上按CR键相同的效果。因此,当通过Telnet连接作为输入接收时,CR LF和CR NUL必须 (MUST) 对ASCII服务器主机具有相同的效果。

用户Telnet必须 (MUST) 能够发送任何形式:CR LF、CR NUL和LF。ASCII主机上的用户Telnet应该 (SHOULD) 具有用户可控的模式,以在用户按下"行尾"键时发送CR LF或CR NUL,并且CR LF应该 (SHOULD) 是默认值。

Telnet行尾序列CR LF必须 (MUST) 用于发送非终端到计算机的Telnet数据(例如,用于发送输出的服务器Telnet,或纳入另一个应用协议的Telnet协议)。

讨论:

为了允许任意Telnet客户端和服务器之间的互操作性,Telnet协议为行终止符定义了标准表示。由于ASCII字符集不包含显式的行尾字符,系统选择了各种表示,例如CR、LF和序列CR LF。Telnet协议选择CR LF序列作为网络传输的标准。

不幸的是,RFC-854 [TELNET:1]中的Telnet协议规范在从客户端发送到服务器的"行尾"键应该发送什么字符方面已被证明有些模糊。结果是一个巨大且持续的互操作性难题,由用户和服务器Telnet的各种错误实现使情况变得更糟。