Linux網路管理員手冊(8) 第八章 點對點協議 PTP PPP LCP (轉)

worldblog發表於2007-12-08
Linux網路管理員手冊(8) 第八章 點對點協議 PTP PPP LCP (轉)[@more@]管理員手冊(8)
2000-07-29 10:40
釋出者:tobull@21cn.com">netbull 閱讀次數:1180 翻譯:趙炯
gohigh@shtdu.edu.cn


第八章 點對點


8.1 揭開P字母

正像SLIP一樣,PPP是在連線上傳送資料包的協議,但卻改進了前者的幾個不足之處。它讓通訊的雙方在開始時協商諸如和最大資料包大小等選項,並且為客戶提供授權()。對於每個這樣的功能,PPP都有一個獨立的協議。下面,我們將概要地討論PPP的這些基本建立框圖。這裡的討論遠不是完整的;如果你想對PPP知道的更多些,極力推薦你閱讀-1548中它的規格說明,以及許多相關的RFCs。[1]
PPP的最底層是高階資料鏈路控制協議(High-Level Data Link Control Protocol),縮寫為HDLC,[2] 它定義了單個PPP幀的分界,並提供了16位元的檢查和。相對於非常原始的SLIP包裝來說,一個PPP幀能夠容納除IP以外的其它協議,如Novell的IPX、或Appletalk。PPP透過在基本的HDLC幀上加上一個協議欄位來做到這功能,這個欄位用於識別幀所攜帶的包的型別。
LCP,鏈路控制協議(the Link Control Protocol),用於HDLC的上層,用於協商適合於資料鏈路的選項,如指出鏈路的一邊同意接收的最大資料包大小的最大接收單元(MRU)。
在PPP連線的階段重要的一步是客戶授權(許可權)。儘管不是強制的,但對於撥號線路幾乎是必要的。通常,被呼叫的主機()透過驗證客戶是否知道某個秘密的鍵值來要求客戶自己。如果呼叫者不能給出正確的秘密鍵值,連線就中斷了。使用PPP,授權工作是雙方面的;也即,呼叫者也可以要求伺服器認證自己。這些認證過程對於雙方是完全獨立的。對於不同的認證型別有兩個協議,我們將在下面更進一步地討論。它們被命名為口令認證協議(Pass Authentication protocol),或PAP和質詢握手認證(Challenge Handshake Authentication Protocol),或CHAP。
透過資料鏈路的每一個網路協議,如IP、Appletalk等等,使用相應的網路控制協議(Network 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-ppp-1.0.0,包含有核心PPP模組、pppd、和一個用於撥號至的稱為chat的程式。
PPP核心驅動程式是由Michael Callahan編制的。pppd源自於為Sun和386機器的一個免費PPP實現,它是由Drew Perkins和其他人編制的,並且由Paul Mackerras維護。是由Al Longyear[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上,你必須設定好基本的網路功能,如回送裝置和解析器。這兩者已在前面章節中討論過了。還有些有關在序列鏈路上使用的解釋;請參考SLIP一章中對此的描述。
作為一個使用pppd如何建立一個PPP連線的例子,假設你再次在vlager。你已經撥號到PPP伺服器,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,依次類推。下一步,它將設定一個指向鏈路另一端主機的路由表條目。在上面示出的例子中,pppd將使得預設網路路由指向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.
auth # require authentication
usehostname # use local hostname for CHAP
lock # use UUCP-style device locking
ain vbrew.com # our domain name

這些選項的頭兩個用於許可權認證並且將在下面給出解釋。lock關鍵字使得pppd遵守標準的UUCP裝置鎖定方法。根據這個慣例,每個訪問序列裝置的程式,如/dev/cua3,在UUCP spool目錄中建立一個名為LCK..cua3的鎖定檔案,用於指示該裝置正在使用。這是避免任何其它程式如minicom或uucico去開啟PPP正在使用的序列裝置。
在全域性配置檔案中提供這些選項的原因是如上顯示的那些選項是不能被覆蓋掉的,因而提供了一個合理的安全級。然而,請注意有些選項可以在後面被覆蓋掉;這樣的一個例子是connect串。

8.5 使用chat撥出
在上例中讓你感到不便的事情之一是在你能夠啟動pppd之前必須手工地建立連線。不象dip,pppd對於撥號至遠端系統以及登入沒有自己的指令碼語言,而是需要依賴於某些外部程式或指令碼來做這些事。要執行的命令可以用connect命令列選項給予pppd。pppd將重定向該命令的標準輸入和輸出到序列線路上。針對此一個有用的程式是expect,是由Don Libes編寫的。它有一個基於Tcl的非常強大的語言,並且是針對此類應用明確地設計出來的。
pppd包帶有一個同樣稱為chat的程式,是用於指定UUCP-風格的會話指令碼的。基本上說,一個會話指令碼是由我們期望從遠端系統收到的互動式的字串序列以及我們所傳送的應答字串序列。我們將分別稱之為期望字串和傳送字串。這是從一個典型會話指令碼中的摘錄:

ogin: b1ff ssword: s3kr3t

這告訴chat等待遠端系統傳送來登入提示,並且返回登入名b1ff。我們只是等待ogin: 所以登入提示是大寫還是小寫沒什麼關係,也不用管它是否完全正確。接下來的又是一個期望字串它使得chat等待口令輸入提示,並且隨後發出你的口令。
這基本上,上面是chat指令碼所要做的。當然,撥號到一個PPP伺服器的完整指令碼也必須包括適當的modem命令。假設你的modem使用Hayes命令集,並且伺服器的電話號碼是318714。那麼與c3po建立一個連線的完整的會話請求是

$ chat -v "" ATZ OK ATDT318714 CONNECT "" ogin: ppp word: GaGariN

根據定義,頭一個字串必須是期望字串,但是在我們啟動modem之前,modem是不會發出任何東西的,所以我們透過指定一個空串來跳過第一個期望字串。然後我們繼續發出ATZ,即Hayes相容modem的復位命令,並等待它的響應(OK)。下一個串向chat傳送出一個撥號命令和電話號碼,並且期望得到CONNECT訊息的響應。接下來又是一個空串,因為我們現在還不想傳送出任何資訊,而是等待登入提示的出現。餘下的chat指令碼所做的工作完全象我們上面描述的一樣。
-v選項使得chat將所有的活動記錄在syslog後臺程式的local2中。[6]
在命令列上寫出會話指令碼會承擔一定的風險,因為使用者可以使用ps命令觀察程式的命令列。你可以將會話指令碼放入一個檔案,比如說是dial-c3po,來避免這個風險。透過給chat一個-f選項後跟這個檔名,你可以使得chat從該檔案中讀取指令碼取而代之從命令列讀取。現在完整的pppd命令就象這樣:

# pppd connect "chat -f dial-c3po" /dev/cua3 38400 -detach
crtscts modem defaultroute

除了指定撥號指令碼的connect選項,我們在命令列上多加了兩個選項:-detach—告知pppd不要從控制檯分離並且變成為後臺程式。Modem關鍵字使得pppd在序列裝置上執行某些modem專用的動作,就如在撥號之前和之後結束通話線路。如果你不使用這個關鍵字,pppd將不會監視埠的DCD線,因而將不會檢測是否遠端出呼意料地結束通話了。
上面給出的例子是非常簡單的;chat允許有更為複雜的會話指令碼。一個非常有用的特性是指定中止含有錯誤的的會話。典型的中止字串是象訊息BUSY、或NO CARRIER,這是當所撥的號碼是忙音、或沒有提起電話時,你的modem產生的。為了使得chat迅速地識別出這些中止字串,而不是等到超時,你可以使用ABORT關鍵字在指令碼的開頭指定它們:

$ chat -v ABORT BUSY ABORT "NO CARRIER" "" ATZ OK ...

以同樣的方式,你可以透過插入TIMEOUT選項來改變會話部分中的超時值。詳細資料,請參見chat(8)的手冊頁。
有時,你也想有條件地執行會話指令碼的一部分。例如,當你沒有接收到遠端的登入提示時,你可能想傳送一個BREAK,或一個Enter鍵。你可以透過給期望字串附加一個子指令碼來做到。它是由一系列的傳送和期望字串組成,正象整個指令碼本身,它是用連字號分開的。每當附加的期望字串沒有及時收到時,該子指令碼就會被執行。在上面的例子中,我們要象下面那樣修改會話指令碼:

ogin:-BREAK-ogin: ppp ssword: GaGariN

現在,當chat沒有收到遠端系統傳送的登入提示時,子指令碼就被執行,首先傳送一個BREAK,然後再次等待登入提示的出現。如果現在提示出現時,指令碼就會象往常那樣繼續,否則的話,它將帶錯而終止。

8.6 你的PPP設定
預設地,pppd將把任何警告和出錯訊息記錄到syslog的daemon設施中。你必須往syslog.conf中增加一個條目,以使得這些訊息重定向到一個檔案中,或者甚至到控制檯上,否則的話syslog就會輕易地丟棄這些訊息。下面這個條目將所有的訊息送到/var/log/ppp-log:

daemon.* /var/log/ppp-log

如果你的PPP設定不能立刻工作,檢視這個日誌檔案會給你什麼地方出錯的一點提示。如果這沒有什麼幫助,你可以使用de選項開啟額外的除錯輸出資訊。這使得pppd將所有傳送和接收的控制資料包的內容記錄到syslog中。所有的訊息將傳入daemon設施中。
最後,最猛烈的方法是透過使用選項kdebugpppd,以啟用核心層的除錯。在該選項之後是下面數值的位元位或運算的數值:1表示一般除錯訊息,2 表示列印所有傳入的HDLC幀的內容,4 是使得驅動程式列印出所有傳出的HDLC幀。要捕獲核心的除錯訊息,你必須或者執行讀取/proc/kmsg檔案的syslogd後臺程式,或者是klogd後臺程式。這兩者都將核心的除錯資訊定向到syslog的kernel設施中。

8.7 IP配置選項
在連線配置期間,IPCP是用於協調幾個IP引數的。通常,每個端點都會發出一個IPCP配置請求包,指出它想要改變哪些預設值,改成什麼值。在接收方,遠端依次檢查每個選項,並且或者同意改變或者拒絕。
關於pppd將嘗試協調哪些IPCP選項,pppd給了你許多的控制權。你可以透過命令列選項來調節這些選項,我們將在下面討論它們。

8.7.1 選擇IP地址
在上面的例子中,我們用pppd撥號到c3po並且建立了一個IP連線。在連線的兩端沒有預備要選擇一個特定的IP地址。而是使用vlager的地址作為本地IP地址,並讓c3po自己給出自己的。然而,有時候在連線的一端或兩端控制要使用的地址是很有用的。pppd支援這種控制的幾種變異。
要請求特定的地址,通常你要給pppd提供下面的選項:

local_addr:remote_addr

這裡local_addr和remote_addr可以用點分四組表示法表示,或用主機名錶示。[7] 這使得pppd試圖使用第一個地址作為它自己的IP地址,而第二個作為對等點的。如果在IPCP協商時,對方拒絕了其中之一的地址,那麼就不能建立起IP連線了。[8]
如果你只想設定本地地址,並接受任何對等點使用的地址,你只需不使用remote_addr部分就行了。例如,要使得vlager使用IP地址130.83.4.27而不使用自己的IP地址,你需要在命令列上給出130.83.4.27:即可。類似地,如果只想設定遠端點的地址,你只需讓local_addr欄位為空。此時,預設地,pppd將使用與你的主機相應的地址。
有些處理許多客戶站點的PPP伺服器動態地為客戶分配地址:只有當撥號進來時才給客戶系統分配地址,而當客戶退出時就再次清除。當撥號到這種伺服器時,你必須確信pppd沒有要求從伺服器要求任何特定的IP地址,而是接受伺服器讓你使用的地址。這意味著你不必指定local_addr引數。另外,你必須使用noipdefault選項,該選項使得pppd等待對等點提供IP地址,以替代使用本地主機的地址。

8.7.2 透過PPP連線進行路由
在設定好網路介面以後,pppd通常將主機的路由只設定到它所連線的遠端點上。如果遠端主機是在一個LAN上,你當然也希望能夠連線到遠端主機所在網路的其它主機上;也即,必須設定一個網路路由。
上面,我們已經知道可以使用defaultroute選項請求pppd設定預設的路由。如果你所撥號連線的伺服器將作為你的Internet閘道器話,那麼這個選項將是非常有用的。
相反的情況是,你的系統作為孤獨的主機的一個閘道器,也同樣很容易做到。例如,假設虛擬釀酒廠的某個僱員,他家的機器叫做loner。當透過PPP連線到vlager時,他使用釀酒廠子網的地址。在vlager端,我們現在可以給pppd一個選項,它將為loner一個ARP條目。這將自動地使得loner可以訪問釀酒廠和葡萄酒廠的所有主機了。
然而事情並不是總是那樣的簡單,例如,當連線兩個時。這常常需要增加一個特殊的網路路由,因為這些網路都可以有它們自己預設的路由。另外,使得兩個端點使用PPP連線作為預設路由將產生一個迴圈,到未知目的地的包將在這兩個端點之間來回傳送,直到它們過了存活期。
作為一個例子,假設虛擬釀酒廠在某個其它城市開了一個分支機構。這個附屬機構使用IP網路號191.72.3.0執行一個他們自己的乙太網,它是釀酒廠的B類網路的子網3。他們想透過PPP連線到釀酒廠的主乙太網上以客戶的資料庫等等。再次,vlager將作為一個閘道器;它的遠端點被稱作sub-etha且IP地址為192.72.3.1。
當sub-etha連線到vlager時,它將象平常一樣使得預設路由指向vlager。然而,在vlager上,我們必須為透過sub-etha的子網3安裝一個網路路由。為此,我們使用一個pppd的至今還沒有討論過的特性—ip-up命令。這是一個位於/etc/ppp中的shell指令碼或程式,是在PPP介面配置完以後執行的。當使用時,它是用下列引數呼叫的:

ip-up iface device speed local addr remote addr

這裡,iface指定所使用的介面,device是所使用的序列裝置檔案(如果使用了stdin/stdout,那麼是/dev/tty)的路徑名,speed是裝置的速度。local_addr和remote_addr給出了以點分四組表示的用於連線兩端點的IP地址。在我們這種情況下,ip-up指令碼可以包含下列程式碼段:

#!/bin/sh
case $5 in
191.72.3.1) # this is sub-etha
route add 191.72.3.0 gw 191.72.3.1;;
esac
exit 0

以類似的方式,/etc/ppp/ip-down是用於在PPP連線再次斷開以後取消所有ip-up的活動。
然而,路由選擇方案還沒有完成。我們已經在雙方的PPP主機上設定好了路由選擇表條目,但至今,在兩個網上的所有其它主機關於PPP連線的任何事情。如果在附屬機構的所有主機有指向sub-etha的預設路由,並且釀酒廠的所有主機都預設地路由到vlager的話,
這就不是個大問題了。如果不是這樣的話,那麼你唯一的選擇是使用一個象gated的路由選擇後臺程式。在vlager上建立了網路路由以後,路由選擇後臺程式將會對所有子網上的主機廣播這個新路由。

8.8 鏈路控制選項
上面,我們已經遇到過LCP,也即鏈路控制協議,它是用於協調鏈路特性以及測試鏈路的。
透過LCP協調的兩個重要的選項是最大接收單元,和非同步控制字元對映表。還有許多其它的LCP配置選項,但它們太特殊,這裡就不給予描述了。請參考RFC1548中對它們的解釋。
非同步控制字元對映表,俗稱非同步表,是用於象電話線路的非同步鏈路上確定必須被換碼的控制字元(用一特殊的二字元序列替換)。例如,你可能想要避開用於軟體握手訊號的XON和XOFF字元,因為某些配置不當的modem在接收到一個XOFF時可能會卡住。其它的控制字元包括Ctrl-](telent的換碼字元)。透過在非同步表中指定這些控制字元,PPP允許你對ASCII碼0到31 中的任何字元進行換碼。
非同步表是一個32位元寬的點陣圖,最低位元位對應於ASCII的NUL字元,最高位元位對應於ASCII碼31。如果一個位元位置位,它表示相應的字元在傳送到鏈路之前必須被轉義(換碼)。最初,非同步表被設定為0xffffffff,它表示所有的控制字元都將被轉義。
為了告訴你的對等點不需要對所有的控制字元換碼,而只需要對其中的幾個進行轉義,你可以使用asyncmap選項給pppd指定一個新的非同步對映。例如,如果只有^S和^Q(ASCII 17和ASCII 19,通常用作XON和XOFF)必須被轉義,那麼就使用下面的選項:

asyncmap 0x000A0000

最大接收單元(Maximum Receive Unit),或MRU,通知對等點我們想接收的HDLC幀的最大長度。儘管這會使你想起MTU的值(最大傳輸單元Maximum Traner Unit),這兩者很少有共同之處。MTU是核心的一個引數,描述了介面能夠處理的最大幀的大小。而MRU只是對遠端點不要產生任何大於MRU值的一個建議;不管怎樣,介面必須能夠接收最大為1500位元組的幀。
因此,如何選擇一個MRU的大小就與鏈路的傳輸能力關係不大了,而是與如何能達到最大的吞吐量有關。如果你打算在鏈路上執行互動式的應用程式,那麼將MRU值設定為小到296是個不錯的主意,這樣一個偶然的大資料包(比如,從一個來的會話)就不會使得你的游標“跳動”了。要告知pppd請求一個296的MRU,你必須給它一個選項mru 296。然而,小的MRUs只有在你沒有禁止VJ頭壓縮(它預設是啟用的)時才有意義。
pppd也能夠理解一些設定協調過程整體行為的LCP選項,比如在鏈路終止前可以的最大請求配置數。除非你明確的知道你在做什麼,否則不要改動它們。
最後,還有兩個用於LCP回顯訊息的選項。PPP定義了兩類訊息,回顯請求(Echo Reguest)和回顯響應(Echo Response)。Pppd使用這個特性來檢查一個鏈路是否還在執行。你可以透過使用lcp-echo-interval選項和一個以秒計的時間值來啟用這個特性。如果在這個時間間隔內沒有從遠端主機收到幀,那麼pppd生成一個Echo Reguest,並切期待對等點返回一個Echo Response。如果對等點沒有產生一個響應,那麼在傳送了一定數量的請求以後鏈路即被中止。這個數量可以用lcp-echo-failure選項來設定。預設地,這個特性是全部禁止的。

8.9 常規安全考慮
一個配置不當的PPP後臺程式能成為一個破壞性的安全缺口。它糟糕到象允許任何人能夠將他的機器接入你的乙太網上(這是非常糟糕的)。在本節中,我們將討論一些能使你安全配置PPP的方法。
Pppd的一個問題是,要配置網路裝置和路由選擇表需要許可權。通常解決這個問題的辦法是執行它setuid root。然而,pppd允許使用者設定各種與安全相關的選項。為了免受使用者可能透過操作這些選項而發起的,建議你在全域性/etc/ppp/options檔案中設定一些預設值,就象使用選項檔案一節例子中顯示的。其中有些,比如授權認證選項使用者是覆蓋不了的,所以對操作起到了一定的保護作用。
當然,你也需要針對你用PPP連線的系統來保護自己。要擋開假冒他人的主機,你應該總是檢查你的對等點的授權認證。另外,你不應該允許外部主機能使用它們選擇的任何IP地址,而是限制他們只能使用幾個地址。下面一節將涉及到這些問題。

8.10 PPP授權認證
8.10.1 CHAP與PAP
對於PPP來講,每個系統可以要求它的對等點使用兩種授權認證協議之一來認證自己。這兩個協議是口令認證協議(Password Authentication Protocol)(PAP)和質詢握手認證協議(Challenge Handshake Authentication Protocol)(CHAP)。當建立了一個連線以後,兩端都可以請求對方認證自己,而不管它是呼叫者還是被呼叫者。下面當我想區別認證系統和認證者時,我將寬鬆地用“客戶”和“伺服器”來講。一個PPP後臺程式能夠請求它的對等點透過傳送另一個確定期望的認證協議的LCP配置請求來進行認證。
PAP與通常的登入過程的工作原理基本上一樣。客戶透過向伺服器傳送一個使用者名稱和一個(可以是的)口令來認證自己,伺服器用它們與自己的秘密資料庫相比較。對於那些透過序列線路以獲得口令的偷聽者和對於重複試驗出錯(trial and error)的攻擊來說,這項技術是易受攻擊的。
CHAP就沒有這些不足之處。對於CHAP,認證者(也即是伺服器)向客戶傳送一個隨機生成的“質詢”字串和自己的主機名。客戶使用該主機名來查詢適當的秘碼(口令),並將其與質詢合在一起形成一個字串,並且使用一個單向(雜湊)雜湊加密該串。結果值與自己的主機名一起返回給伺服器。現在伺服器執行相同的計算,如果得到相同的結果就認可該客戶。
CHAP的另一個特性是它不僅在開始時請求客戶認證自己,而且每隔一定的時間就傳送一個質詢,以確信客戶並沒有被者替換掉,例如透過切換電話線路。
pppd將CHAP和PAP的秘密鍵值分別存放在兩個不同的檔案中,稱為/etc/ppp/chap-secrets和pap-secrets,透過使用一個或另一個檔案來進入遠端主機,你可以很好地控制是使用CHAP還是PAP來與對方認證我們自己,反之也然。
預設地,pppd無須來自遠端的認證,但是同意來自遠端的認證請求。由於CHAP比PAP來得更為穩固和強壯,pppd會盡可能地使用前者。如果對方不支援它,或者pppd在它的chap-secrets檔案中找不到該遠端系統的一個CHAP秘密(密碼),它就回過來使用PAP。如果它也沒有針對於對等點的PAP密碼,它就拒絕做任何認證。結果,連線被關閉。
這種行為可以從幾個方面進行修改。例如,當給出auth鍵值時,pppd將請求對方來認證自己。如果pppd分別在CHAP或PAP資料庫中有一個對於該對等點的密碼時, pppd將同意使用CHAP或PAP來做。還有一個可以開啟或關閉特定認證協議的選項,但這裡我們就不再描述它們了。詳細資訊請參考pppd(8)手冊頁。
如果所有和你進行PPP對話的系統同意為你認證它們自己,你應該將auth選項放入全域性/etc/ppp/options檔案中並且為每個系統在chap-secrets檔案中定義口令。如果一個系統不支援CHAP,那麼就在pap-secrets檔案中為其加入一個條目。這樣,你就可以確信連線到你的主機上的任何系統都是認證過的。
下面兩節描述了這兩個PPP密碼檔案,pap-secrets和chap-secrets。它們位於/etc/ppp中,包含客戶、伺服器和口令三為一組的值,還可以後接任選的一個IP地址列表。客戶和伺服器欄位的解釋對於CHAP和PAP是不同的,這也起決於我們是否要為對方認證我們自己,或者要求伺服器為我們認證它們自己。

8.10.2 CHAP的秘密檔案
當pppd必須為某些使用CHAP的伺服器認證自己時,pppd就在pap-secrets檔案中尋找客戶欄位與本地主機名相同、伺服器欄位與在CHAP質詢中傳送來的遠端主機名相同的條目。當要求對等點認證它自己時,該規則只是簡單地反一下:此時pppd尋找客戶欄位與遠端主機名相同(經由客戶的CHAP響應傳送過來的)、伺服器欄位與本地主機名相同的條目。

下面是vlager的一個樣本chap-secrets檔案:[9]

# CHAP secrets for vlager.vbrew.com
#
# client server secret addrs
#-------------------------------------------------------------------
vlager.vbrew.com c3po.lucas.com "Use The Luke" vlager.vbr
c3po.lucas.com vlager.vbrew.com "riverrun, pasteve" c3po.lucas
* vlager.vbrew.com "VeryStupidPassword" pub.vbrew.

當與c3po建立了一個PPP連線時,c3po要求vlager透過傳送一個CHAP質詢用CHAP來認證自己。然後pppd掃描chap-secrets檔案中的客戶欄位等於vlager.vbrew.com、伺服器欄位等於c3po.lucas.com的條目,[10] 這樣就找到了上面的第一行。然後它就從質詢字串和密碼(Use The Source Luke)生成一個CHAP響應,併傳送給c3po。
與此同時,pppd為c3po組合成一個CHAP質詢,其中包含一個唯一的質詢字串和它的全資主機名vlager.vbrew.com。c3po以剛才我們討論的方式構成一個CHAP響應,並將其返回給vlager。現在,pppd從響應中取得客戶的主機名(c3po.vbrew.com),並且查詢chap-secrets檔案中客戶欄位為c3po、伺服器欄位為vlager的一行。這正是上面的第二行,所以pppd將CHAP質詢和該行的密碼(riverrun, pasteve)組合在一起並進行加密,並將結果與c3po的CHAP響應相比較。
可選的第四個欄位列出了在第一個欄位的客戶的IP地址的一個列表。這個地址可以用點分四組表示法給出也可以用解析器查詢出的主機名給出。例如,如果c3po在IPCP協商中請求使用一個不在這個列表中的IP地址,請求將被拒絕,並且IPCP將被關閉。因此在上面所示的樣本檔案中,c3po被限制於只能使用自己的IP地址。如果地址欄位是空的,那麼就允許使用任何地址;如果該欄位不空,就限制了該客戶使用的IP地址。
樣本chap-secrets檔案的第三行允許任何主機與vlager建立一個PPP連結,因為一個為*的客戶或伺服器欄位與任何主機名匹配。唯一的限制是這些主機必須知道秘碼,並且使用地址pub.vbrew.com。以萬用字元作主機名的任何條目可以在秘密檔案中的任何地方,因為pppd總是使用伺服器/客戶對最為匹配的條目。
關於pppd在秘密檔案中查詢獲取主機名的方式,還有一些要作說明。就象前面所解釋的,遠端主機名總是透過對等點的CHAP質詢或響應包提供的。本地主機名預設的是透過呼叫gethostname(2)函式來得到的。如果你已經將系統名設定為你的非限制的主機名,這樣的話,你就必須使用domain選項為pppd另外給出一個域名:

# pppd …domain vbrew.com

這將使得對於所有有關授權認證的活動,都將把釀酒廠的域名新增到vlager上。其它修改本地主機名的progpppd的想法是usehostname和name。當你使用“local:varremote”(local不是點分四組表示的名字)在命令列上給出本地IP地址,pppd將使用它作為本地主機名。詳細資訊請參見pppd(8)的手冊頁。

8.10.3 PAP秘密檔案
PAP秘密檔案與CHAP所用的非常相似。頭兩個欄位總是包含一個使用者名稱和一個伺服器名;第三個欄位含有PAP密碼。當遠端傳送來一個認證請求時,pppd使用伺服器欄位等於本地主機名、使用者欄位等於請求中傳送過來的使用者名稱的條目。當為對等點認證自己時,pppd從使用者欄位等於本地使用者名稱、伺服器欄位等於遠端主機名的行中取得密碼(secret)。
一個樣本PAP秘密檔案就象這一樣:

# /etc/ppp/pap-secrets
#
# user server secret addrs
vlager-pap c3po cresspahl vlager.vbrew.com
c3po vlager Donaldth c3po.lucas.com

第一行用於和c3po對話時認證我們自己。第二行說明一個名為c3po的使用者必須為我們認證它自己。
第一列的名字vlager-pap是我們傳送給c3po的使用者名稱。預設地,pppd將用本地主機名作為使用者名稱,但是你也可以透過給出user選項後跟一個名字來指定一個不同的名字。
當為了與對等點進行認證而從pap-secrets檔案中選取一個條目時,pppd必須知道遠端主機的名字。由於它沒法找出該名字,你必須在命令列上使用remotename關鍵字後跟對等點的主機名來指定它。例如,要使用上面的條目與c3po認證,我們必須在pppd的命令列上加入下面的選項:

#{} pppd … remotename c3po user vlager-pap

在第四個欄位(以及所有後面的欄位),你可以指定特定的主機所允許的IP地址,正如CHAP秘密檔案中的一樣。這樣,對等點就可以從那個列表中只請求地址。在樣本檔案中,我們要求c3po使用它的真實IP地址。
注意,PAP是一個非常弱的認證方法,所以建議儘可能使用CHAP。因此我們在這裡對PAP就不再詳述了;如果你對PAP的使用感興趣的話,你可以在pppd(8)的手冊頁中找到許多有關PAP的特性。

8.11 配置一個PPP伺服器
以伺服器方式執行pppd只需在命令列上加上一些適當的選項。原則上講,你要建立一個特殊的帳號,比如說是ppp,並給它一個指令碼或程式作為用這些選項呼叫pppd的登入shell。例如,你要在/etc/passwd中加入下面一行:

ppp:*:500:200:Public PPP Account:/tmp:/etc/ppp/ppplogin

當然,你可以使用與上面所示不同的uids和gids。你還必須使用passwd命令為上面的帳號設定口令。
然後,ppplogin指令碼可以象這樣:

#!/bin/sh
# ppplogin - script to fire up pppd on login
mesg n
stty -echo
exec pppd -detach silent modem crtscts

mesg命令用於禁止其他使用者往tty寫資訊,比如使用write命令。stty命令關閉字元回顯功能。這是必須的,否則的話對等點傳送來的任何資訊都將回顯回去。上面給出的最重要的pppd選項是-detach,因為它防止pppd脫離控制tty。如果我們不指定這個選項,它就會進入後臺,使得shell指令碼退出。隨之而來的是序列線路將被結束通話,連線中止。silent選項使得pppd在開始傳送前進行等待直到它從呼叫系統接收到一個資料包。這可以防止當呼叫系統很緩慢地啟動它的PPP客戶時傳輸的超時。modem選項用於使得pppd監視DTR引線用以觀察對等點是否已掉線,而crtscts選項用以開啟硬體握手訊號。
除了這些選項以外,你還可以迫使使用某些授權認證,例如透過在pppd的命令列上或在全域性選項檔案中指定auth。有關開啟和禁用各種認證協議的更多選項的描述,可參見線上手冊。



註釋
[1] 相關的RFCs列在本書後面的指定參考書目中。
[2] 實際上,HDLC是一個由國際標準化組織(ISO)設計的非常通用協議。
[3] 兩位作者都已經說過今後會比較忙。如果你有任何有關PPP的一般問題,你最好詢問Linux積極分子mailing list的NET通道上的人。
[4] karl@morningstar.com 。
[5] 預設的網路路由只是在還沒有時才被建立。
[6] 如果你編輯syslog.conf將這些登入資訊重定向到一個檔案中,請確信這個檔案是不可讀的,因為chat預設地記錄下整個會話指令碼—包括口令和所有其它的資訊。
[7] 對於CHAP許可權認證方法在該選項中使用主機名錶示是有其因果關係的。請參見下面的CHAP一節。
[8] 透過將選項ipcp-accept-local和ipcp-accept-remote給予pppd,你可以允許遠端點覆蓋你對使用IP地址的設想。詳細資訊請參閱手冊。
[9] 雙引號不是口令的一部分,它們只是用來標明口令中的空格而已。
[10] 這個主機名是從CHAP質詢中得到的。


來源:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-989885/,如需轉載,請註明出處,否則將追究法律責任。

相關文章