----------------------- Page 1-----------------------
第26章 Telnet和Rlogin:远程登录
26.1 引言
远程登录(Remote Login )是I n t e r n e t上最广泛的应用之一。我们可以先登录(即注册)
到一台主机然后再通过网络远程登录到任何其他一台网络主机上去,而不需要为每一台主机
连接一个硬件终端(当然必须有登录帐号)。
在T C P / I P网络上,有两种应用提供远程登录功能。
1) Te l n e t是标准的提供远程登录功能的应用,几乎每个T C P / I P的实现都提供这个功能。它
能够运行在不同操作系统的主机之间。Te l n e t通过客户进程和服务器进程之间的选项协商机制,
从而确定通信双方可以提供的功能特性。
2) Rlogin起源于伯克利U n i x ,开始它只能工作在U n i x系统之间,现在已经可以在其他操
作系统上运行。
在本章中,我们将介绍Te l n e t和R l o g i n 。首先介绍R l o g i n,因为R l o g i n 比较简单。
Te l n e t是一种最老的I n t e r n e t应用,起源于1 9 6 9年的A R PA N E T 。它的名字是“电信
网络协议(telecommunication network protocol )”的缩写词。
远程登录采用客户-服务器模式。图 2 6 - 1显示的是一个Te l n e t客户和服务器的典型连接图
(对于R l o g i n 的客户和服务器连接图,我们可以画得更加简单)。
图26-1 客户-服务器模式的Telnet简图
在这张图中,有以下要点需要注意:
1) Te l n e t客户进程同时和终端用户和T C P / I P协议模块进行交互。通常我们所键入的任何信
息的传输是通过T C P连接,连接的任何返回信息都输出到终端上。
2) Te l n e t服务器进程经常要和一种叫做“伪终端设备”(pseudo-terminal device )打交道,
至少在U n i x系统下是这样的。这就使得对于登录外壳 ( s h e l l )进程来讲,它是被Te l n e t服务器进
程直接调用的,而且任何运行在登录外壳进程处的程序都感觉是直接和一个终端进行交互。
对于像满屏编辑器这样的应用来讲,就像直接在和终端打交道一样。实际上,如何对服务器
进程的登录外壳进程进行处理,使得它好像在直接和终端交互,往往是编写远程登录服务器
----------------------- Page 2-----------------------
进程程序中最困难的方面之一。
3) 仅仅使用了一条T C P连接。由于客户进程必须多次和服务器进程进行通信(反之亦然),
这就必然需要某些方法,来描绘在连接上传输的命令和用户数据。我们在后面的内容中会介
绍Te l n e t和R l o g i n是如何处理这个问题的。
4) 注意在图2 6 - 1 中,我们用虚线框把终端驱动进程和伪终端驱动进程框了起来。在
T C P / I P实现中,虚线框的内容一般是操作系统内核的一部分。 Te l n e t客户进程和服务器进程一
般只是属于用户应用程序。
5) 把服务器进程的登录外壳进程画出来的目的是为了说明:当我们想登录到系统的时候,
必须要有一个帐号,Te l n e t和R l o g i n都是如此。
对于Te l n e t和R l o g i n,如果比较一下它们客户进程和服务器进程源代码的数量,就可以知
道这两者的复杂程度。图2 6 - 2显示了伯克利不同版本的Te l n e t和R l o g i n客户进程和服务器进程
源代码的数量。
图26-2 Telnet/ Rlogin/客户进程/服务器进程的源代码数量比较
现在,不断有新的Te l n e t选项被添加到Te l n e t中去,这就使得Te l n e t实现的源代码数量大大
增加,而R l o g i n依然变化不大,还是比较简单。
远程登录不是那种有大量数据报传输的应用。正如我们前面讲到的一样,客户进程和服
务器进程交互的分组大多比较小。 [Paxson 1993]发现客户进程发出的字节数(用户在终端上
键入的信息)和服务器进程端发出的字节数的数量之比是 1 : 2 0。这是因为我们在终端上键入
的一条短命令往往令服务器进程端产生很多输出。
26.2 Rlogin协议
R l o g i n 的第一次发布是在4 . 2 B S D 中,当时它仅能实现U n i x主机之间的远程登录。这就使
得R l o g i n 比Te l n e t简单。由于客户进程和服务器进程的操作系统预先都知道对方的操作系统类
型,所以就不需要选项协商机制。在过去的几年中, R l o g i n协议也派生出几种非U n i x环境的
版本。
RFC 1282 [Kantor 1991]详细说明了R l o g i n协议。类似于选路信息协议(R I P )的R F C,它
是R l o g i n用了许多年后才发布的。 [Stevens 1990]的第1 5章介绍了远程登录的客户进程及服务
器进程端的编程,并且给出了 R l o g i n 的客户进程及服务器进程的完整源代码。 [ C o m e r和
Stevens 1993]的第2 5章和第2 6章给出了Te l n e t的客户进程的实现细节和源代码。
----------------------- Page 3-----------------------
26.2.1 应用进程的启动
R l o g i n 的客户进程和服务器进程使用一个T C P连接。当普通的T C P连接建立完毕之后,客
户进程和服务器进程之间将发生下面所述的动作。
1) 客户进程给服务器进程发送4个字符串:(a)一个字节的0;(b )用户登录进客户进程主机
的登录名,以一个字节的0结束;(c)登录服务器进程端主机的登录名,以一个字节的0
结束;(d)用户终端类型名,紧跟一个正斜杠“/ ”,然后是终端速率,以一个字节的0结
束。在这里需要两个登录名字,这是因为用户登录客户和服务器的名称有可能不一样。
由于大多满屏应用程序需要知道终端类型,所以终端类型也必须发送到服务器进程。发
送终端速率的原因是因为有些应用随着速率的改变,它的操作也有所变化。例如 v i编辑
器,当速率比较小的时候,它的工作窗口也变小。所以它不能永远保持同样大小的窗口。
2) 服务器进程返回一个字节的0 。
3) 服务器进程可以选择是否要求用户输入口令。这个步骤的数据交互没有什么特别的协
议,而被当作是普通的数据进行传输。服务器进程给客户进程发送一个字符串(显示
在客户进程的屏幕上),通常是password: 。如果在一定的限定时间内(通常是 6 0秒)
客户进程没有输入口令,服务器进程将关闭该连接。
通常可以在服务器进程的主目录(home directory)下生成一个文件(通常叫 . r h o s t s),该
文件的某些行记录了一个主机名和用户名。如果从该文件中已经记录的主机上用已经
记录的用户名进行登录,服务器进程将不提示我们输入口令。但是很多关于安全性的
文献,如[Curry 1992],强烈建议不要采用这种方法,因为这存在安全漏洞。
如果提示输入口令,那么我们输入的口令将以明文的形式发送到服务器进程。我们所
键入的每个字符都是以明文的格式传输的。所以某人只要能够截取网络上的原始传输
的分组,他就可以截获用户口令。针对这个问题,新版本的 R l o g i n客户程序,例如
4 . 4 B S D版本的客户程序,第一次采用了 K e r b e r o s安全模型。K e r b e r o s安全模型可以避
免用户口令以明文的形式在网络上传输。当然,这要求服务器进程也支持 K e r b e r o s
([Curry 1992]详细描述了K e r b e r o s安全模型)。
4) 服务器进程通常要给客户进程发送请求,询问终端的窗口大小(将在后面解释)。
客户进程每次给服务器进程发送一个字节的内容,并且接收服务器进程的所有返回信息。
这在1 9 . 2节中已经介绍过了。同样我们也采用了N a g l e算法(在1 9 . 4节中曾经介绍),该算法可
以保证在速率较低的网络上,若干输入字节以单个 T C P报文段传输。操作其实很简单:用户
键入的所有东西被发送到服务器,服务器发送给客户的任何信息返回到用户的屏幕上。
另外,服务器和客户之间还可以互相发送命令。在介绍这些命令之前,先介绍需要用到
这些命令的场合。
26.2.2 流量控制
默认情况下,流量控制是由 R l o g i n 的客户进程完成的。客户进程能够识别用户键入的
S TO P和S TA RT的A S C I I字符(C o n t r o l S和C o n t r o l Q ),并且终止或启动终端的输出。
_ _
如果不是这样,每次我们为终止终端输出而键入的 C o n t r o l _ S字符将沿网络传输到服务器
进程,这时服务器进程将停止往网络上写数据。但是在写操作终止之前,服务器进程可能已
经往网络上写了一窗口的输出数据。也就是说,在输出停止之前,成千上万的数据字节还将
----------------------- Page 4-----------------------
在屏幕上显示。图2 6 - 3显示了这个情况。
图26-3 服务器进程执行STOP/START的情况
对于一个交互式用户来讲,C o n t r o l _ S字符的响应延时是较大的。
有时候,服务器的应用程序需要解释输入的每个字节,但又不想让客户对它的输入内容
进行处理,例如对控制字符如 C o n t r o l _ S和C o n t r o l _ Q进行特殊处理(e m a c s编辑器就是这样的
一个例子,它把C o n t r o l _ S和C o n t r o l _ C作为自己的命令)。解决这个问题的办法就是由服务器
告诉客户是否要进行流量控制。
26.2.3 客户的中断键
当我们为中断服务器正在运行的进程而键入一个中断字符时(通常是 D E L E T E 或
C o n t r o l _ C ),会发生和流量控制相同的问题。这个情况和图 2 6 - 3所示的类似,在一条T C P连接
的管道上,从服务器进程向客户进程正在发送大量的数据,而客户进程同时在向服务器进程传
输中断字符。而我们的本意是要中断字符尽快终止某个进程,使屏幕上不再有任何响应输出。
在流量控制和中断键这两种情况中,流量控制机制很少终止客户进程到服务器进程的数
据流。这个方向仅仅包含我们键入的字符。所以对于从客户输出到服务器的特殊输入字符
(C o n t r o l _ S和中断字符)不需要采用T C P的紧急方式(u rgent mode )。
26.2.4 窗口大小的改变
如果是窗口风格的显示方式,当应用程序在运行的时候,我们还可以动态地改变窗口的
大小。一些应用程序(典型的如那些操作整个窗口的应用程序,如全屏编辑器)需要知道窗
口大小的变化。目前大多数U n i x系统提供这种功能,可以告诉应用程序关于窗口大小的变化。
对于远程登录这种情况,窗口大小的变化发生在客户端,而运行在服务器端的应用程序
需要知道窗口大小变化。所以 R l o g i n 的客户需要采用某些方法来通知服务器窗口大小变化的
情况以及新窗口的大小。
26.2.5 服务器到客户的命令
现在我们介绍通过T C P连接,R l o g i n服务器进程可以发送给客户进程的 4条命令。问题是
只有一条T C P连接可供使用,所以服务器进程必须给这些命令字节做标记,使得客户进程可
以从数据流中识别出这些是命令,而不是显示在终端上。所以我们将使用 T C P 的紧急方式
(在2 0 . 8节中曾经介绍)。
当服务器要给客户发送命令时,服务器就进入紧急方式,并且把命令放在紧急数据的最
后一个字节中。当客户进程收到这个紧急方式通知时,它从连接上读取数据并且保存起来,
直到读到命令字节(即紧急数据的最后一个字节)。这时候客户进程根据读到的命令,再决定
对于所读到并保存起来的数据是显示在终端上还是丢弃它。图 2 6 - 4介绍了这4个命令。
采用T C P紧急方式发送这些命令的一个原因是第一个命令(“清仓输出(flush output) ”)需
要立即发送给客户,即使服务器到客户的数据流被窗口流量控制所终止。这种情况下,即服
----------------------- Page 5-----------------------
务器到客户的输出被流量控制所终止的情况是经常发生的,这是因为运行在服务器的进程的
输出速率通常大于客户终端的显示速率。另一方面,客户到服务器的数据流很少被流量控制
所终止,因为这个方向的数据流仅仅包含用户所键入的字符。
图26-4 服务器到客户的Rlogin命令
回忆一下图2 0 - 1 4 中的例子,在那里我们介绍了即使窗口大小是 0时,紧急通知通过网络
进行传输的情况(在下节中,我们还将介绍一个类似的例子)。其他的3个命令实时性并不特
别强,但为了简单起见,也采用了和第一个命令相同的技术。
26.2.6 客户到服务器的命令
对于客户到服务器的命令,只定义了一条命令,那就是:将当前窗口大小发送给服务器。
当客户的窗口大小发生变化时,客户并不立即向服务器报告,除非收到了服务器发来的 0 x 8 0
命令(图2 6 - 4 中有介绍)。
同样,由于只存在一条T C P连接,客户必须对在连接上传输的该命令字节进行标注,使
得服务器可以从数据流中识别出命令,而不是把它发送到上层的应用程序中去。处理的方法
就是在两个字节的0 x ff后面紧跟着发送两个特殊的标志字节。
对于窗口大小命令,两个标志字节是A S C I I码的字符‘s ’。之后是4个16 bit长的数据(按
网络字节顺序),分别是:行数(例如,2 5 ),每列的字符数(例如,8 0),X方向的像素数量,
Y方向的像素数量。通常情况下,后两个 1 6 b i t是0,因为在R l o g i n服务器进程调用的应用程序
中,通常是以字符为单位来度量屏幕的,而不是像素点。
上面我们介绍的从客户进程到服务器进程的命令采用带内信令( in-band signaling ),这是
因为命令字节和其他的普通数据一起传输。选择0 x ff字节来表示这个带内信令的原因是:一般
用户的操作不会产生0 x ff这个字节。所以说R l o g i n是不完备的,如果我们采用某种方法,使得
通过键盘就可以产生两个连续的 0 x ff字节,而且正好在这之前是两个 A S C I I 的‘s ’字符,那
么下面的8个字节就会被误认为是窗口大小了。
图2 6 - 4 中介绍的是从服务器到客户的R l o g i n命令,由于大多数的A P I采用的技术叫做“带
外数据(out-of-band data )”,所以我们就称它为带外信令(out-of-band signaling) 。但是回忆一
下在2 0 . 8节中对T C P紧急方式的讨论,在那里我们说紧急方式数据不是带外数据,命令字节是
按照普通数据流进行传输的,特殊之处是采用了紧急指针。
既然带内信令被用来传输从客户到服务器的命令,那么服务器进程必须检查从客户进程
收到的每个字节,看看是否有两个连续的 0 x ff字节。但是对于采用带外信令的、从服务器传
输到到客户的命令,客户进程不需要检查收到的每个字节,除非服务器进程进入了紧急方
----------------------- Page 6-----------------------
式。即使在紧急方式下,客户进程也仅仅需要留意紧急指针所指向的字节。而且由于从客
户进程到服务器的数据流量和相反方向的数据流量之比是 1 : 2 0,这就暗示带内信令适合于数
据量比较小的情况(从客户到服务器),而带外信令适合于数据量比较大的情况(从服务器
到客户)。
26.2.7 客户的转义符
通常情况下,我们向R l o g i n客户进程键入的信息将传输到服务器进程。但是有些时候,我
们并不需要把键入的信息传输到服务器,而是要和 R l o g i n客户进程直接通信。方法是在一行
的开头键入代字符( t i l d e ) “~ ”,紧跟着是下列4个字符之一:
1) 以一个句号结束客户进程。
2) 以文件结束符(通常是C o n t r o l _ D )结束客户进程。
3) 以任务控制挂起符(通常是C o n t r o l _ Z )挂起客户进程。
4) 以任务控制延迟挂起符(通常是C o n t r o l _ Y)来挂起仅仅是客户进程的输入。这时,不
管客户运行什么程序,键入的任何信息将由该程序进行解释,但是从服务器发送到客户的信
息还是输出到终端上。这非常适合当我们需要在服务器上运行一个长时间程序的场合,我们
既想知道该程序的输出结果,同时还想在客户上运行其他程序。
只有当客户进程的U n i x系统支持任务控制时,后两个命令才有效。