Linux网络管理员手册(7)
翻译:赵炯
[email protected]
第七章 串行线路IP
串行线路协议SLIP和PPP为资金缺乏者提供Internet连接。除了需要一个modem和一块配有FIFO缓冲的串行板(卡)外,不再需要其它的硬件了。使用它并不比使用一个邮箱复杂,并且不断增长的私人机构以可以接受的价格为大家提供拨号上网IP。
Linux有SLIP和PPP两种驱动程序。SLIP已存在相当长的时间了,并且工作的很稳定。PPP驱动程序是由Michael Callahan and Al Longyear最近开发的。PPP将在下一章中讨论。
7.1 一般需求
要使用SLIP或PPP,你当然必须配置一些如前章所讨论的那些基本网络特性。起码,你必须设置回送(loopback)接口,并且提供名字解析。当连接到Internet上时,你当然要用到DNS。最方便的方法是将某个名字服务器的地址写入resolv.conf文件中;SLIP链接一旦被激活,就会查询这个服务器。名字服务器离你拨入的地方越近越好。
然而,这个方法并不是最佳的,因为所有的名字查找仍然都要通过你的SLIP/PPP链接。如果你担心这样做所耗费的带宽,你也可以设置一个只缓冲(caching-only)名字服务器。它并不真的服务于一个域,而只是作为你的主机所产生的所有DNS查询的一个中继。这个方案的优点在于它建立了一个缓冲,大多数的查询只需往串行线路上发送一次。一个只缓冲服务器的named.boot文件看上去象这样:
; named.boot file for caching-only server
directory /var/named
primary 0.0.127.in-addr.arpa db.127.0.0 ; loopback net
cache . db.cache ; root servers
除了这个name.boot文件,你也还需要设置db.cache文件,其中含有有效根名字服务器的一张列表。这些在解析器的配置一章中的最后讨论。
7.2 SLIP操作
拨号(上网)IP服务器通常使用特殊的用户帐号提供SLIP服务。在登陆进这样一个帐号以后,你不会进入普通的shell程序;而是执行一个程序或shell脚本,激活串行线路的服务器SLIP驱动程序并且配置适当的网络接口。然后你需要在链接的你这端做同样的工作。
在某些操作系统上,SLIP驱动程序是用户空间程序;在Linux下,它是内核的一部分,这使得它更快一些。然而,这需要将串行线路明确地转换成SLIP模式。这是通过特殊的tty线路规程,SLIPDISC,来做到的。当tty为普通线路规程(DISCO)时,它将使用普通的read(2)和write(2)调用只与用户进程交换数据,而SLIP驱动程序不能从tty读取或写进数据。在SLIPDISC规程里,规则正好相反:现在任何用户空间进程从tty的读取和写入被阻止,此时,从串行端口来的所有数据将被直接地传递到SLIP驱动程序。
SLIP驱动程序本身可以识别SLIP协议的多种变化。除了普通的SLIP,它也能理解CSLIP,这在输出的IP包上执行所谓的Van Jacobson头压缩。[1] 这显著地改进了交互式会话的吞吐量。另外,对于这些协议的每一种有六比特的版本。
将串行线路转换为SLIP模式的一种简单方法是通过使用slattach工具。假设你的modem连在/dev/cua3上,并且成功地登录上SLIP服务器。然后执行:
# slattach /dev/cua3 &
这将cua3的线路规程转换成SLIPDISC,并把它连接到SLIP网络接口之一。如果这是你的第一次激活的SLIP链接,该线路将连至sl0;第二个将连至sl1,以此类推。目前的内核同时支持多达八个SLIP链接。
Slattach所选择的缺省的压缩封装是CSLIP。你可以使用-p开关来选择任何其它的模式。要使用常规的SLIP(无压缩的),可以使用
# slattach -p slip /dev/cua3 &
其它的模式有cslip、slip6、cslip6(SLIP的六比特版本)、以及适应性SLIP(adaptive SLIP)的adaptive。后者让内核找出远端所用的是那一种SLIP压缩封装类型。
注意,你必须使用与你的对等点同样的压缩封装。例如,如果cowslip使用CSLIP,你也必须使用它。如果选择不匹配,那么将会出现ping到远程主机将收不到任何返回信息包的现象。如果其它的主机ping你,那么在你的控制台上也会出现象“不能建立ICMP头”(“Can’t build ICMP header”)的信息。避免这些问题的一种方法是使用适应性SLIP。
实际上,slattach并不仅仅允许你使能SLIP,同样也可以激活串行线路的其它协议,如PPP或KISS(另一个由无线电爱好者使用的协议)。详细信息,请参考slattach(8)再线手册。
在将线路转至SLIP驱动程序以后,你必须配置这个网络接口。再一次,我们使用标准的ifconfig和route命令来做这个配置。假设从vlager,我们拨号到一个名为cowslip的服务器。那么你要执行
#ifconfig sl0 vlager pointopoint cowslip
# route add cowslip
# route add default gw cowslip
第一个命令将接口配置成到cowslip的点对点链接,而第二、第三个命令增加到cowslip的路由以及使用cowslip作为一个缺省的网关。
当拆卸一个SLIP链接时,你首先必须使用带del选项的route命令移去所有通过cowslip的路由,将接口关闭,并向slattch发送一个hangup信号。然后,你必须再次使用你的终端程序挂断modem:
# route del default
# route del cowslip
# ifconfig sl0 down
# kill -HUP 516
7.3 使用dip
现在来看,上面讲的是非常简单的。然而,你也许想使上面的步骤自动地执行,这样你就可以只调用一个简单的命令来执行上面给出的所有步骤了。这也就是dip所要做的。[2] 在写作这本手册时它的当前发行版本是3.3.7。它已被许多人大大地修改过了,所以它已不再是原来的dip程序了。这些不同的开发变化有希望在今后的版本中合并。
Dip为简单的脚本语言提供了一个解释器,它能为你处理modem,将线路转变为SLIP模式,并配置接口。这是非常基本的和有局限性的,但对于大多数情况已足够有效了。某天一个新的dip版本将能适用于更为广泛的语言。
为了配置SLIP接口,dip需要root权限。现在可以临时使用dip将uid置为root,因此所有的用户能够拨号到某个SLIP服务器而不需要给这些用户root权限。这是非常危险的,因为用dip设置假的接口和默认路由可能会严重地破坏网络的路由。更糟的是,这将给你的用户连接到任何SLIP服务器的能力,并在你的网络上带来危险的攻击。所以如果你想允许你的用户建立一个SLIP连接,就为每个期望的SLIP服务器写一个小的包装程序,并且让这些包装程序调用包括建立连接用的特定脚本的dip。那么,这些程序就可以安全地置成root的uid。[3]
7.3.1 一个简单的脚本程序
图7.1列出了一个简单的脚本程序。通过用脚本程序的名字作为参数调用dip,它可以用于连接cowslip:
# dip cowslip.dip
DIP: Dialup IP Protocol Driver version 3.3.7 (12/13/93)
Written by Fred N. van Kempen, MicroWalt Corporation.
connected to cowslip.moo.com with addr 193.174.7.129
#
当激活了SLIP并连接到cowslip以后,dip将从终端上脱开并运行于后台。此时你就可以在SLIP连接上使用通常的网络服务了。要想终止连接,只需用-k选项调用dip。这使用/etc/dip.pid [4]中记录的进程id dip给dip进程发送了一个挂断信号:
# kill –k
在dip的脚本语言中,前加美元符号的关键字表示变量名。Dip有一个预定义的变量集,将在下面列出。例如,$remote和$local含有与SLIP连接有关的本地以及远程主机的主机名。
# Sample dip script for dialing up cowslip
# Set local and remote name and address
get $local vlager
get $remote cowslip
port cua3 # choose a serial port
speed 38400 # set speed to max
modem HAYES # set modem type
reset # reset modem and tty
flush # flush out modem response
# Prepare for dialing.
send ATQ0V1E1X1\\r
wait OK 2
if $errlvl != 0 goto error
dial 41988
if $errlvl != 0 goto error
wait CONNECT 60
if $errlvl != 0 goto error
# Okay, we\"re connected now
sleep 3
send \\r\\n\\r\\n
wait ogin: 10
if $errlvl != 0 goto error
send Svlager\\n
wait ssword: 5
if $errlvl != 0 goto error
send hey-jude\\n
wait running 30
if $errlvl != 0 goto error
# We have logged in, and the remote side is firing up SLIP.
print Connected to $remote with address $rmtip
default # Make this link our default route
mode SLIP # We go to SLIP mode, too
# fall through in case of error
error:
print SLIP to $remote failed.
图7.1 一个dip脚本样本
样本脚本程序中的头两句是get命令,这是dip设置变量的方法。这里,本地和远程主机名分别设置成了vlager和cowslip。
接下来的五句用来设置终端线路和modem。Reset向modem发送了一个复位串;对于Hayes兼容的modem,这是个ATZ命令。下一个语句刷出modem的响应,以使得接下来的几行中的登录会话能够正常的工作。这个对话是非常直观的:它简单地拨出cowslip的号码41988,并且使用口令hey-jude登录进Svlager帐号。Wait命令使得dip等待给出的字符串作为它的第一个参数;作为第二个参数的秒数使得在这些秒数之后如果还没有收到这样的字符串时使等待超时。散布在登录过程中的If命令检查执行命令时是否有错。
在登录后最后执行的命令是default --它使得SLIP连接成为所有主机的缺省路由,和mode –它在线路上激活SLIP模式并且为你配置接口和路由选择表。
7.3.2 dip参考
尽管dip被广泛地使用着,但它至今没有很好的文档。因此在这一节,我们将给出大部分dip命令的参考。你可以使用测试模式调用dip来得到所有命令的一个概观,并且进入帮助命令。要找出一个命令的句法,你可以不加任何参数地键入它;当然这对不用参数的命令是没有效的。
DIP> help
DIP knows about the following commands:
databits default dial echo flush
get goto help if init
mode modem parity print port
reset send sleep speed stopbits
term wait
DIP> echo
Usage: echo on|off
DIP>
下面,所有显示有DIP>提示符的例子示出了如何在测试模式下输入一个命令,以及该命令所产生的输出。没有这个提示符的示例将作为脚本引用。
modem命令
dip提供了许多配置你的串行线路和modem的命令。有些是显而易见的,如port—它选择一个串行口,以及speed、databits、stopbits和parity,这些是用来设置通常的线路参数的。
modem命令用来选择一个modem类型。目前,所支持的唯一类型是HAYES(需大写)。你必须给dip提供一个modem类型,否则的话,它将拒绝执行dial和reset命令。reset命令给modem发送一复位字符串;所用的字符串依赖于选择的modem类型。对于Hayes兼容modem,它是ATZ。
flush命令用于刷新modem迄今为止所发出的所有响应。否则的话跟在reset后面的会话脚本可能会混淆,因为它会读取早些命令的OK响应。
init命令用于在拨号之前向modem选择发送一条初始化串。Hayes modem的缺省值是“ATE0 Q0 V1 X1”,它启动命令的回应和长结果代码,并且选择盲拨号(对拨号音不作检查)。
dial命令最终向modem发出初始化串并且向远程系统拨号。Hayes modem的缺省dial命令是ATD。
echo和term
echo命令是用作调试目的的,当echo on时,就会使得dip在控制台上回显发送给串行设备的所有命令信息。通过调用echo off可以再次关闭回显。
dip同样允许你暂时离开脚本模式并进入终端模式。在这种模式下,你可以象任何其它常用的终端程序那样使用dip,写至串行线路并从串行线路读取信息。要离开这种模式,键入Ctrl-]。
get命令
get命令是dip设置变量的方法。最简单的形式是将变量设置成一个常数,正如用于上面例子中的一样。然而,你也可以通过指定关键字ask代替一个值来提示用户输入:
DIP> get $local ask
Enter the value for $local:
第三种方式是试着从远程主机取得这个值,这在某些情况下是非常有用的:有些SLIP服务器不允许你在SLIP连接上使用自己的IP地址,而是在你拨入时从一个地址池中取得一个分配给你,显示出一些信息通知你有关给你分配的地址。如果该信息看上去象这样“Your address: 193.174.7.202”,那么下面一段dip代码将让你获取地址:
… login ….
wait address: 10
get $locip remote
print命令
这个命令是向dip启动的控制台上回显文字。任何dip变量都可以用于print命令中,如
DIP> print Using port $port at speed $speed
Using port cua3 at speed 38400
变量名
dip只认识一组预定义的变量。变量名总是以美元符号开头并且必须用小写字符。
$local和$locip变量含有本地主机的名字和IP地址。设置主机名使得dip将规范主机名存入$local,同时将相应的IP地址存入$locip。设置$locip也类似于设置$local。
$remote和$rmtip变量对远程主机名和地址做同样的事情。$mtu含有连接的MTU值。
这五个变量是仅有的能够使用get命令直接进行赋值的。主机的其它变量只能通过相应的命令来设置,但可以用于print语句;这些是$modem、$port和$speed。
通过$errlvl变量你可以获得上一条命令执行的结果。一个0错误号表示成功,而非零值表示有错。
if和goto命令
if命令相对于平常所称的if来说更是一个条件分支。它的语法是
if var op number goto label
这里表达式必须是与变量$errlvl、$locip、和$rmtip之一的一个简单的比较关系。第二个操作数必须是一个整数;运算符op可以是==、!=、<、>、<=、以及>=之一。
goto命令使得脚本跳转至label标号后继续执行。一个标号必须是一行中头一个记号,并且必须紧跟一个分号。
send、wait和sleep
这些命令在dip中帮助实现简单的会话脚本。 send将它的参数输出到串行线路上。它不支持变量,但是支持所有C-风格的反斜杠字符序列如\\n和\\b。发音字符(~)用作回车/换行的缩写。
wait将一个单词作为参数,扫描串行线路上的所有输入直到识别出这个单词。这个单词中不能含有任何空格。作为选项,你可以给wait一个超时值作为第二个参数;如果在该期间内没有收到期望的单词,命令将返回并置$errlvl值为1。
sleep语句可以用来等待一段时间,例如耐心地等待登录序列的完成,再次,间隔时间是以秒计的。
mode和default
这些命令用于将串行线路转换至SLIP模式和配置接口。
mode命令是dip在进入后台执行前最后执行的命令。除非出错,否则这个命令没有返回。
mode将一个协议作为参数。目前dip只能识别SLIP和CSLIP作为有效的名字。然而当前版本的dip不能识别适应性SLIP。
当在串行线路上激活SLIP以后,dip执行ifconfig将接口配置成点对点连接,并且调用route将路由设置至远程主机。
另外,如果脚本在mode之前先执行default,dip也会使得缺省路由指向SLIP连接。
7.4 运行于服务器模式
设置你的SLIP客户是最艰难的部分。相反地,也即配置你的主机作为SLIP服务器,就很容易了。
一种方法是以服务器模式使用dip,可以通过以diplogin方式调用它来完成。它的主要配置文件是/etc/diphosts,它将登录名与分配给这台主机的地址相关联。另一种方法是,你也可以使用sliplogin,这是一个源自于BSD的工具,具有更灵活的配置方案,能在主机连接和脱开时让你执行shell脚本。目前这是个Beta版本。
这两个程序都需要你为每个SLIP客户设置一登录帐号。例如,假设你为在dent.beta.com的Arthur Dent提供SLIP服务,你可以通过在你的passwd文件中增加下面一行来建立一个名为dent的帐号:
dent:*:501:60:Arthur Dent\"s SLIP account:/tmp:/usr/sbin/diplogin
此后,你要使用passwd工具设置dent的口令。
现在,当dent登录时,dip将作为一个服务器启动。为了查出他确实允许使用SLIP,dip将查找/etc/diphosts中的用户名。这个文件详细列出了每个SLIP用户的访问权限和连接参数。dent的样本条目就象这样:
dent::dent.beta.com:Arthur Dent:SLIP,296
冒号分隔的第一个字段是用户登录用的名字。第二个字段可以含有一个另加的口令(见下面)。第三个字段是拨号的主机名或IP地址。下一个字段是没有任何特殊意义的信息字段(至今)。最后一个字段描述了连接参数。这是一个用逗号分隔的列表,指定协议(目前只有SLIP或CSLIP),后跟MTU。
当dent登录时,diplogin从diphosts文件中抽取出他的有关信息,并且,如果第二个字段不空的话,提示输入一个“外部安全口令”。用户输入的字符串将与diphosts中的相应口令(未加密的)相比较。如果它们不匹配的话,这个登录企图将被拒绝。
否则的话,diplogin通过将串行线路转换成CSLIP或SLIP、并且设置接口和路由来处理。这个连接将保持建立状态直到用户断开并且modem撤消连线为止。此时,diplogin将线路返回到普通线路规程并且退出。
diplogin需要超级用户特权。如果你没有让dip运行setuid为root,那么你应该使得diplogin是dip的一个独立的拷贝,而不是一个简单的连接。然后,diplogin能够安全地被setuid,而不会影响dip本身的状态。
注释
[1] 在RFC1441中描述了Van Jacobson头压缩。
[2] dip意思是Dialup IP。它是由Fred van Kempen编制的。
[3] diplogin 也能够(并且必须)运行setuid。见本章最后一节。
[4] 对于使用三字符的首字母缩写词的更多的回文乐趣,参见新闻组alt.tla。
发布人:netbull 来自:Linux自由鸽