第八章 点对点协议
8.1 揭开P字母
正像SLIP一样,PPP是在串行连接上发送数据报的协议,但却改进了前者的几个不足之处。它
让通信的双方在开始时协商诸如IP地址和最大数据报大小等选项,并且为客户提供授权(权
限)。对于每个这样的功能,PPP都有一个独立的协议。下面,我们将概要地讨论PPP的这些
基本创建框图。这里的讨论远不是完整的;如果你想对PPP知道的更多些,极力推荐你阅读R
FC-1548中它的规格说明,以及许多相关的RFCs。[1]
PPP的最底层是高级数据链路控制协议(High-Level Data Link Control Protocol),缩写
为HDLC,[2] 它定义了单个PPP帧的分界,并提供了16比特的检查和。相对于非常原始的SLI
P包装来说,一个PPP帧能够容纳除IP以外的其它协议,如Novell的IPX、或Appletalk。PPP通
过在基本的HDLC帧上加上一个协议字段来做到这功能,这个字段用于识别帧所携带的包的类
型。
LCP,链路控制协议(the Link Control Protocol),用于HDLC的上层,用于协商适合于数
据链路的选项,如指出链路的一边同意接收的最大数据报大小的最大接收单元(MRU)。
在PPP连接的配置阶段重要的一步是客户授权(权限)。尽管不是强制的,但对于拨号线路几
乎是必要的。通常,被呼叫的主机(服务器)通过验证客户是否知道某个秘密的键值来要求
客户认证自己。如果呼叫者不能给出正确的秘密键值,连接就中断了。使用PPP,授权工作是
双方面的;也即,呼叫者也可以要求服务器认证自己。这些认证过程对于双方是完全独立的
。对于不同的认证类型有两个协议,我们将在下面更进一步地讨论。它们被命名为口令认证
协议(Password Authentication protocol),或PAP和质询握手认证(Challenge Handsha
ke Authentication Protocol),或CHAP。
路由通过数据链路的每一个网络协议,如IP、Appletalk等等,使用相应的网络控制协议(N
etwork Control Protocol)(NCP)被动态地配置。例如,要通过链路发送IP数据报,PPP的
双方首先必须协商双方使用的IP地址。用于此目的的控制协议是IPCP,即互连网协议控制协
议(Internet Protocol Control Protocol)。
除了通过链路发送标准的IP数据报,PPP也支持IP数据报的Van Jacobson头压缩。这是一项将
TCP包头缩小到仅有三个字节的技术。它也用于CSLIP,并且常常通俗地称为VJ头压缩。是否
使用压缩同样可以在开始时通过IPCP协商来决定。
8.2 Linux上的PPP
在Linux中,PPP的功能被分成了两个部分,一个是位于内核的低级的HDLC驱动程序部分,另
一部分是处理各种控制协议的用户空间的pppd后台程序。Linux的PPP当前发行版是linux-pp
p-1.0.0,包含有内核PPP模块、pppd、和一个用于拨号至远程系统的称为chat的程序。
PPP内核驱动程序是由Michael Callahan编制的。pppd源自于为Sun和386BSD机器的一个免费
PPP实现,它是由Drew Perkins和其他人编制的,并且由Paul Mackerras维护。是由Al Long
year[3] 移植到Linux上的。chat是由Karl Fox编制的。[4]
正如SLIP,PPP是通过一个特殊的线路规程来实现的。要以PPP连接使用某个串行线路,你首
先要象往常那样通过modem建立一个连接,随后将线路转换成PPP模式。在这种模式下,所有
的进入的数据都传给了PPP驱动程序,该驱动程序检查传入的HDLC帧的有效性(每个HDLC帧带
有一个16比特的检验和),并且解开并分发它们。目前,它能够处理IP数据报,可选地使用
Van Jacobson头压缩。为了支持IPX,PPP驱动程序也将被扩展成能处理IPX包。
内核的驱动程序是由pppd,PPP后台程序,协助工作的,在实际的网络通信能在链路上进行之
前,它执行必要的整个初始化和认证过程。pppd的行为可以使用一些选项来调整。由于PPP非
常复杂,不可能在一章中解释所有的东西。因此本书不打算涵盖pppd的所有方面,而只是给
你一个介绍。详细信息,请参考在线手册页和pppd原始发行版中的READMEs,它将帮助解决在
这章中没有讨论过的大多数问题。如果在阅读了所有的文档之后你的问题还没有得到解决,
你应该到新闻组comp.protocols.ppp寻求帮助,在那里你可以接触到包括pppd开发者的大多
数人。
8.3 运行pppd
当你想通过一个PPP连接连到Internet上,你必须设置好基本的网络功能,如回送设备和解析
器。这两者已在前面章节中讨论过了。还有些有关在串行链路上使用DNS的解释;请参考SLI
P一章中对此的描述。
作为一个使用pppd如何建立一个PPP连接的入门例子,假设你再次在vlager。你已经拨号到P
PP服务器,c3po,并且登录进ppp帐号。c3po已经启动它的PPP驱动程序。在退出用于拨号的
通信程序以后,你执行下面的命令:
# pppd /dev/cua3 38400 crtscts defaultroute
这会将串行线路cua3转换到PPP模式并建立一个到c3po的IP连接。用于串行端口的传输速度将
是38400bps。crtscts选项打开端口的硬件握手功能,这对于高于9600bps的速度是绝对必要
的。
在启动之后pppd所做的首件事情是使用LCP与远端协商几种连接特性,通常,pppd所试用的缺
省的选项集将能工作,所以我们不打算在这里考虑这些。我们将在后面几节中再回过来详细
讨论LCP。
此时,我们也假设c3po不需要从我们这边取得任何认证,所以配置阶段成功地完成了。
然后pppd将使用IPCP,IP控制协议,与它的对等点协商IP参数。由于上面我们没有对pppd指
定任何特殊的IP地址。它将试着使用通过解析器查找本地主机名获得的地址。此后,两者将
向对方宣告他们的地址。
通常,这些缺省设置并没有什么错误。即使你的机器是在一个以太网上,你可以对以太网和
PPP接口使用同一个IP地址。当然,pppd允许你使用不同的地址,或者请求对方使用某个特定
的地址。这些选项将在以后章节中描述。
在通过了IPCP设置阶段以后,pppd将准备你的主机的网络层来使用PPP连接。它首先配置PPP
网络接口作为一个点对点连接,对第一个活动的PPP连接使用ppp0,对第二个使用ppp1,依次
类推。下一步,它将设置一个指向链路另一端主机的路由表条目。在上面示出的例子中,pp
pd将使得缺省网络路由指向c3po,因为我们已给它defaultroute选项。[5] 这使得所有到不
在本地网络上主机的数据报都被发送到c3po。pppd还支持几个不同的路由选择方案,这将在
本章后面详细讨论。
8.4 使用选项文件
在pppd分析它的命令行参数之前,为了查找缺省选项它扫描几个文件。这些文件可能含有有
效的命令行参数,它们分布在任意的行上。注释语句是由“#”开头的。
第一个选项文件是/etc/ppp/options,当pppd启动时总会扫描它。使用它设置一些全局缺省
值是个好主意,因为它允许你阻止你的用户做某些危及安全的事情。例如,要使得pppd要求
对方某种授权认证(PAP或CHAP),你应该在该文件中加入auth选项。用户覆盖不了这个选项
,所以与不在我们的授权数据库中的任何系统建立一个PPP连接变成不可能的事。
在/etc/ppp/options文件以后读取的其它选项文件,是用户主目录中的.ppprc。它允许每个
用户指定她自己的缺省选项集。
一个样本/etc/ppp/options文件可以是象这样的:
# Global options for pppd running on vlager.vbrew.com
auth # require authentication
usehostname # use local hostname for CHAP
lock # use UUCP-style device locking
domain vbrew.com # our domain name
这些选项的头两个用于权限认证并且将在下面给出解释。lock关键字使得pppd遵守标准的UU
CP设备锁定方法。根据这个惯例,每个访问串行设备的进程,如/dev/cua3,在UUCP spool目
录中创建一个名为LCK..cua3的锁定文件,用于指示该设备正在使用。这是避免任何其它程序
如minicom或uucico去打开PPP正在使用的串行设备。
在全局配置文件中提供这些选项的原因是如上显示的那些选项是不能被覆盖掉的,因而提供
了一个合理的安全级。然而,请注意有些选项可以在后面被覆盖掉;这样的一个例子是conn
ect串。
8.5 使用chat拨出
在上例中让你感到不便的事情之一是在你能够启动pppd之前必须手工地建立连接。不象dip,
pppd对于拨号至远程系统以及登录没有自己的脚本语言,而是需要依赖于某些外部程序或sh
ell脚本来做这些事。要执行的命令可以用connect命令行选项给予pppd。pppd将重定向该命
令的标准输入和输出到串行线路上。针对此一个有用的程序是expect,是由Don Libes编写的
。它有一个基于Tcl的非常强大的语言,并且是针对此类应用明确地设计出来的。
pppd软件包带有一个同样称为chat的程序,是用于指定UUCP-风格的会话脚本的。基本上说,
一个会话脚本是由我们期望从远程系统收到的交互式的字符串序列以及我们所发送的应答字
符串序列。我们将分别称之为期望字符串和发送字符串。这是从一个典型会话脚本中的摘录
:
ogin: b1ff ssword: s3kr3t
这告诉chat等待远程系统发送来登录提示,并且返回登录名b1ff。我们只是等待ogin: 所以
登录提示是大写还是小写没什么关系,也不用管它是否完全正确。接下来的又是一个期望字
符串它使得chat等待口令输入提示,并且随后发出你的口令。
这基本上,上面是chat脚本所要做的。当然,拨号