TCP/IP詳解(3)

5  RARP:逆地址解析協議

 

5.1 引言

    具有本地磁盤的系統引導時,一般是從磁盤上的配置文件中讀取IP地址。但是無盤機,如X終端或無盤工作站,則需要採用其他方法來獲得IP地址。

    網絡上的每個系統都具有唯一的硬件地址,它是由網絡接口生產廠家配置的。無盤系統的RARP實現過程是從接口卡上讀取唯一的硬件地址,然後發送一份RARP請求(一幀在網絡上廣播的數據),請求某個主機響應該無盤系統的IP地址(在RARP回答中)。

    在概念上這個過程是很簡單的,但是實現起來常常比ARP要困難,其原因在本章後面介紹。RARP的正式規範是RFC 903 [Finlayson et al. 1984]

 

5.2  RARP的分組格式

    RARP分組的格式與ARP分組基本一致(圖4.3)。它們之間主要的差別是RARP請求或回答的幀類型代碼爲0x8035,而且RARP請求的操作代碼爲3,回答操作代碼爲4

    對應於ARPRARP請求以廣播方式傳送,而RARP回答一般是單播(unicast)傳送的。

 

5.3  RARP舉例

    在我們的互連網中,我們可以強制sun主機從網絡上引導,而不是從本地磁盤引導。如果我們在主機bsdi上運行RARP服務程序和tcpdump命令,那麼可以得到如圖5.1那樣的輸出。我們用-e參數使得tcpdump命令打印出硬件地址:

 

5.1 RARP請求和回答

 

    RARP請求是廣播方式(第1行),而第2行的RARP回答是單播方式。第2行的輸出中at sun表示RARP回答包含主機sunIP地址(140.252.13.33)。

    在第3行中,我們可以看到,一旦sun收到RARP回答,它就發送一個TFTP讀請求(RRQ)給文件8CFC0D21.SUN4C。(TFTP表示簡單文件傳輸協議。我們將在第15章詳細介紹它。)文件名中的8個十六進制數字表求主機sunIP地址140.252.13.33。這個IP地址在RARP回答中返回。文件名的後綴SUN4C表示被引導系統的類型。

    tcpdump在第3行中指出IP數據報的長度是65個字節,而不是一個UDP數據報(實際上是一個UDP數據報),因爲我們運行tcpdump命令時帶有-e參數,以查看硬件層的地址。在圖5.1中需要指出的另一點是,第2行中的以太網數據幀長度比最小長度還要小(在4.5節中我們說過應該是60字節。)其原因是我們在發送該以太網數據幀的系統(bisdi)上運行tcpdump命令的。應用程序rarpd42字節到BSD分組過濾設備上(其中14字節爲以太網數據幀的報頭,剩下的28字節是RARP回答),這就是tcpdump收到的副本。但是以太網設備驅動程序要把這一短幀填充空白字符以達到最小傳輸長度(60)。如果我們在另一個系統上運行tcpdump命令,其長度將會是60

    我們從這個例子可以看出,當無盤系統從RARP回答中收到它的IP地址後,它將發送TFTP請求來讀取引導映象。在這一點上我們將不再進一步詳細討論無盤系統是如何引導的。(第16章將描述無盤X終端利用RARPBOOTP以及TFTP進行引導的過程。)

    當網絡上沒有RARP服務器時,其結果如圖5.2所示。每個分組的目的地址都是以太網廣播地址。在who-後面的以太網地址是目的硬件地址,跟在tell後面的以太網地址是發送端的硬件地址。

    請注意重發的頻度。第一次重發是在6.55秒以後,然後增加到42.80秒,然後又減到5.34秒和6.55秒,然後又回到42.79秒。這種不確定的情況一直繼續下去。如果計算一下兩次重發之間的時間間隔,我們發現存在一種雙倍的關係:從5.346.551.21秒,從 6.558.972.42秒,從8.9713.804.83秒,一直這樣繼續下去。當時間間隔達到某個閾值時(大於42.80秒),它又重新置爲5.34秒。

 

5.2 網絡中沒有RARP服務器的RARP請求

 

    超時間隔採用這樣的遞增方法比每次都採用相同值的方法要好。在圖6.8中,我們將看到一種錯誤的超時重發方法,以及在第21章中將看到TCP的超時重發機制。

 

5.4  RARP服務器的設計

    雖然RARP在概念上很簡單,但是設計一個RARP服務器與系統相關而且比較複雜。相反,提供一個ARP服務器很簡單,通常是TCP/IP在內核中實現的一部分。由於內核知道IP地址和硬件地址,因此當它收到一個詢問IP地址的ARP請求時,只需用相應的硬件地址來提供回答就可以了。

 

作爲用戶進程的RARP服務器

    RARP服務器的複雜性在於,服務器一般要爲多個主機(網絡上所有的無盤系統)提供硬件地址到IP地址的映射。該映射包含在一個磁盤文件中(在Unix系統中一般位於/etc/ethers目錄中)。由於內核一般不讀取和分析磁盤文件,因此RARP服務器的功能就由用戶進程來提供,而不是作爲內核的TCP/IP實現的一部分。

    更爲複雜的是,RARP請求是作爲一個特殊類型的以太網數據幀來傳送的(幀類型字段值爲0x8035,如圖2.1所示)。這說明RARP服務器必須能夠發送和接收這種類型的以太網數據幀。在附錄A中,我們描述了BSD分組過濾器,Sun的網絡接口栓,以及SVR4數據鏈路提供者接口都可用來接收這些數據幀。由於發送和接收這些數據幀與系統有關,因此RARP服務器的實現與系統是捆綁在一起的。

 

每個網絡有多個RARP服務器

    RARP服務器實現的一個複雜因素是RARP請求是在硬件層上進行廣播的,如圖5.2所示。這意味着它們不經過路由器進行轉發。爲了讓無盤系統在RARP服務器關機的狀態下也能引導,通常在一個網絡上(例如一根電纜)要提供多個RARP服務器。

    當服務器的數目增加時(以提供冗餘備份),網絡流量也隨之增加,因爲每個服務器對每個RARP請求都要發送RARP回答。發送RARP請求的無盤系統一般採用最先收到的RARP回答。(對於ARP我們從來沒有遇到這種情況,因爲只有一臺主機發送ARP回答。)另外,還有一種可能發生的情況是每個RARP服務器同時回答,這樣會增加以太網發生衝突的概率。

 

5.5 小結

    RARP協議是許多無盤系統在引導時用來獲取IP地址。RARP分組格式基本上與ARP分組一致。一個RARP請求在網絡上進行廣播,它在分組中標明發送端的硬件地址,以請求相應IP地址的響應。回答通常是單播傳送的。

    RARP帶來的問題包括使用鏈路層廣播,這樣就阻止大多數路由器轉發RARP請求,只返回很少信息:只是系統的IP地址。在第16章中,我們將看到BOOTP在無盤系統引導時會返回更多的信息:IP地址,引導主機的名字等等。

    雖然RARP在概念上很簡單,但是RARP服務器的實現卻與系統相關。因此,並不是所有的TCP/IP實現都提供RARP服務器。

 

習題

5.1 RARP需要不同的幀類型字段嗎?ARPRARP都使用相同的值0x0806嗎?

5.2 在一個有多個RARP服務器的網絡上,如何防止它們的響應發生衝突?

53

6  ICMPInternet控制報文協議

 

6.1 引言

    ICMP經常被認爲是IP層的一個組成部分。它傳遞差錯信息以及其它需要注意的信息。ICMP報文通常被IP層或更高層協議(TCPUDP)使用。一些ICMP報文把差錯信息返回給用戶進程。

    ICMP信息是在IP數據報內部被傳輸的,如6.1所示。

 

6.1 ICMP封裝在IP數據報內部

 

ICMP 的正式規範參見RFC 792 [Posterl 1981b]

    ICMP報文的格式如圖6.2所示。所有報文的前4個字節都是一樣的,但是剩下的其它字節則互不相同。下面我們將逐個介紹各種報文格式。

    類型字段可以有15個不同的值,以描述特定類型的ICMP報文。某些ICMP報文還使用代碼字段的值來進一步描述不同的條件。

    檢驗和字段覆蓋整個ICMP報文。使用的算法與我們在3.2節中介紹的IP首部檢驗和算法相同。ICMP的檢驗和是必需的。

 

6.2 ICMP報文

 

    在本章中,我們將粗淺地討論ICMP報文,並對其中一部分作詳細介紹:地址掩碼請求和回答,時間戳請求和回答,以及不可答端口。我們將詳細介紹第27Ping程序所使用的迴應請求和回答報文和第9章處理IP路由的ICMP報文。

 

6.2  ICMP報文的類型

    各種類型的ICMP報文如圖6.3所示,不同類型由報文中的類型字段和代碼字段來共同決定。

    圖中的最後兩列表明ICMP報文是一份查詢報文還是一份差錯報文。因爲對ICMP差錯報文有時需要作特殊處理,因此我們需要對它們進行區分。例如,在對ICMP差錯報文進行響應時,永遠不會生成另一份ICMP差錯報文。(如果沒有這個限制規則,我們可能會遇到一個差錯產生另一個差錯的情況,而差錯再產生差錯,這樣無休止地循環下去。)

    當發送一份ICMP差錯報文時,報文始終包含IP的首部和產生ICMP差錯報文的IP數據報的前8個字節。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協議(根據IP數據報首部中的協議字段來判斷)和用戶進程(根據包含在IP數據報前8個字節中的TCPUDP報文首部中的TCPUDP端口號來判斷)聯繫起來。在6.5節我們將舉例來說明一點。

    下面各種情況都不會導致產生ICMP差錯報文:

    1ICMP差錯報文。(但是,ICMP查詢報文可能會產生ICMP差錯報文。)

    2.目的地址是廣播地址(圖3.9)或多播地址(D類地址,圖1.5)的IP數據報。

    3.作爲鏈路層廣播的數據報。

    4.不是IP分片的第一片。(我們將在11.5節介紹分片。)

    5.源地址不是單個主機的數據報。這就是說,源地址不能爲零地址、環回地址、廣播地址或多播地址。

 

(下面是圖6.3的譯文)

類型

代碼

描述

查詢

差錯

0

0

回答回顯(Ping回答,第7章)

·

 

3

 

目的不可到達:

 

 

 

0

    網絡不可到達(9.3節)

 

·

 

1

    主機不可到達(9.3節)

 

·

 

2

    協議不可到達

 

·

 

3

    端口不可到達(6.5節)

 

·

 

4

    需要進行分片但設置了不分片比特(11.6節)

 

·

 

5

    源站路由選擇失敗(8.5節)

 

·

 

6

    目的網絡不認識

 

·

 

7

    目的主機不認識

 

·

 

8

    源主機被隔離(作廢不用)

 

·

 

9

    目的網絡被強制禁止

 

·

 

10

    目的主機被強制禁止

 

·

 

11

    由於服務類型TOS網絡不可到達(9.3節)

 

·

 

12

    由於服務類型TOS主機不可到達(9.3節)

 

·

 

13

    由於過濾通信被強制禁止

 

·

 

14

    主機越權

 

·

 

15

    優先權中止生效

 

·

4

0

源端被關閉(基本流控制,11.11節)

 

·

5

 

改變路由(9.5節):

 

·

 

0

    對網絡改變路由

 

·

 

1

    對主機改變路由

 

·

 

2

    對服務類型和網絡改變路由

 

·

 

3

    對服務類型和主機改變路由

 

·

8

0

請求回顯(Ping請求,第7章)

·

 

9

0

路由器通告(9.6節)

·

 

10

0

路由器請求(9.6節)

·

 

11

 

超時:

 

 

 

0

    傳輸期間生存時間爲0Traceroute, 8章)

 

·

 

1

    在數據報組裝期間生存時間爲011.5節)

 

·

12

 

參數問題:

 

 

 

0

    壞的IP首部(包括各種差錯)

 

·

 

1

    缺少必需的選項

 

·

13

0

時間戳請求(6.4節)

·

 

14

0

時間戳回答(6.4節)

·

 

15

0

信息回答(作廢不用)

·

 

16

0

信息回答(作廢不用)

·

 

17

0

地址掩碼請求(6.3節)

·

 

18

0

地址掩碼回答(6.3節)

·

 

6.3 ICMP報文類型

 

    這些規則是爲了防止過去允許ICMP差錯報文對廣播分組響應所帶來的廣播風暴。

 

6.3  ICMP地址掩碼請求與回答

    ICMP地址掩碼請求用於無盤系統在引導過程中獲取自己的子網掩碼(3.5節)。系統廣播它的ICMP請求報文。(這一過程與無盤系統在引導過程中用RARP獲取IP地址是類似的。)無盤系統獲取子網掩碼的另一個方法是BOOTP協議,我們將在第16章中介紹。ICMP地址掩碼請求和回答報文的格式如圖6.4所示。

 

6.4 ICMP地址掩碼請求和回答報文

 

    ICMP報文中的標識符和序列號字段由發送端任意選擇設定,這些值在回答中將被返回。這樣,發送端就可以把回答與請求進行匹配。

    我們可以寫一個簡單的程序(取名爲icmpaddrmask),它發送一份ICMP地址掩碼請求報文,然後打印出所有的回答。由於一般是把請求報文發往廣播地址,因此這裏我們也這樣做。目的地址(140.252.13.63)是子網140.252.13.32的廣播地址(圖3.12)。

 

    sun % icmpaddrmask 140.252.13.33

    received mask = ffffffe0, from 140.252.13.33   來自本機

    received mask = ffffffe0, from 140.252.13.35   來自bsdi

    received mask = ffff0000, from 140.252.13.34   來自svr4

 

    在輸出中我們首先注意到的是,從svr4返回的子網掩碼是差錯的。顯然,儘管svr4接口已經設置了正確的子網掩碼,但是SVR4還是返回了一個普通的B類地址掩碼,就好像子網並不存在一樣。

 

    svr4 % ifconfig emd0

    emd0: flags=23<UP,BROADCAST,NOTRAILERS>

            inet 140.252.13.34 netmask ffffffe0 broadcast 140.252.13.63

 

SVR4處理ICMP地址掩碼請求過程存在差錯。

    我們用tcpdump命令來查看主機bsdi上的情況,輸出如圖6.5所示。我們用-e參數來查看硬件地址。

 

6.5 發到廣播地址的ICMP地址掩碼請求

 

    注意,儘管在線路上什麼也看不見,但是發送主機sun也能接收到ICMP回答(帶有from ourself的輸出行)。這是廣播的一般特性:發送主機也能通過某種內部環回機制收到一份廣播報文拷貝。由於術語“廣播”的定義是指局域網上的所有主機,因此它必須包括髮送主機在內。(參見圖2.4,當以太網驅動程序識別出目的地址是廣播地址後,它就把分組送到網絡上,同時傳一份拷貝到環回接口。)

    接下來,bsdi廣播回答,而svr4卻只把回答傳給請求主機。通常,回答地址必須是單播地址,除非請求端的源IP地址是0.0.0.0,本例不屬於這種情況。因此,把回答發送到廣播地址是BSD/386的一個內部差錯。

 

(下面是原書p.73①的譯文)

    RFC規定,除非系統是地址掩碼的授權代理,否則它不能發送地址掩碼回答。(爲了成爲授權代理,它必須進行特殊配置,以發送這些回答。參見附錄E。)但是,正如我們從本例中看到的那樣,大多數主機在收到請求時都發送一個回答,甚至有一些主機還發送差錯的回答。

 

    最後一點可以通過下面的例子來說明。我們向本機IP地址和環回地址分別發送地址掩碼請求:

 

    sun % icmpaddrmask sun

    received mask= ff000000, from 140.252.13.33

 

    sun % icmpaddrmask localhost

    received mask= ff000000, from 127.0.0.1

 

 

    上述兩種情況下返回的地址掩碼對應的都是環回地址,即A類地址127.0.0.1。還有,我們從圖2.4可以看到,發送給本機IP地址的數據報(140.252.12.33)實際上是送到環回接口。ICMP地址掩碼回答必須是收到請求接口的子網掩碼(這是因爲多接口主機每個接口有不同的子網掩碼),因此兩種情況下地址掩碼接求都來自於環回接口。

 

6.4  ICMP時間戳請求與回答

    ICMP時間戳請求允許系統向另一個系統查詢當前的時間。返回的建議值是自午夜開始計算的毫秒數,協調的統一時間(Coordinated Universal Time, UTC)。(早期的參考手冊認爲UTC是格林尼治時間。)這種ICMP報文的好處是它提供了毫秒級的分辨率,而利用其它方法從別的主機獲取的時間(如某些Unix系統提供的rdate命令)只能提供秒級的分辨率。由於返回的時間是從午夜開始計算的,因此調用者必須通過其它方法獲知當時的日期,這是它的一個缺陷。

    ICMP時間戳請求和回答報文格式如圖6.6所示。

 

6.6 ICMP時間戳請求和回答報文

 

    請求端填寫發起時間戳,然後發送報文。回答系統收到請求報文時填寫接收時間戳,在發送回答時填寫發送時間戳。但是,實際上,大多數的實現把後面兩個字段都設成相同的值。(提供三個字段的原因是可以讓發送方分別計算髮送請求的時間和發送回答的時間。)

 

例子

    我們可以寫一個簡單程序(取名爲icmptime),給某個主機發送ICMP時間戳請求,並打印出返回的回答。它在我們的小互連網上運行結果如下:

 

(見原書p.74的①)

 

    程序打印出ICMP報文中的三個時間戳:發起時間戳(orig),接收時間戳(recv),以及發送時間戳(xmit)。正如我們在這個例子以及下面的例子中所看到的那樣,所有的主機把接收時間戳和發送時間戳都設成相同的值。

    我們還能計算出往返時間(rtt),它的值是收到回答時的時間值減去發送請求時的時間值。difference的值是接收時間戳值減去發起時間戳值。這些值之間的關係如圖6 7所示。

    如果我們相信RTT的值,並且相信RTT的一半用於請求報文的傳輸,另一半用於回答報文的傳輸,那麼爲了使本機時鐘與查詢主機的時鐘一致,本機時鐘需要進行調整,調整值是difference減去RTT的一半。在前面的例子中,bsdi的時鐘比sun的時鐘要慢7 ms8 ms

    由於時間戳的值是自午夜開始計算的毫秒數,即UTC,因此它們的值始終小於86,400,000 (24×60×60×1000)。這些例子都是在下午4:00以前運行的,並且在一個比UTC7個小時的時區,因此它們的值比82,800,0002300小時)要大是有道理的。

    如果我們對主機bsdi重複運行該程序數次,我們發現接收時間戳和發送時間戳的最後一位數總是0。這是因爲該版本的軟件(0.9.4版)只能提供10毫秒的時間分辨率。(說明參見附錄B。)

    如果我們對主機svr4運行該程序兩次,我們發現SVR4時間戳的最後三位數始終爲0

 

(見原書p.75的①)

 

    由於某種原因,SVR4ICMP時間戳中不提供毫秒級的分辨率。這樣,對秒以下的時間差調整將不起任何作用。

    如果我們對子網140.252.1上的其它主機運行該程序,結果表明其中一臺主機的時鐘與sun相差3.7秒,而另一個主機時鐘相差近75秒:

 

(見原書p.75的②)

 

    另一個令人感興趣的例子是路由器gateway(一個Cisco路由器)。這表明,當系統返回一個非標準時間戳值時(不是自午夜開始計算的毫秒數,UTC),它就用32 bit時間戳中的高位來表示。我們的程序證明了一點,在尖括號中打印出了接收和發送的時間戳值(在關閉高位之後)。另外,我們不能計算髮起時間戳和接收時間戳之間的時間差,因爲它們的單位不一致。

 

(見原書p.76的①)

 

    如果我們在這臺主機上運行該程序數次,會發現時間戳值顯然具有毫秒級的分辨率,而且是從某個起始點開始計算的毫秒數,但是起始點並不是午夜UTC。(例如,可能是從路由器引導時開始計數的毫秒數。)

    作爲最後一個例子,我們來比較sun主機和另一個已知是準確的系統時鐘----一個NTP stratum 1服務器。(下面我們會更多地討論NTP,網絡時間協議。)

 

(見原書p.76的②)

 

    如果我們把difference的值減去RTT的一半,結果表明sun主機上的時鐘要快38.551.5 ms

 

另一種方法

    還可以用另一種方法來獲得時間和日期。

    1. 我們在1.12節中描述了日期時間服務程序和時間服務程序。前者是以人們可讀的格式返回當前的時間和日期,是一行ASCII字符。我們可以用telnet命令來驗證這個服務:

 

(見原書p.76的③)

 

    另一方面,時間服務程序返回的是一個32 bit的二制進數值,表示自UTC190011午夜起算的秒數。這個程序是以秒爲單位提供的日期和時間。(前面我們提過的rdate命令使用的是TCP時間服務程序。)

    2. 嚴格的計時器使用網絡時間協議(NTP),該協議在RFC 1305中給出了描述[Mills 1992]。這個協議採用先進的技術來保證LANWAN上的一組系統的時鐘誤差在毫秒級以內。對計算機精確時間感興趣的讀者應該閱讀這份RFC文檔。

    3. 開放軟件基金會(OSF)的分佈式計算環境(DCE)定義了分佈式時間服務(DTS),它也提供計算機之間的時鐘同步。文獻[Rosenberg, Kenney and Fisher 1992]提供了該服務的其它細節描述。

    4. 伯克利大學的Unix系統提供守護程序timed(8),來同步局域網上的系統時鐘。不像NTPDTStimed不在廣域網範圍內工作。

 

6.5  ICMP端口不可達差錯

    最後兩小節我們來討論ICMP查詢報文----地址掩碼和時間戳查詢及回答。我們現在來分析一種ICMP差錯報文,即端口不可到達報文,它是ICMP目的不可到達報文中的一種,以此來看一看ICMP差錯報文中所附加的信息。我們使用UDP(見第11章)來查看它。

    UDP的規則之一是,如果收到一份UDP數據報而目的端口與某個正在使用的進程不相符,那麼UDP返回一個ICMP不可到達報文。我們可以用TFTP來強制生成一個端口不可到達報文。(TFTP將在第15章描述。)

    對於TFTP服務器來說,UDP的公共端口號是69。但是大多數的TFTP客戶程序允許我們用connect命令來指定一個不同的端口號。這裏,我們就用爲它指定爲8888

 

(見原書p.77的①)

 

    connect命令首先指定要連接的主機名及其端口號,接着用get命令來取文件。敲入get命令後,一份UDP數據報就發送到主機svr4上的8888端口。tcpdump命令引起的報文交換結果如圖6.8所示。

    UDP數據報送到svr4之前,要先發送一份ARP請求來確定它的硬件地址(第1行)。接着返回ARP回答(第2行),然後才發送UDP數據報(第3行)。(我們在tcpdump的輸出中保留ARP請求和回答是爲了提醒我們,這些報文交換可能在第一個IP數據報從一個主機發送到的另一個主機之前是必需的。在本書以後的章節中,如果這些報文與討論的題目不相關,那麼我們將省略它們。)

 

6.8 TFTP產生的ICMP端口不可到達差錯

 

    一個ICMP端口不可到達差錯是立刻返回的(第4行)。但是,TFTP客戶程序看上去似乎忽略了這個ICMP報文,而在5秒鐘之後又發送了另一份UDP數據報(第5行)。在客戶程序放棄之前重發了三次。

    注意,ICMP報文是在主機之間交換的,而不用目的端口號,而每個20字節的UDP數據報則是從一個特定端口(2924)發送到另一個特定端口(8888)。

    跟在每個UDP後面的數字20指的是UDP數據報中的數據長度。在這個例子中,20字節包括TFTP2個字節的操作代碼,9個字節以空字符結束的文件名temp.foo,以及9個字節以空字符結束的字符串netascii。(TFTP報文的詳細格式參見圖15.1。)

    如果用-e參數運行同樣的例子,我們可以看到每個返回的ICMP端口不可到達報文的完整長度。這裏的長度爲70字節,各字段分配如圖6.9所示。

 

6.9 UDP端口不可到達”例子中返回的ICMP報文

 

    ICMP的一個規則是,ICMP差錯報文(參見圖6.3的最後一列)必須包括生成該差錯報文的數據報IP首部(包含任何選項),還必須至少包括跟在該IP首部後面的前8個字節。在我們的例子中,跟在IP首部後面的前8個字節包含UDP的首部(圖11.2)。

    一個重要的事實是包含在UDP首部中內容是源端口號和目的端口號。就是由於目的端口號(8888)才導致產生了ICMP端口不可到達的差錯報文。接收ICMP的系統可以根據源端口號(2924)來把差錯報文與某個特定的用戶進程相關聯(在本例中是TFTP客戶程序)。

    導致差錯的數據報中的IP首部要被送回的原因是因爲IP首部中包含了協議字段,使得ICMP可以知道如何解釋後面的8個字節(在本例中是UDP首部)。如果我們來查看TCP首部(圖17.2,可以發現源端口和目的端口被包含在TCP首部的前8個字節中。

    ICMP不可到達報文的一般格式如圖6.10所示。

 

6.10 ICMP不可到達報文

 

    在圖6.3中,我們注意到有16種不同類型的ICMP不可到達報文,代碼分別從015ICMP端口不可到達差錯代碼是3。另外,儘管圖6.10指出了在ICMP報文中的第二個32 bit字必須爲0,但是當代碼爲4時(“需要分片但設置了不分片比特”),路徑MTU發現機制(2.9節)卻允許路由器把外出接口的MTU填在這個32 bit字的低16 bit中。我們在11.6節中給出了一個這種差錯的例子。

 

(下面是原書p.79①的譯文)

    儘管ICMP規則允許系統返回多於8個字節的產生差錯的IP數據報中的數據,但是大多數從伯克利派生出來的系統只返回8個字節。Solaris 2.2ip_icmp_return_data_bytes選項默認條件下返回前64個字節(E.4節)。

 

tcpdump時間系列

    在本書的後面章節中,我們還要以時間系列的格式給出tcpdump命令的輸出,如圖6.11所示。

 

6.11 發送到無效端口的TFTP請求的時間系列

 

    時間隨着向下而遞增,在圖左邊的時間標記與tcpdump命令的輸出是相同的(圖6.8.位於圖頂部的標記是通信雙方的主機名和端口號。需要指出的是,隨着頁面向下的y座標軸與真正的時間值不是成比例的。當出現一個有意義的時間段時,在本例中是每5秒之間的重發,我們就在時間系列的兩側作上標記。當UDPTCP數據正在被傳送時,我們用粗線的行來表示。

    ICMP報文返回時,爲什麼TFTP客戶程序還要繼續重發請求呢?這是由於網絡編程中的一個因素,即BSD系統不把從插口(socket)接收到的ICMP報文中的UDP數據通知用戶進程,除非該進程已經發送了一個connect命令給該插口。標準的BSD TFTP客戶程序並不發送connect命令,因此它永遠也不會收到ICMP差錯報文的通知。

    這裏需要注意的另一點是TFTP客戶程序所採用的不太好的超時重發算法。它只是假定5秒是足夠的,因此每隔5少就重傳一次,總共需要25秒鐘的時間。在後面我們將看到TCP有一個較好的超時重發算法。

 

(下面是原書p.81的①的譯文)

    TFTP客戶程序所採用的超時重傳算法已被RFC所禁用。不過,在作者所在子網上的三個系統以及Solaris 2.2仍然在使用它。AIX 3.2.2採用一種指數退避方法來設置超時值,分別在051535秒時重發報文,這正是所推薦的方法。我們將在第21章更詳細地討論超時問題。

    最後需要指出的是,ICMP報文是在發送UDP數據報3.5 ms後返回的,這與第7章我們所看到的Ping回答的往返時間差不多。

 

6.6  ICMP報文的4.4BSD處理

    由於ICMP覆蓋的範圍很廣泛,從致命差錯到信息差錯,因此即使在一個給定的系統實現中,對每個ICMP報文的處理都是不相同的。圖6.12的內容與圖6.3相同,它顯示的是4.4BSD系統對每個可能的ICMP報文的處理方法。

    如果最後一列標明是“內核”,那麼ICMP就由內核來處理。如果最後一列指明是“用戶進程”,那麼報文就被傳送到所有在內核中登記的用戶進程,以讀取收到的ICMP報文。如果不存在任何這樣的用戶進程,那麼報文就悄悄地被丟棄。(這些用戶進程還會收到所有其他類型的ICMP報文的拷貝,雖然它們應該由內核來處理,當然用戶進程只有在內核處理以後才能收到這些報文。)有一些報文完全被忽略。最後,如果最後一列標明的是引號內的一串字符,那麼它就是對應的Unix差錯。其中一些差錯,如TCP對發送端關閉的處理等,我們將在以後的章節中對它們進行討論。

 

(下面是圖6.12的譯文)

類型

代碼

描述

處理方法

0

0

回顯回答

用戶進程

3

 

目的不可到達:

 

 

0

    網絡不可到達

“無路由到達主機”

 

1

    主機不可到達

“無路由到達主機”

 

2

    協議不可到達

“連接被拒絕”

 

3

    端口不可到達

“連接被拒絕”

 

4

    需要進行分片但設置了不分片比特DF

“報文太長”

 

5

    源站路由選擇失敗

“無路由到達主機”

 

6

    目的網絡不認識

“無路由到達主機”

 

7

    目的主機不認識

“無路由到達主機”

 

8

    源主機被隔離(作廢不用)

“無路由到達主機”

 

9

    目的網絡被強制禁止

“無路由到達主機”

 

10

    目的主機被強制禁止

“無路由到達主機”

 

11

    由於服務類型TOS網絡不可到達

“無路由到達主機”

 

12

    由於服務類型TOS主機不可到達

“無路由到達主機”

 

13

    由於過濾通信被強制禁止

(忽略)

 

14

    主機越權

(忽略)

 

15

    優先權中止生效   

(忽略)

4

0

源站被抑制(quench)

TCP由內核處理,UDP則忽略

5

 

改變路由

 

 

0

    對網絡改變路由

內核更新路由表

 

1

    對主機改變路由

內核更新路由表

 

2

    對服務類型和網絡改變路由

內核更新路由表

 

3

    對服務類型和主機改變路由

內核更新路由表

8

0

回顯請求

 

9

0

路由器通告

用戶進程

10

0

路由器請求

用戶進程

11

 

超時:

 

 

0

    傳輸期間生存時間爲0

用戶進程

 

1

    在數據報組裝期間生存時間爲0

用戶進程

12

 

參數問題:

 

 

0

    壞的IP首部(包括各種差錯)

“協議不可用”

 

1

    缺少必需的選項

“協議不可用”

13

0

時間戳請求

內核產生回答

14

0

時間戳回答

用戶進程

15

0

信息請求(作廢不用)

(忽略)

16

0

信息回答(作廢不用)

用戶進程

17

0

地址掩碼請求

內核產生回答

18

0

地址掩碼回答

用戶進程

6.12 4.4BSD系統對ICMP報文的處理

 

6.7 小結

    本章對每個系統都必須包括的Internet控制報文協議進行了討論。圖6.3列出了所有的ICMP報文類型,其中大多數我們都將在以後的章節中加以討論。

    我們詳細討論了ICMP地址掩碼請求和回答以及時間戳請求和回答。這些是典型的請求-回答報文。二者在ICMP報文中都標識符和序號。發送端應用程序在標識字段內存入一個唯一的數值,以區別於其它進程的回答。序號字段使得客戶程序可以在回答和請求之間進行匹配。

    我們還討論了ICMP端口不可到達差錯,一種常見的ICMP差錯。我們對返回的ICMP差錯信息進行了分析:導致差錯的IP數據報的首部及後序8個字節。這個信息對於ICMP差錯的接收方來說是必要的,可以更多地瞭解導致差錯的原因。這是因爲TCPUDP都在它們的首部前8個字節中存入源端口號和目的端口號。

    最後,我們第一次給出了按時間先後的tcpdump輸出,這種表現方式的輸出在本書後面的章節中會經常用到。

 

習題

6.1 6.2節的末尾我們列出了5種不發送ICMP差錯報文的特殊條件。如果這些條件不滿足而我們又在局域網上向一個似乎不存在的端口號發送一份廣播UDP數據報,這時會發生什麼樣的情況?

6.2 閱讀RFC [Braden 1989a],注意生成一個ICMP端口不可到達差錯是否爲“必須”,“應該”或者“可能”。這些信息所在的頁碼和章節是多少?

6.3 閱讀RFC 1349 [Almquist 1992],看看IP的服務類型字段(圖3.2)是如何被ICMP設置的?

6.4 如果你的系統提供netstat命令,請用它來查看接收和發送的ICMP報文類型。

 

69

7  Ping程序

 

7.1 引言

    ping”這個名字來自於聲納定位操作。Ping程序由Mike Muuss編寫,目的是爲了測試另一臺主機是否可達。該程序發送一份ICMP回顯請求報文給主機,並等待返回ICMP回顯回答。(圖6.3列出了所有的ICMP報文類型。)

    一般來說,如果你不能Ping到某臺主機,那麼你就不能Telnet或者FTP到那臺主機。反過來,如果你不能Telnet到某臺主機,那麼通常可以用Ping程序來確定問題出在哪裏。Ping程序還能測出到這臺主機的往返時間,以表明該主機離我們有“多遠”。

    在本章中,我們將使用Ping程序作爲診斷工具來深入剖析ICMPPing還給我們提供了檢測IP記錄路由和時間戳選項的機會。文獻[Stevens 1990]的第11章提供了Ping程序的源代碼。

 

(下面是原書p.85①的譯文)

    幾年前我們還可以作出這樣沒有限定的斷言,如果我們不能Ping到某臺主機,那麼就不能TelnetFTP那臺主機。隨着Internet安全意識的增強,出現了提供訪問控制清單的路由器和防火牆,那麼像這樣沒有限定的斷言不再成立了。一臺主機的可達性可能不只取決於IP層是否可達,還取決於使用何種協議以及端口號。Ping程序的運行結果可能顯示某臺主機不可達,但我們可以用Telnet遠程登錄到該臺主機的25號端口(郵件服務器)。

 

7.2  Ping程序

    我們稱發送回顯請求的ping程序爲客戶,而稱被ping的主機爲服務器。大多數的TCP/IP實現都在內核中直接支持Ping服務器——這種服務器不是一個用戶進程。(我們在第6章中描述的兩種ICMP查詢服務,地址掩碼和時間戳請求,也都是直接在內核中進行處理的。)

    ICMP回顯請求和回顯回答報文如圖7.1所示。

 

7.1 ICMP回顯請求和回顯回答報文格式

 

    對於其他類型的ICMP查詢報文,服務器必須響應標識符和序號字段。另外,客戶發送的選項數據必須回顯,假設客戶對這些信息都會感興趣。

    Unix系統在實現ping程序時是把ICMP報文中的標識符字段置成發送進程的ID號。這樣即使在同一臺主機上同時運行了多個ping程序實例,ping程序也可以識別出返回的信息。

    序號從0開始,每發送一次新的回顯請求就加1ping程序打印出返回的每個分組的序號,允許我們查看是否有分組丟失,失序或重複。IP是一種最好的數據報傳遞服務,因此這三個條件都有可能發生。

    舊版本的ping程序曾經以這種模式運行,即每秒發送一個回顯請求,並打印出返回的每個回顯回答。但是,新版本的實現需要加上-s參數才能以這種模式運行。默認情況下,新版本的ping程序只發送一個回顯請求,如果收到回顯回答則輸出“host is alive”,否則在20秒內沒有收到回答就輸出“no answer”(沒有回答)。

 

LAN輸出

    在局域網LAN上運行ping程序的結果輸出一般有如下格式:

 

(見原書p.86的①)

 

    當返回ICMP回顯回答時,要打印出序號和TTL,並計算往返時間。(TTL位於IP首部中的生存時間字段。當前的BSD系統中的ping程序每次收到回顯回答時都打印出收到的TTL----有些系統並不這樣做。我們將在第8章中通過traceroute程序來介紹TTL的用法。)

    我們從上面的輸出中可以看出,回顯回答是以發送的次序返回的(012等等)。

    ping程序通過在ICMP報文數據中存放發送請求的時間值來計算往返時間。當回答返回時,用當前時間減去存放在ICMP報文中的時間值,即是往返時間。注意,在發送端bsdi上,往返時間的計算結果都爲0 ms。這是因爲程序使用的計時器分辨率低的原因。BSD/386版本0.9.4系統只能提供10 ms級的計時器。(我們在附錄B中有更詳細的介紹。)在後面的章節中,當我們在具有較高分辨率計時器的系統上(Sun)查看tcpdump輸出時會發現,ICMP回顯請求和回顯回答的時間差在4 ms以下。

    輸出的第一行包括目的主機的IP地址,儘管我們指定的是它的名字(svr4)。這說明名字已經經過解析器被轉換成IP地址了。我們將在第14章介紹解析器和DNS。現在,我們發現,如果敲入ping命令,幾秒鐘過後會在第一行打印出IP地址,DNS就是利用這段時間來確定主機名所對應的IP地址。

    本例中的tcpdump輸出如圖7.2所示。

 

7.2 LAN上運行ping程序的結果

 

    從發送回顯請求到收到回顯回答,時間間隔始終爲3.7 ms。我們還可以看到,回顯請求大約每隔1秒鐘發送一次。

    通常,第一個往返時間值要比其他的大。這是由於目的端的硬件地址不在ARP高速緩存中的緣故。正如我們在第4章中看到的那樣,在發送第一個回顯請求之前要發送一個ARP請求並接收ARP回答,這需要花費幾毫秒的時間。下面的例子說明了這一點:

 

(見原書p.88的①)

 

    第一個RTT中多的3 ms很可能就是因爲發送ARP請求和接收ARP回答所花費的時間。

    這個例子運行在sun主機上,它提供的是具有微秒級分辨率的計時器,但是ping程序只能打印出毫秒級的往返時間。在前面運行於BSD/386 0.9.4版上的例子中,打印出來的往返時間值爲0 ms,這是因爲計時器只能提供10 ms的誤差。下面的例子是BSD/386 1.0版的輸出,它提供的計時器也具有微秒級的分辨率,因此ping程序的輸出結果也具有較高的分辨率。

 

(見原書p.88的②)

 

WAN輸出

    在一個廣域網WAN上,結果會有很大的不同。下面的例子是在某個工作日的下午即Internet具有正常通信量時的運行結果:

 

(見原書p.88的③)

 

    這裏,序號爲1234610111213的回顯請求或回顯回答在某個地方丟失了。另外,我們注意到往返時間發生了很大的變化。(像52%這樣高的分組丟失率是不正常的。即使是在工作日的下午,對於Internet來說也是不正常的,。)

    通過廣域網還有可能看到重複的分組(即相同序號的分組被打印兩次或更多次),失序的分組(序號爲N + 1的分組在序號爲N的分組之前被打印。)

 

線路SLIP鏈接

    讓我們再來看看SLIP鏈路上的往返時間,因爲它們經常運行於低速的異步方式,如9600 b/s或更低。回想我們在2.10節計算的串行線路吞吐量。針對這個例子,我們把主機bsdislip之間的SLIP鏈路傳輸速率設置爲1200 b/s

    下面我們可以來估計往返時間。首先,我們從前面的Ping程序輸出例子中可以注意到,默認情況下發送的ICMP報文有56個字節。再加上20個字節的IP首部和8個字節的ICMP首部,IP數據報的總長度爲84字節。(我們可以運行tcpdump -e命令查看以太網數據幀來驗證這一點。)另外,從2.4節我們可以知道,至少要增加兩個額外的字節:在數據報的開始和結尾加上END字符。此外,SLIP幀還有可能再增加一些字節,但這取決於數據報中每個字節的值。對於1200 b/s這個速率來說,由於每個字節含有8 bit數據,1 bit起始位和1 bit結束位,因此傳輸速率是每秒120個字節,或者說每個字節8.33 ms。所以我們可以估計需要143386×8.33×2 ms 。(乘2是因爲我們計算的是往返時間。)

    下面的輸出證實了我們的計算:

 

(見原書p.89的①)

 

    (對於SVR4來說,如果每秒鐘發送一次請求則必須帶-s參數。)往返時間大約是1.5秒,但是程序仍然每間隔1秒鐘發送一次ICMP回顯請求。這說明在第一個回顯回答返回之前(1.480秒時刻)就已經發送了兩次回顯請求(分別在0秒和1秒時刻)。這就是爲什麼總結行指出丟失了一個分組。實際上分組並未丟失,很可能仍然在返回的途中。

    我們在第8章討論traceroute程序時將回頭再討論這種低速的SLIP鏈路。

 

拔號SLIP鏈路

    對於拔號SLIP鏈路來說,情況有些變化,因爲在鏈路的兩端增加了調制解調器。用在sunnetb系統之間的調制解調器提供的是V.32調製方式(9600 b/s),V.42錯誤控制方式(也稱作LAP-M),以及V.42bis數據壓縮方式。這表明我們針對線路鏈路參數進行的簡單計算不再準確了。

    很多因素都有可能影響。調制解調器帶來了時延。隨着數據的壓縮,分組長度可能會減小,但是由於使用了錯誤控制協議,分組長度又可能會增加。另外,接收端的調制解調器只能在驗證了循環檢驗字符(檢驗和)後才能釋放收到的數據。最後,我們還要處理每一端的計算機異步串行接口,許多操作系統只能在固定的時間間隔內,或者收到若干字符後者纔去讀這些接口。

    作爲一個例子,我們在sun主機上ping主機gemini,輸出結果如下:

 

(見原書p.90的①)

 

    注意,第一個RTT不是10 ms的整數倍,但是其它行都是10 ms的整數倍。如果我們運行該程序若干次,發現每次結果都是這樣。(這並不是由sun主機上的時鐘分辨率造成的結果,因爲根據附錄B中的測試結果可以知道它的時鐘能提供毫秒級的分辨率。)

    另外還要注意,第一個RTT要比其他的大,而且依次遞減,然後徘徊在280300 ms之間。我們讓它運行一分鐘到兩分鐘,RTT一直處於這個範圍,不會低於260 ms。如果我們以9600 b/s的速率計算RTT(習題7.2),那麼我們觀察到的值應該大約是估計值的1.5倍。

    如果運行ping程序60秒鐘並計算觀察到的RTT的平均值,我們發現在V.42V.42bis模式下平均值爲277 ms。(這要比上個例子打印出來的平均值要好,因爲運行時間較長,這樣就把開始較長的時間平攤了。)如果我們關閉V.42bis數據壓縮方式,平均值爲330 ms。如果我們關閉V.42錯誤控制方式(它同時也關閉了V.42bis數據壓縮方式),平均值爲300 ms。這些調制解調器的參數對RTT的影響很大,使用錯誤控制和數據壓縮方式似乎效果最好。

 

7.3  IP記錄路由選項

    ping程序爲我們提供了查看IP記錄路由(RR)選項的機會。大多數不同版本的ping程序都提供-R參數,以提供記錄路由的功能。它使得ping程序在發送出去的IP數據報中設置IP RR選項(該IP數據報包含ICMP回顯請求報文)。這樣,每個處理該數據報的路由器都把它的IP地址放入選項字段中。當數據報到達目的端時,IP地址清單應該複製到ICMP回顯回答中,這樣返回途中所經過的路由器地址也被加入清單中。當ping程序收到回顯回答時,它就打印出這份IP地址清單。

    這個過程聽起來簡單,但存在一些缺陷。源端主機生成RR選項,中間路由器對RR選項的處理,以及把ICMP回顯請求中的RR清單複製到ICMP回顯回答中,所有這些都是選項功能。幸運的是,現在的大多數系統都支持這些選項功能,只是有一些系統不把ICMP請求中的IP清單複製到ICMP回答中。

    但是,最大的問題是IP首部中只有有限的空間來存放IP地址。我們從圖3.1可以看到,IP首部中的首部長度字段只有4 bit,因此整個IP首部最長只能包括1532 bit長的字(即60個字節)。由於IP首部固定長度爲20字節,RR選項用去3個字節(下面我們再討論),這樣只剩下37個字節(60 - 20 - 3)來存放IP地址清單,也就是說只能存放9IP地址。對於早期的ARPANET來說,9IP地址似乎是很多了,但是現在看來是非常有限的。(在第8章中,我們將用Traceroute工具來確定數據報的路由。)除了這些缺點,記錄路由選項工作得很好,爲詳細查看如何處理IP選項提供了一個機會。

    IP數據報中的RR選項的一般格式如圖7.3所示。

 

7.3 IP首部中的記錄路由選項的一般格式

 

    code是一個字節,指明IP選項的類型。對於RR選項來說,它的值爲7lenRR選項總字節長度,在這種情況下爲39。(儘管可以爲RR選項設置比最大長度小的長度,但是ping程序總是提供39字節的選項字段,最多可以記錄9IP地址。由於IP首部中留給選項的空間有限,它一般情況都設置成最大長度。)

    ptr稱作指針字段。它是一個基於1的指針,指向存放下一個IP地址的位置。它的最小值爲4,指向存放第一個IP地址的位置。隨着每個IP地址存入清單,ptr的值分別爲81216,最大到36。當記錄下9IP地址後,ptr的值爲40,表示清單已滿。

    當路由器(根據定義應該是多穴的)在清單中記錄IP地址時,它應該記錄哪個地址呢?是入口地址還是出口地址?爲此,RFC 791 [Postel 1981a]指定路由器記錄出口IP地址。我們在後面將看到,當原始主機(運行ping程序的主機)收到帶有RR選項的ICMP回顯回答時,它也要把它的入口IP地址放入清單中。

 

正常的例子

    我們舉一個用RR選項運行ping程序的例子。我們在主機svr4上運行ping程序到主機slip。一箇中間路由器(bsdi)將處理這個數據報。下面是svr4的輸出結果:

 

(見原書p.92的①)

 

    分組所經過的四站如圖7.4所示(每個方向各有兩站),每一站都把自己的IP地址加入RR清單。

 

7.4 帶有記錄路由選項的ping程序

 

    路由器bsdi在不同方向上分別加入了不同的IP地址。它始終是把出口的IP地址加入清單。我們還可以看到,當ICMP回顯回答到達原始系統(svr4)時,它把自己的入口IP地址也加入清單中。

    我們還可以通過運行帶有-v參數的tcpdump命令來查看主機sun上進行的分組交換(參見IP選項)。輸出如圖7.5所示。

 

7.5 記錄路由選項的tcpdump輸出

 

    輸出中optlen=40表示在IP首部中有40個字節的選項空間。(IP首部長度必須爲4字節的整數倍。)RR{39}的意思是記錄路由選項已被設置,它的長度字段是39。然後是9IP地址,符號“#”用來標記RR選項中的ptr字段所指向的IP地址。由於我們是在主機sun上觀察這些分組(參見圖7.4),因此我們所能看到ICMP回顯請求中的IP地址清單是空的,而ICMP回顯回答中有3IP地址。我們省略了tcpdump輸出中的其它行,因爲它們與圖7.5基本一致。

    位於路由信息末尾的標記EOL表示IP選項“end of list”(清單結束)的值。EOL選項的值可以爲0。這時表示39個字節的RR數據位於IP首部中的40字節空間中。由於在數據報發送之前空間選項被設置爲0,因此跟在39個字節的RR數據之後的0字符就被解釋爲EOL。這正是我們所希望的結果。如果在IP首部中的選項字段中有多個選項,在開始下個選項之前必須填入空白字符,另外還可以用另一個值爲1的特殊字符NOP(“no operation”)。

 

(下面是原書p.93①的譯文)

    在圖7.5中,SVR4把回顯請求中的TTL字段設爲32BSD/386設爲255。(它打印出的值爲254是因爲路由器bsdi已經將其減去1。)新的系統都把ICMP報文中的TTL設爲最大值(255)。

    在作者使用的三個TCP/IP系統中,BSD/386SVR4都支持記錄路由選項。這就是說,當轉發數據報時,它們都能正確地更新RR清單,而且能正確地把接收到的ICMP回顯請求中的RR清單複製到出口ICMP回顯回答中。雖然SunOS 4.1.3在轉發一個數據報時能正確更新RR清單,但是不能複製RR清單。Solaris 2.x對這個問題已作了修改。

 

異常的輸出

    下面的例子是作者觀察到的,我們把它作爲第9章討論ICMP間接報文的起點。我們在子網140.252.1子網上ping主機aix(在主機sun上通過拔號SLIP連接可以訪問),並帶有記錄路由選項。在slip主機上運行有如下輸出結果:

 

(見原書p.94的①)

 

    我們已經在主機bsdi上運行過這個例子。現在我們選擇slip來運行它,觀察RR清單中所有的9IP地址。

    在輸出中令人感到疑惑的是,爲什麼傳出的數據報(ICMP回顯請求)直接從netb傳到aix,而返回的數據報(ICMP回顯回答)卻從aix開始經路由器gateway再到netb?這裏看到的正是下面我們將要描述的IP路由選擇的一個特點。數據報經過的路由如圖7.6所示。

 

7.6 運行帶有記錄路由選項的ping程序,顯示IP路由選擇的特點

 

    問題是aix不知道要把目的地爲子網140.252.13IP數據報發到主機netb上。相反,aix在它的路由表中有一個默認項,它指明當沒有明確某個目的主機的路由時,就把所有的數據報發往默認項指定的路由器gateway。路由器gateway比子網140.252.1上的任何主機都具備更強的路由選擇能力。(在這個以太網上有超過150臺主機,每臺主機的路由表中都有一個默認項指向路由器gateway,這樣就不用在每臺主機上都運行一個路由選擇守護程序。)

    這裏沒有回答的一個問題是爲什麼gateway不直接發送ICMP報文改變路由到aix9.5節),以更新它的路由表?由於某種原因(很可能是由於數據報產生的改變路由是一份ICMP回顯請求報文),改變路由並沒有產生。但是如果我們用Telnet登錄到aix上的daytime服務器,ICMP就會產生改變路由,因而它在aix上的路由表也隨之更新。如果我們接着執行ping程序並帶有記錄路由選項,其路由顯示錶明數據報從netbaix,然後返回netb,而不再經過路由器gateway。在9.5節中我們將更詳細地討論ICMP改變路由的問題。

 

7.4  IP時間戳選項

    IP時間戳選項與記錄路由選項類似。IP時間戳選項的格式如圖7.7所示(請與圖7.3進行比較)。

 

7.7 IP首部中時間戳選項的一般格式

 

    時間戳選項的代碼爲0x44。其它兩個字段lenptr與記錄路由選項相同:選項的總長度(一般爲3640)和指向下一可用空間的指針(5913,等)。

接下來的兩個字段是4 bit的值:OF表示溢出字段,FL表示標誌字段。時間戳選項的操作根據標誌字段來進行,如圖7.8所示。

 

(下面是圖7.8的譯文)

標誌

描述

0

只記錄時間戳,正如我們在圖7.7看到的那樣。

1

每臺路由器都記錄它的IP地址和時間戳。在選項列表中只有存放四對地址和時間戳的空間。

3

發送端對選項列表進行初始化,存放了4IP地址和四個取值爲0的時間戳值。只有當列表中的下一個IP地址與當前路由器地址相匹配時,才記錄它的時間戳。

7.8 時間戳選項不同標誌字段值的意義

 

    如果路由器由於沒有空間而不能增加時間戳選項,那麼它將增加溢出字段的值。

    時間戳的取值一般爲自午夜開始計的毫秒數,UTC,與ICMP時間戳請求和回答相類似。如果路由器不使用這種格式,它就可以插入任何它使用的時間表示格式,但是必須打開時間戳中的高位以表明爲非標準值。

    與我們遇到的記錄路由選項所受到的限制相比,時間戳選項遇到情況要更壞一些。如果我們要同時記錄IP地址和時間戳(標誌位爲1),那麼就可以同時存入其中的四對值。只記錄時間戳是沒有用處的,因爲我們沒有標明時間戳與路由器之間的對應關係(除非我們有一個永遠不變的拓撲結構)。標誌值取3會更好一些,因爲我們可以插入時間戳的路由器。一個更爲基本的問題是,你很可能無法控制任何給定路由器上時間戳的正確性。這使得試圖用IP選項來計算路由器之間的跳站數是徒勞的。我們將看到(第8章)traceroute程序可以提供一種更好的方法來計算路由器之間的跳數。

 

7.5 小結

    ping程序是對兩個TCP/IP系統連通性進行測試的基本工具。它只利用ICMP回顯請求和回顯回答報文,而不用經過傳輸層(TCP/UDP)。Ping服務器一般在內核中實現ICMP的功能。

    我們分析了在LANWAN以及SLIP鏈路(拔號和線路)上運行ping程序的輸出結果,並對串行線路上的SLIP鏈路吞吐量進行了計算。我們還討論並使用了ping程序的IP記錄路由選項。利用該IP選項,我們可以看到它是如何經常使用默認路由的。在第9章我們將再次回到這個討論主題。另外,我們還討論了IP 時間戳選項,但它在實際使用時有所限制。

 

習題

7.1 請畫出7.2節中ping輸出的時間線。

7.2 若把bsdislip主機之間的SLIP鏈路設置爲9600 b/s,請計算這時的RTT。假定默認的數據是56字節。

7.3 當前BSD版中的ping程序允許我們爲ICMP報文的數據部分指定一種模式。(數據部分的前8個字節不用來存放模式,因爲它要存放發送報文的時間。)如果我們指定的模式爲0xc0,請重新計算上一題中的答案。(提示:閱讀2.4節。)

7.4 使用壓縮SLIPCSLIP,見2.5節)是否會影響我們在7.2節中看到的ping輸出中的時間值?

7.5 在圖2.4中,ping環回地址與ping主機以太網地址會出現什麼不同?

  

 

 

 

77

8  Traceroute程序

 

8.1 引言

    Van Jacobson編寫的Traceroute程序是一個能更深入探索TCP/IP協議的方便可用的工具。儘管不能保證從源端發往目的端的兩份連續的IP數據報具有相同的路由,但是大多數情況下是這樣的。Traceroute程序可以讓我們看到IP數據報從一臺主機傳到另一臺主機所經過的路由。Traceroute程序還可以讓我們使用IP源路由選項。

 

(下面是原書p.97①的譯文)

    使用手冊上說:“程序由Steve Deering提議,由Van Jacobson實現,並由許多其他人根據C. Philip Wood, Tim Seaver Ken Adelman等人提出的令人信服的建議或補充意見進行調試。”

 

8.2  Traceroute程序的操作

    7.3節中,我們描述了IP記錄路由選項(RR)。爲什麼不使用這個選項而另外開發一個新的應用程序?有三個方面的原因。首先,原先並不是所有的路由器都支持記錄路由選項,因此該選項在某些路徑上不能使用。(Traceroute程序不需要中間路由器具備任何特殊的或可選的功能。)

    其次,記錄路由一般是單向的選項。發送端設置了該選項,那麼接收端不得不從收到的IP首部中提取出所有的信息然後全部返回給發送端。在7.3節中,我們看到大多數Ping服務器的實現(內核中的ICMP回顯回答功能)把接收到的RR清單返回,但是這樣使得記錄下來的IP地址翻了一番(一來一回),這樣會受到一些限制,這一點我們在下一段討論。(Traceroute程序只需要目的端運行一個UDP模塊----其他不需要任何特殊的服務器應用程序。)

    最後一個原因也是最主要的原因是,IP首部中留給選項的空間有限,不能存放當前大多數的路徑。在IP首部選項字段中最多隻能存放9IP地址。在原先的ARPANET中這是足夠的,但是對現在來說是遠遠不夠的。

    Traceroute程序使用ICMP報文和IP首部中的TTL字段。TTL字段(生存週期)是由發送端初始設置一個8 bit字段。推薦的初始值由分配數字RFC指定,當前值爲64。較老版本的系統經常初始化爲1532。我們從第7章中的一些ping程序例子中可以看出,發送ICMP回顯回答時經常把TTL設爲最大值255

    每個處理數據報的路由器都需要把TTL的值減1或減去數據報在路由器中停留的秒數。由於大多數的路由器轉發數據報的時延都小於1秒鐘,因此TTL最終成爲一個跳站的計數器,所經過的每個路由器都將其值減1

 

(下面是原書p.98①的譯文)

    RFC 1009 [Braden and Postel 1987]指出,如果路由器轉發數據報的時延超過1秒,那麼它將把TTL值減去所消耗的時間(秒數)。但很少有路由器這麼實現。新的路由器需求文檔RFC [Almquist 1993]爲此指定它爲可選擇功能,允許把TTL看成一個跳站計數器。

 

    TTL字段的目的是防止數據報在路由選擇時無休止地在網絡中流動。例如,當路由器癱瘓或者兩個路由器之間的連接丟失時,路由選擇協議有時會去檢測丟失的路由並一直進行下去。在這段時間內,數據報可能在循環迴路被終止。TTL字段就是在這些循環傳遞的數據報上加上一個生存上限。

    當路由器收到一份IP數據報,如果其TTL字段是01,則路由器不轉發該數據報。(接收到這種數據報的目的主機可以將它交給應用程序,這是因爲不需要轉發該數據報。但是在通常情況下,系統不應該接收TTL字段爲0的數據報。)相反地,路由器將該數據報丟棄並給信源機發一份ICMP“超時”信息。Traceroute程序的關鍵在於包含這份ICMP信息的IP報文的信源地址是該路由器的IP地址。

    我們現在可以猜想一下Traceroute程序的操作過程。它發送一份TTL字段爲1IP數據報給目的主機。處理這份數據報的第一個路由器將TTL值減1,丟棄該數據報,併發回一份超時ICMP報文。這樣就得到了該路徑中的第一個路由器的地址。然後Traceroute程序發送一份TTL值爲2的數據報,這樣我們就可以得到第二個路由器的地址。繼續這個過程直至該數據報到達目的主機。但是目的主機哪怕接收到TTL值爲1IP數據報,也不會丟棄該數據報併產生一份超時ICMP報文,這是因爲數據報已經到達其最終目的地。那麼我們該如何判斷已經到達目的主機了呢?

    Traceroute程序發送一份UDP數據報給目的主機,但它選擇一個不可能的值作爲UDP端口號(大於30,000),使目的主機的任何一個應用程序都不可能使用該端口。因爲,當該數據報到達時,將使目的主機的UDP模塊產生一份“端口不可到達”錯誤(見6.5節)的ICMP報文。這樣,Traceroute程序所要做的就是區分接收到的ICMP信息是超時還是端口不可到達,以判斷什麼時候結束。

 

(下面是原書p.99①的譯文)

    Traceroute程序必須可以爲發送的數據報設置TTL字段。並非所有與TCP/IP接口的程序都支持這項功能,同時並非所有的實現都支持這項能力,但目前大部分系統都支持這項功能,並可以運行Traceroute程序。這個程序界面通常要求用戶具有超級用戶權限,這意味着它可能需要特殊的權限以在你的主機上運行該程序。

 

8.3  局域網輸出

    我們現在已經做好運行Traceroute程序並觀察其輸出的準備了。我們將使用從svr4slip,經路由器bsdi的簡單互連網(見內封面)。 bsdislip之間是9600 b/sSLIP鏈路。

 

(見原書p.99的②)

 

    輸出的第一個無標號行給出了目的主機名和其IP地址,指出traceroute程序最大的TTL字段值爲3040字節的數據報包含20字節IP首部,8字節的UDP首部和12字節的用戶數據。(12字節的用戶數據包含每發一個數據報就加1的序號,送出TTL的副本以及發送數據報的時間。)

    輸出的後面兩行以TTL開始,接下來是主機或路由器名,以及其IP地址。對於每個TTL值,發送3份數據報。每接收到一份ICMP報文,就計算並打印出往返時間。如果在5秒種內仍未收到3份數據報的任意一份的響應,則打印一個星號,併發送下一份數據報。在上述輸出結果中,TTL字段爲1的前三份數據報的ICMP報文分別在201010 ms收到。TTL字段爲23份數據報的ICMP報文則在120 ms後收到。由於TTL字段爲2到達最終目的主機,因此程序就此停止。

    往返時間是由發送主機的traceroute程序計算的。它是指從traceroute程序到該路由器的總往返時間。如果我們對每段路徑的時間感興趣,可以用TTL字段爲N+1所打印出來的時間減去TTL字段爲N的時間。

    8.1給出了tcpdump的運行輸出結果。正如我們所預想的那樣,第一個發往bsdi的探測數據報的往返時間是20 ms而後面兩個數據報往返時間是10 ms的原因是發生了一次ARP交換。tcpdump結果證實了確實是這種情況。

    目的主機UDP端口號最開始設置爲33435,且每發送一個數據報加1。可以通過命令行選項來改變開始的端口號。UDP數據報包含12個字節的用戶數據,我們在前面traceroute程序輸出的40字節數據報中已經對其進行了描述。

    後面tcpdump打印出了TTL字段爲1IP數據報的註釋[ttl 1]。當TTL值爲01時,tcpdump打印出這條信息,以提示我們數據報中有些不太尋常之處。在這裏我們可以預見到TTL值爲1,而在其它一些應用程序中,它可以警告我們數據報可能無法到達其最終目的主機。我們不可能看到路由器傳送一個TTL值爲0的數據報,除非發出該數據報的該路由器已經崩潰。

 

8.1  svr4sliptraceroute程序示例的tcpdump輸出結果

 

    因爲bsdi路由器將TTL值減到0,因此我們預計它將發回“傳送超時”的ICMP報文。即使這份被丟棄的IP報文發送往slip,路由器也會發回ICMP報文。

    有兩種不同的ICMP“超時”報文(見p.71頁的圖6.3),它們的ICMP報文中code字段不同。圖8.2給出了這種ICMP錯誤報文的格式。

 

8.2 ICMP超時報文

 

    我們所討論的ICMP報文是在TTL值等於0時產生的,其code字段爲0

    主機在組裝分片時可能發生超時,這時,它將發送一份“組裝報文超時”的ICMP報文。(我們將在11.5節討論分片和組裝。)這種錯誤報文將code字段置1

    8.1的第9-14行對應於TTL23份數據報。這3份報文到達最終目的主機,併產生一份ICMP端口不可到達報文。

    計算出SLIP鏈路的往返時間是很有意義的,就象我們在7.2節中所舉的Ping例子,將鏈路值設置爲1200 b/s一樣。發送出動的UDP數據報共42個字節,包括12字節的數據,8字節UDP首部,20字節的IP首部以及(至少)2字節的SLIP幀(2.4節)。但是與Ping不一樣的是,返回的數據報大小是變化的。從圖6.9可以看出,返回的ICMP報文包含發生差錯的數據報的IP首部以及緊隨該IP首部的8字節數據(在traceroute程序中,即UDP首部)。這樣,總共就是20 + 8 + 20 + 8 + 2,即58字節。在數據速率爲960 B/s的情況下,預計的RTT就是(42 + 58/960),即104 ms。這個值與svr4上所估算出來的110 ms是吻合的。

    8.1中的源端口號(42804)看起來有些大。traceroute程序將其發送的UDP數據報的源端口號設置爲Unix進程號與32768之間的邏輯或值。對於在同一臺主機上多次運行traceroute程序的情況,每個進程都查看ICMP返回的UDP首部的源端口號,並且只處理那些對自己發送回答的報文。

    關於traceroute程序還有一些必須指出的事項。首先,並不能保證現在的路由也是將來所要採用的路由,甚至兩份連續的IP數據報都可能採用不同的路由。如果在運行程序時,路由發生改變,你就會觀察到這種變化,這是因爲對於一個給定的TTL,如果其路由發生變化,traceroute程序將打印出新的IP地址。

    第二,不能保證ICMP報文的路由與traceroute程序發送的UDP數據報採用同一路由。這表明所打印出來的往返時間可能並不能真正體現數據報發出和返回的時間差。(如果UDP數據報從信源到路由器的時間是1秒,而ICMP報文用另一條路由返回信源用了3秒時間,則打印出來的往返時間是4秒。)

    第三,返回的ICMP報文中的信源IP地址是UDP數據報到達的路由器接口的IP地址。這與IP記錄路由選項(7.3節)不同,記錄的IP地址指的是發送接口地址。由於每個定義的路由器都有2個或更多的接口,因此,從A主機到B主機上運行traceroute程序和從B主機到A主機上運行traceroute程序所得到的結果可能是不同的。事實上,如果我們從slip主機到svr4上運行traceroute程序,其輸出結果變成了:

 

(見原書p.101的①)

 

    這次打印出來的bsdi主機的IP地址是140.252.13.66,對應於SLIP接口,而上次的地址是140.252.13.35,是以太網接口地址。由於traceroute程序同時也打印出與IP地址相關的主機名,因而主機名也可能變化。(在我們的例子中,bsdi上的兩個接口都採用相同的名字。)

    考慮圖8.3的情況。它給出了兩個局域網通過一個路由器相連的情況。兩個路由器通過一個點對點的鏈路相連。如果我們在左邊LAN的一個主機上運行traceroute程序,那麼它將發現路由器的IP地址爲if1if3。但在另一種情況下,就會發現打印出來的IP地址爲if4if2if2if3有着同樣的網絡號,而另兩個接口則有着不同的網絡號。

 

8.3  traceroute程序打印出的接口標識

 

    最後,在廣域網情況下,如果traceroute程序的輸出是可讀的域名形式,而不是IP地址形式,那麼會更好理解一些。但是由於traceroute程序接收到ICMP報文時,它所獲得的唯一信息就是IP地址,因此,在給定IP地址的情況下,它做一個“反向域名查看”工作來獲得域名。這就需要路由器或主機的管理員正確配置其反向域名查看功能(並非所有的情況下都是如此)。我們將在14.5節描述如何使用DNS將一個IP地址轉換成域名。

 

8.4  廣域網輸出

    我們前面所給出的小互連網的輸出例子對於查看協議運行過程來說是足夠了,但對於像全球互連網這樣的大互連網來說,應用traceroute程序就需要一些更爲實際的東西。

8.4是從sun主機到NIC (Network Information Center)的情況。

 

8.4  sun主機到nic.ddn.miltraceroute程序

 

    由於運行的這個例子包含文本,非DDN站點(如,非軍方站點)的NIC已經從nic.ddn.mil轉移到rs.internic.net,即新的“InterNIC"

    一旦數據報離開tuc.noao.edu網,它們就進入了telcom.arizona.edu網絡。然後這些數據報進入NASA Science Internetnsn.nasa.govTTL字段爲67的路由器位於JPL (Jet Propulsion Laboratory)上。TTL字段爲11所輸出的sura.net網絡位於Southeastern Universities Research Association Network上。TTL字段爲12的域名GSIGovernment Systems, Inc., NIC的運營者。

    TTL字段爲6的第二個RTT590)幾乎是其它兩個RTT值(234262)的兩倍 。它表明IP路由的動態變化。在發送主機和這個路由器之間發生了使該數據報速度變慢的事件。同樣,我們不能區分是發出的數據報還是返回的ICMP差錯報文被攔截。

    TTL字段爲3的第一個RTT探測值(204)比TTL字段爲2的第一個探測值(233)值還小。由於每個打印出來的RTT值是從發送主機到路由器的總時間,因此這種情況是可能發生的。

8.5的例子是從sun主機到作者出版商之間的運行例子。

 

8.5  sun.tuc.noao.edu主機到aw.comtraceroute程序

 

    在這個例子中,數據報離開telcom.arizona.edu網絡後就進行了地區性的網絡westnet.net (TTL字段值爲67)。然後進行了由Advanced Network & Services運營的NSFNET主幹網,t3.ans.net,(T3是對於主幹網採用的45 Mb/s電話線的一般縮寫。)最後的網絡是alter.net,即aw.com與互連網的連接點。

 

8.5 IP源站選路選項

    通常IP路由是動態的,即每個路由器都要判斷數據報下面該轉發到哪個路由器。應用程序對此不進行控制,而且通常也並不關心路由。它採用類似traceroute程序的工具來發現實際的路由。

    源站選路(source routing)的思想是由發送者指定路由。它可以採用以下兩種形式:

    ·嚴格的源路由選擇。發送端指定IP數據報所必須採用的確切路由。如果一個路由器發現源路由所指定的下一路由器不在其直接連接的網絡上,那麼它就返回一個“源站路由失敗”的ICMP差錯報文。

    寬鬆的源站選路。發送端指定一個數據報經過的IP地址清單,但是數據報在清單上指定的任意兩個地址之間可以通過其它路由器。

    Traceroute程序爲我們提供了一個查看源站選路的方法,我們可以在選項中指明源站路由,然後檢查其運行情況。

 

(原書p.104①的譯文)

    一些公開的Traceroute程序源代碼包中包含指明寬鬆的源站選路的補丁。但是在標準版中通常並不包含此項。這些補丁的解釋是“Van Jacobson的原始Traceroute程序(1988年春)支持該特性,但他後來因爲有人提出會使網關崩潰而將此功能去除。”對於本章中所給出的例子,作者將這些補丁安裝上,並將它們設置成允許寬鬆的源站選路和嚴格的源站選路。

 

    8.6給出了源站路由選項的格式。

 

8.6 IP首部源站路由選項的通用格式

 

    這個格式與我們在圖7.3中所示的記錄路由選項格式基本一致。但不同之處是,對於源站選路,我們必須在發送IP數據報前填充IP地址清單,而對於記錄路由選項,我們需要爲IP地址清單分配並清空一些空間,並讓路由器填充該清單中的各項。同時,對於源站選路,我們只要爲所需要的IP地址數分配空間並進行初始化,通常其數量小於9。而對於記錄路由選項來說,我們必須儘可能地分配空間,以達到9個地址。

    對於寬鬆的源站選路來說,code字段的值是0x83,而對於嚴格的源站選路,其值爲0x89lenptr字段與我們在7.3節中所描述的一樣。

    源站路由選項的實際稱呼爲“源站及記錄路由”(對於寬鬆的源站選路和嚴格的源站選路,分別用LSRRSSRR表示),這是因爲在數據報沿路由發送過程中,對IP地址清單進行更新。下面是其運行過程:

    ·發送主機從應用程序接收源站路由清單,將第一個項去掉(它是數據報的最終目的地址),將剩餘的項移到一個項中(如圖8.6所示),並將原來的目的地址作爲清單的最後一項。指針仍然指向清單的第一項(即,指針的值爲4)。

    ·每個處理數據報的路由器檢查其是否爲數據報的最終地址。如果不是的話,則正常轉發數據報。(在這種情況下,必須指明寬鬆源站選路,否則我們就不能接收到該數據報。)

    ·如果該路由器是最終目的,且指針不大於路徑的長度,那麼(1)由ptr所指定的清單中的下一個地址就是數據報的最終目的地址,(2)由出接口(outgoing interface)相對應的IP地址取代剛纔使用的源地址,然後,(3)指針加4

    可以用下面這個例子很好地解釋上述過程。在圖8.7中,我們假設主機S上的發送應用程序發送一份數據報給D,指定源路由爲R1R2R3

 

8.7  IP源路由示例

 

    在上圖中,#表示指針字段,其值分別是481216。長度字段恆爲15(三個IP地址加上三個字節首部)。可以看出,每一跳IP數據報中的目的地址都發生改變。

當一個應用程序接收到由信源指定路由的數據時,在發送回答時,應該讀出接收路由值,並提供反向路由。

 

(下面是原書p.105①的譯文)

    Host Requirements RFC指明,TCP客戶必須能指明源站路由選擇,同時,TCP服務器必須能夠接收源站路由選擇,並且對於該TCP連接的所有報文段都能採用反向路由。如果TCP服務器下面接收到一個不同的源站路由選擇,那麼新的源站路由將取代舊的源站路由。

 

寬鬆的源站選路的traceroute程序示例

    使用traceroute程序的 -g 選項,我們可以爲寬鬆的源站選路指明一些中間結點。採用該選項可以最多指定8箇中間路由。(其個數是8而不是9的原因是,所使用的編程接口要求最後的表目是目的主機。)

    在圖8.4中,去往NICnic.ddn.mil的路由經過NASA Science Internet。在圖8.8中,我們通過指定路由器 enss142.UT.westnet.net (192.31.39.21) 作爲中間路由器來強制數據報通過NSFNET

 

8.8 採用寬鬆源站選路通過NSFNET到達nic.ddn.miltraceroute程序

 

    在這種情況下,看起來路徑中共有16跳,其平均RTT大約是350 ms,而圖8.4的通常路由選擇則只有13跳,其平均RTT約爲322 ms。默認路徑看起來更好一些。(在建立路徑時,還需要考慮其它的一些因素。其中一些必須考慮的因素是所包含網絡的組織及政治因素。)

    前面我們說看起來有16跳,這是因爲將其輸出結果與我們前面的通過NSFNET(圖8.5)的示例比較,發現在本例採用寬鬆源路由,選擇了3個路由器。(這可能是因爲路由器對源站選路數據報產生ICMP超時差錯報文上存在一些差錯。)在netbbutch路由器之間的gateway.tuc.noao.edu路由器丟失了,同時,位於Gabbyenss142.UT.west.net之間的Westgate.Telcom.Arizona.eduuu-ua.AZ.westnet.net兩個路由器也丟失了。在這些丟失的路由器上可能發生了與接收到寬鬆的源站選路選項數據報有關的程序問題。實際上,當採用NSFNET時,信源和NIC之間的路徑有19跳。本章習題8.5繼續對這些丟失路由器進行討論。

    本例同時也指出了另一個問題。在命令行,我們必須指定路由器enss142.UT.westnet.net的點分十進制IP地址,而不能以其域名代替。這是因爲,反向域名解析(14.5節中描述的通過IP地址返回域名)將域名與IP地址相關聯,但是前向解析(即給出域名返回IP地址)則無法做到。在DNSDomain Name System,域名系統)中,前向映射和反向映射是兩個獨立的文件,而並非所有的管理者都同時擁有這兩個文件。因此,在一個方向是工作正常而另一個方向失敗的情況並不少見。

    還有一種我們以前沒有碰到過的情況是在TTL字段爲8的情況下,對於第一個RTT,打印一個星號(*)。這表明,發生超時,在5秒內未收到本次探查的回答信號。

    將本圖與圖8.4相比較,我們還可以得出一個結論,即路由器ns-FIX-pe.sura.net同時與NSFNETNASA Science Internet相連。

 

嚴格的源站選路的traceroute程序示例

    在作者的traceroute程序版本中,-G參數與前面所描述的-g參數是完全一樣的,不過此時是嚴格的源站選路而不是寬鬆的源站選路。我們可以採用這個參數來觀察在指明無效的嚴格的源站選路時其結果會是什麼樣的。從圖8.5可以看出來,從作者的子網發往NSFNET的數據報的正常路由器順序是netbgatewaybutchgabby。(爲了便於查看,我們後面所有的輸出結果中,省略了域名後綴 .tuc.noao.edu .telcom.arizona.edu。)我們指定了一個嚴格源路由,使其試圖將數據報從gateway直接發送到gabby,而省略了butch。我們可以猜測到其結果會是失敗的,正如圖8.9所給出的結果。

 

8.9 採用嚴格源路由失敗的traceroute程序

 

    這裏的關鍵是在於TTL字段爲3的輸出行中,RTT後面的!S。這表明traceroute程序接收到ICMP“源站路由失敗”的差錯報文:即圖6.3type字段爲3,而code字段爲5TTL字段爲3的第二個RTT位置的星號表示未收到這次探查的回答信號。這與我們所猜想的一樣, gateway不可能直接發送數據報給gabby,這是因爲它們之間沒有直接的連接。

    TTL字段爲23的結果都來自於gateway,對於TTL字段爲2的回答來自gateway是因爲gateway接收到TTL字段爲1的數據報。在它查看到(無效的)嚴格的源站選路之前,就發現TTL已過期,因此發送回ICMP超時報文。TTL字段等於3的行,在進入gateway時其TTL字段爲2,因此,它查看嚴格的源站選路,發現它是無效的,因此發送回ICMP源站選路失敗的差錯報文。

    8.10給出了與本例相對應的tcpdump輸出結果。該輸出結果是在sunnetb之間的SLIP鏈路上懼到的。我們必須在tcpdump中指定-v選項以顯示出源站路由信息。這樣,會輸出一些像數據報ID這樣的我們不需要的結果,我們在給出結果中將這些不需要的結果刪除掉。同樣,我們用SSRR表示“嚴格的源站及記錄路由”。

 

8.10  失敗的嚴格的源站選路traceroute程序的tcpdump輸出結果

 

    首先注意到,sun所發送的每個UDP數據報的目的地址都是netb,而不是目的主機(westgate)。這一點可以用圖8.7的例子來解釋。類似的,-G參數所指定的另外兩個路由器(gatewaygabby)以及最終目的(westgate)成爲第一跳的SSRR選項。

    從這個輸出結果中,我們還可以看出,traceroute程序所採用的定時時間(第15行和16行之間的時間差)是5秒。

 

寬鬆的源站選路traceroute程序的往返路由

    我們在前面已經說過,從AB的路徑並不一定與從BA的路徑完全一樣。除非同時在兩個系統中登錄並在每個終端上運行traceroute程序,否則很難發現兩條路徑是否不同。但是,採用寬鬆的源站選路,我們就可以決定兩個方向上的路徑。

    這裏的竅門就在於指定一個寬鬆的源站路由,該路由的目的端和寬鬆路徑一樣,但發送端爲目的主機。例如,在sun主機上,我們可以查看到發往以及來自bruno.cs.colorado.edu的結果如圖8.11所示。

 

8.11 顯示非對稱路徑的traceroute程序

 

    發出路徑(TTL字段爲1-11)的結果與返回路徑(TTL字段爲11-21)不同,這很好地說明了在Internet 上,路由選擇可能是不對稱的。

    該輸出同時還說明了我們在圖8.3中所討論的問題。比較TTL字段爲219的輸出結果:它們都是路由器gateway.tuc.noao.edu,但兩個IP地址卻是不同的。由於traceroute程序以進入接口作爲其標識,而我們從兩條不同的方向經過該路由器,一條是發出路徑(TTL字段爲2),另一條是返回路徑(TTL字段爲19),因此我們可以猜想到這個結果。通過比較TTL字段爲318417的結果,我們可以看到同樣的結果。

 

8.6 小結

    在一個TCP/IP網絡中,traceroute程序是不可缺少的工具。其操作很簡單:開始時發送一個TTL字段爲1UDP數據報,然後將TTL字段每次加1,以確定路徑中的每個路由器。每個路由器在丟棄UDP數據報時都返回一個ICMP超時報文2,而最終目的主機則產生一個ICMP端口不可到達的報文。

    我們給出了在LANWAN上運行traceroute程序的例子,並用它來考察IP源站選路。我們用寬鬆的源站選路來檢測發往目的主機的路由是否與從目的主機返回的路由一樣。

 

習題:

8.1 IP將接收到的TTL字段減1,發現它爲0時,將會發生什麼結果?

8.2 traceroute程序是如何計算RTT的?將這種計算RTT的方法與ping相比較。

8.3 (本習題與下一道習題是基於開發traceroute程序過程中遇到的實際問題,它們來自於traceroute程序源代碼註釋。)假設有源主機和目的主機之間有三個路由器(R1R2R3),而中間的路由器(R2)在進入TTL字段爲1時,將TTL字段減1,但卻錯誤地將該IP數據報發往下一個路由器。請描述會發生什麼結果。在運行traceroute程序是你會看到什麼樣的現象?

8.4 同樣,假設源主機和目的主機之間有三個路由器。由於目的主機上存在錯誤,因此,它總是將進入TTL值作爲外出ICMP報文的TTL值。請描述這將發生什麼結果,你會看到什麼現象。

8.5 在圖8.8運行例子中,我們可以在sunnetb之間的SLIP鏈路上運行tcpdump程序。如果我們指定-v參數,就可以看到返回ICMP報文的TTL值。這樣,我們可以看到進入netbbutchGabbyenss142.UT.westnet.netTTL值分別爲255253252249。這是否爲我們判斷是否存在丟失路由器提供了額外的信息?

8.6 SunOSSVR4都提供了帶-l選項的ping版本,以提供鬆源路由選擇。手冊上說明,該選項可以與 -R 選項(指定記錄路由選項)一起用的。如果你已經進入到這些系統中,請嘗試同時用這兩個選項。其結果是什麼:如果你採用tcpdump來觀測數據報,請描述其過程。

8.7 比較pingtraceroute程序在處理同一臺主機客戶的多個實例上的不同點。

8.8 比較pingtraceroute程序在計算往返時間上的不同點。

8.9 我們已經說過,traceroute程序選取開始UDP目的主機端口號爲33453,每發送一個數據報將此數加1。在1.9節中,我們說過暫時端口號通常是10245000之間的值,因此traceroute程序的目的主機端口號不可能是目的主機上所使用的端口號。在Solaris2.2系統中的情況也是如此嗎?(提示:查看E.4節)

8.10 RFC 1393 [Malkin 1993b]提出了另一種判斷到目的主機路徑的方法。請問其優缺點是什麼?

88

9  IP路由選擇

 

9.1 引言

    路由選擇是IP最重要的功能之一。圖9.1IP層處理過程的簡單流程。需要進行路由選擇的數據報可以由本地主機產生,也可以由其他主機產生。在後一種情況下,主機必須配置成一個路由器,否則通過網絡接口接收到的數據報,如果目的地址不是本機就要被丟棄(例如,悄無聲息地被丟棄)。

    在圖9.1中,我們還描述了一個路由守護程序(daemon),一般來說是一個用戶進程。在Unix系統中,大多數普通的守護程序都是路由程序和網關程序。(術語daemon指的是運行在後臺的進程,它代表整個系統執行某些操作。daemon一般在系統引導時啓動,在系統運行期間一直存在。)在某個給定主機上運行何種路由協議,如何在相鄰路由器上交換選路信息,以及選路協議是如何工作的,所有這些問題都是非常複雜的,其本身就可以用整本書來加以討論。(有興趣的讀者可以參考文獻[Perlman 1992]以獲得更詳細的信息。)在第10章中,我們將簡單討論動態路由選擇和選路信息協議RIPRouting Information Protocol)。在本章我們主要的目的是瞭解單個IP層如何作出路由決策的。

    9.1所示的路由表經常被IP訪問(在一個繁忙的主機上,一秒鐘內可能要訪問幾百次),但是它被路由守戶程序更新的頻度卻要低得多(可能大約30秒種一次)。當接收到ICMP“改變路由(redirect)”報文時路由表也要被更新,這一點我們將在9.5節討論route命令時加以介紹。在本章中,我們還將用netstat命令來顯示路由表。

 

9.1 IP層工作流程

 

9.2 路由選擇的原理

    開始討論IP路由選擇之前,首先要理解內核是如何維護路由表的。路由表中包含的信息決定了IP層所做的所有決策。

    3.3節中,我們列出了IP搜索路由表的幾個步驟:

    1. 搜索匹配的主機地址;

    2. 搜索匹配的網絡地址;

    3. 搜索默認表項。(默認表項一般在路由表中被指定爲一個網絡表項,其網絡號爲0。)

 

匹配主機地址步驟始終發生在匹配網絡地址步驟之前。

    IP層進行的路由選擇實際上是一種路由選擇機制,它搜索路由表並決定向哪個網絡接口發送分組。這區別於路由選擇策略,它只是一組決定把哪些路由放入路由表的規則。IP執行路由選擇機制,而路由守護程序則一般提供路由選擇策略。

 

簡單路由表

    首先讓我們來看一看一些典型的主機路由表。在主機svr4上,我們先執行帶-r參數的netstat命令列出路由表,然後以-n參數再次執行該命令,以數字格式打印出IP地址。(我們這樣做是因爲路由表中的一些表項是網絡地址,而不是主機地址。如果沒有-n參數,netstat命令將搜索文件/etc/networks並列出其中的網絡名。這樣會與另一種形式的名字——網絡名加主機名相混淆。

 

(見原書p.113的①)

 

    第一行說明,如果目的地是140.252.13.65slip主機),那麼網關(路由器)將把分組轉發給140.252.13.35bsdi)。這正是我們所期望的,因爲主機slip通過SLIP鏈路與bsdi相連接,而bsdi與該主機在同一個以太網上。

    對於一個給定的路由器,可以打印出五種不同的標誌(flag):

    U  該路由可以使用。

    G  該路由是到一個網關(路由器)。如果沒有設置該標誌,說明目的地是直接相連的。

    H  該路由是到一個主機,也就是說,目的地址是一個完整的主機地址。如果沒有設置該標誌,說明該路由是到一個網絡,而目的地址是一個網絡地址:一個網絡號,或者網絡號與子網號的組合。

    D  該路由是由改變路由(redirect)報文創建的(9.5節)。

    M  該路由已被改變路由報文修改(9.5節)。

   

    標誌G是非常重要的,因爲由它區分了間接路由和直接路由。(對於直接路由來說是不設置標誌G的。)其區別在於,發往直接路由的分組中不但具有指明目的端的IP地址,還具有其鏈路層地址(圖3.3)。當分組被髮往一個間接路由時,IP地址指明的是最終的目的地,但是鏈路層地址指明的是網關(即下一站路由器)。我們在圖3.4已看到這樣的例子。在個路由表例子中,我們有一個間接路由(設置了標誌G),因此採用這一項路由的分組其IP地址是最終的目的地(140.252.13.65),但是其鏈路層地址必須對應於路由器140.252.13.35

    理解GH標誌之間的區別是很重要的。G標誌區分了直接路由和間接路由,如上所述。但是H標誌表明,目的地址(netstat命令輸出第一行)是一個完整的主機地址。沒有設置H標誌說明目的地址是一個網絡地址(主機號部分爲0)。當爲某個目的IP地址搜索路由表時,主機地址項必須與目的地址完全匹配,而網絡地址項只需要匹配目的地址的網絡號和子網號就可以了。另外,大多數版本的netstat命令首先打印出所有的主機路由表項,然後纔是網絡路由表項。

    參考記數Refcnt(“Reference count ”)列給出的是正在使用路由的活動進程個數。面向連接的協議如TCP在建立連接時要固定路由。如果在主機svr4slip之間建立Telnet連接,我們可以看到參考記數值變爲1。建立另一個Telnet連接時,它的值將增加爲2,以此下去。

    下一列(“use")顯示的是通過該路由發送的分組數。如果我們是這個路由的唯一分組,那麼我們運行ping程序發送5個分組後,它的值將變爲5。最後一列列出的(interface)是本地接口的名字。

    輸出的第2行是環回接口(2.7節),它的名字始終爲lo0。沒有設置G標誌,因爲該路由不是一個網關。H標誌說明目的地址(127.0.0.1)是一個主機地址,而不是一個網絡地址。由於沒有設置G標誌,說明這是一個直接路由,網關列給出的是出口IP地址。

    輸出的第3行是默認路由。每個主機都有一個或多個默認路由。這一項表明,如果在表中沒有找到特定的路由,就把分組發送到路由器140.252.13.33sun主機)。這說明當前主機(svr4)利用這一個路由表項就可以通過Internet經路由器sun(及其SLIP鏈路)訪問其他的系統。建立默認路由是一個功能很強的概念。該路由標誌(UG)表明它是一個網關,這是我們所期望的。

 

(下面是原書p.114①的譯文)

    這裏,我們有目的地稱sun爲路由器而不是主機,因爲它被當作默認路由器來使用,它發揮的是IP轉發功能,而是主機功能。

    Host Requirements RFC文檔特別說明,IP層必須支持多個默認路由。但是,許多實現系統並不支持這一點。當存在多個默認路由時,一般的技術就成爲它們周圍的知更鳥了,例如,Solaris 2.2就是這樣做的。

 

    輸出中的最後一行是所在的以太網。H標誌沒有設置,說明目的地址(140.252.13.32)是一個網絡地址,其主機地址部分設爲0。事實上,是它的低5位設爲0(圖3.11)。由於這是一個直接路由(G標誌沒有被設置),網關列指出的IP地址是出口地址。

    netstat命令輸出的最後一項還隱含了另一個信息,那就是目的地址(140.252.13.32)的子網掩碼。如果要把該目的地址與140.252.13.33進行比較,那麼在比較之前首先要把它與目的地址掩碼(0xffffffe03.7節)進行邏輯與。由於內核知道每個路由表項對應的接口,而且每個接口都有一個對應的子網掩碼,因此每個路由表項都有一個隱含的子網掩碼。

    主機路由表的複雜性取決於主機所在網絡的拓撲結構。

    1. 最簡單的(也是最不令人感興趣的)情況是主機根本沒有與任何網絡相連。TCP/IP協議仍然能用於這樣的主機,但是隻能與自己本身通信!這種情況下的路由表只包含環回接口一項。

    2. 接下來的情況是主機連在一個局域網上,只能訪問局域網上的主機。這時路由表包含兩項:一項是環回接口,另一項是局域網(如以太網)。

    3. 如果主機能夠通過單個路由器訪問其他網絡(如Internet)時,那麼就要進行下一步。一般情況下增加一個默認表項指向該路由器。

    4. 如果要新增其他的特定主機或網絡路由,那麼就要進行最後一步。在我們的例子中,到主機slip的路由要通過路由器bsdi就是這樣的例子。

    我們根據上述IP操作的步驟使用這個路由表爲主機svr4上的一些例子分組選擇路由。

    1. 假定目的地址是主機sun140.252.13.33。首先進行主機地址的匹配。路由表中的兩個主機地址表項(sliplocalhost)均不匹配,接着進行網絡地址匹配。這一次匹配成功,找到表項140.252.13.32(網絡號和子網號都相同),因此使用emd0接口。這是一個直接路由,因此鏈路層地址將是目的端的地址。

    2. 假定目的地址是主機slip140.252.13.65。首先在路由表搜索主機地址,並找到一個匹配地址。這是一個間接路由,因此目的端的IP地址仍然是140.252.13.65,但是鏈路層地址必須是網關140.252.13.65的鏈路層地址,其接口名爲emd0

    3. 這一次我們通過Internet給主機aw.com192.207.117.2)發送一份數據報。首先在路由表中搜索主機地址,失敗後進行網絡地址匹配。最後成功地找到默認表項。該路由是一個間接路由,通過網關140.252.13.33並使用接口名爲emd0

    4. 在我們最後一個例子中,我們給本機發送一份數據報。有四種方法可以完成這件事,如用主機名,主機IP地址,環回名,或者環回IP地址:

   

         ftp svr4

         ftp 140.252.13.34

 

         ftp localhost

         ftp 127.0.0.1

 

    在前兩種情況下,對路由表的第二次搜索得到一個匹配的網絡地址140.252.13.32,並把IP報文傳送給以太網驅動程序。正如圖2.4所示的那樣,IP報文中的目的地址爲本機IP地址,因此報文被送給環回驅動程序,然後由驅動程序把報文放入IP輸出隊列中。

    在後兩種情況下,由於指定了環回接口的名字或IP地址,第一次搜索就找到匹配的主機地址,因此報文直接被送給環回驅動程序,然後由驅動程序把報文放入IP輸出隊列中。

上述四種情況報文都要被送給環回驅動程序,但是採用的兩種路由決策是不相同的。

 

初始化路由表

    我們從來沒有說過這些路由表是如何被創建的。每當初始化一個接口時(通常是用 ifconfig命令設置接口地址時),就爲接口自動創建一個直接路由。對於點對點鏈路和環回接口來說,路由是到達主機(例如,設置H標誌)。對於廣播接口來說,如以太網,路由是到達網絡。

    到達主機或網絡的路由如果不是直接相連的,那麼就必須加入路由表。一個普通的方法在系統引導時顯式地在初始化文件中運行route命令。在主機svr4上,我們運行下面兩個命令來添加路由表中的表項:

 

    route add default sun 1

    route add slip bsdi 1

 

    第三個參數(defaultslip)代表目的端,第四個參數代表網關(路由器),最後一個參數代表路由的度量(metric)route命令在度量值大於0時要爲該路由設置G標誌,否則當耗費值爲0時就不設置G標誌。

 

(下面是原書p.116①的譯文)

    不幸的是,幾乎沒有系統願意在啓動文件中包含route命令。在4.4 BSDBSD/386系統中,啓動文件是/etc/netstart, SVR4系統中,啓動文件是/etc/inet/rc.inet, Solaris 2.x中,啓動文件是/etc/rc2.d/S69inet, SunOS 4.1.x中,啓動文件是/etc/rc.local, AIX 3.2.2則使用文件/etc/rc.net

    一些系統允許在某個文件中指定默認的路由器,如/etc/defaultrouter,於是在每次重新啓動系統時都要在路由表中加入該默認項。

    初始化路由表的其它方法是運行路由守護程序(第10章)或者用較新的路由器發現協議(9.6節)。

 

較複雜的路由表

    在我們的子網上,主機sun是所有主機的默認路由器,因爲它有拔號SLIP鏈路連接到Internet上(參見封二上的圖)。

 

(見原書p.117的①)

 

    前兩項與主機svr4的前兩項一致:通過路由器bsdi到達slip的特定主機路由,以及環迴路由。

    第三行是新加的。這是一個直接到達主機的路由(沒有設置G標誌,但設置了H標誌),對應於點對點的鏈路,即SLIP接口。如果我們把它與ifconfig命令的輸出進行比較:

 

    sun % ifconfig sl0

    sl0: flags=1051<     UP,POINTOPOINT,RUNNING>

          inet 140.252.1.29 --> 140.252.1.183 netmask ffffff00

 

    我們發現路由表中的目的地址就是點對點鏈路的另一端(即路由器netb), 網關地址爲本地出口IP地址(140.252.1.29)(我們前面已經說過, netstat爲直接路由打印出來的網關地址就是本地接口所用的IP地址。)

    默認的路由表項是一個到達網絡的間接路由(設置了G標誌,但沒有設置H標誌),這正是我們所希望的。網關地址是路由器的地址(140.252.1.183SLIP鏈路的另一端), 而不是SLIP鏈路的本地IP地址(140.252.1.29)。其原因還是因爲是間接路由,不是直接路由。

    我們還應該指出的是,netstat輸出的第三和第四行(接口名爲sl0)SLIP軟件在啓動時創建,並在關閉時刪除.

 

沒有到達目的地的路由

    我們所有的例子都假定對路由表的搜索都能找到匹配的表項,即使匹配的是默認項。如果路由表中沒有默認項,而又沒有找到匹配項,這時會發生什麼情況呢?

    結果取決於該IP數據報是由主機產生的還是被轉發的(例如,我們就充當一個路由器)。如果數據報是由本地主機產生的,那麼就給發送該數據報的應用程序返回一個差錯,或者是“主機不可達差錯”或者是“網絡不可達差錯”。如果是被轉發的數據報,那麼就給原始發送端發送一份ICMP主機不可達差錯的報文。在下一節我們將討論這種差錯。

 

9.3  ICMP主機與網絡不可達差錯

    當路由器收到一份IP數據報但又不能轉發時,就要發送一份ICMP“主機不可到達”差錯報文。(ICMP主機不可達報文的格式如圖6.10所示)。我們可以很容易發現,在我們的網絡上把接在路由器sun上的拔號SLIP鏈路斷開,然後試圖通過該SLIP鏈路發送分組給任何指定sun爲默認路由器的主機。

 

(下面是原書p.118①的譯文)

    較老版本的BSD產生一個主機不可達或者網絡不可達差錯,這取決於目的端是否處於一個局域子網上。4.4 BSD只產生主機不可達差錯。

 

    我們在上一節通過在路由器sun上運行netstat命令可以看到,當接通SLIP鏈路啓動時就要在路由表中增加一項使用SLIP鏈路的表項,而當斷開SLIP鏈路時則刪除該表項。這說明當SLIP鏈路斷開時,sun的路由表中就沒有默認項了。但是我們不想改變網絡上其他主機的路由表,即同時刪除它們的默認路由。相反,對於sun不能轉發的分組我們對它產生的ICMP主機不可達差錯報文進行計數。

    在主機svr4上運行ping程序就可以看到這一點,它在拔號SLIP鏈路的另一端(拔號鏈路已被斷開):

 

(見原書p.118的②)

 

    在主機bsdi上運行tcpdump命令的輸出如圖9.2所示。

 

9.2 響應ping命令ICMP主機不可達報文

 

    當路由器sun發現找不到能到達主機gemini的路由時,它就響應一個主機不可達的迴響請求報文。

    如果我們把SLIP鏈路接到Internet上,然後試圖ping一個與Internet沒有連接的IP地址,那麼應該會產生差錯。但令人感興趣的是,我們可以看到在返回差錯報文之前,分組要在Internet上傳送多遠:

 

(見原書p.118的③)

 

    從圖8.5可以看出,在發現該IP地址是無效的之前,該分組已通過了6個路由器。只有當它到達NSFNET骨幹網的邊界時才檢測到差錯。這說明, 6個路由器之所以能轉發分組是因爲路由表中有默認項,只有當分組到達NSFNET骨幹網時,路由器才能知道每個連接到Internet上的每個網絡的信息。這說明許多路由器只能在局部範圍內工作。

    參考文獻[Ford, Rekhter, and Braun 1993]定義了頂層選路域(top-level routing domain),由它來維護大多數Internet網站的路由信息,而不使用默認路由。他們指出,在Internet上存在5個這樣的頂層選路域:NSFNET主幹網,商業互連網交換(Commercial Internet Exchange: CIX),NASA科學互連網(NASA Science Internet: NSI),SprintLink,以及歐洲IP主幹網(EBONE)。

 

9.4  轉發或不轉發

    前面我們已經提過幾次,一般都假定主機不轉發IP數據報,除非對它們進行特殊配置而作爲路由器使用。如何進行這樣的配置呢?

    大多數伯克利派生出來的系統都有一個內核變量ipforwarding,或其他類似的名字。(參見附錄E。)一些系統(如BSD/386SVR4)只有在該變量值不爲0的情況下才轉發數據報。SunOS 4.1.x允許該變量可以三個不同的值:-1表示始終不轉發並且始終不改變它的值;0表示默認條件下不轉發,但是當打開兩個或更多個接口時就把該值設爲11表示始終轉發。Solaris 2.x把這三個值改爲0(始終不轉發),1(始終轉發)和2(在打開兩個或更多個接口時才轉發)。

    較舊版本的4.2BSD主機在默認條件下可以轉發數據報,這給沒有進行正確配置的系統帶來了許多問題。這就是內核選項爲什麼要設成默認的“始終不轉發”的原因,除非系統管理員進行特殊設置。

 

9.5  ICMP改變路由差錯

    IP數據報應該被髮送到另一個路由器時,收到數據報的路由器就要發送ICMP改變路由(redirect)差錯報文給IP數據報的發送端。這在概念上是很簡單的,正如我們在圖9.3中所示的那樣。只有當主機可以選擇路由器發送分組的情況下我們纔可能看到ICMP改變路由報文。(回憶我們在圖7.6中看過的例子。)

    1. 我們假定主機發送一份IP數據報給R1。這種路由選擇決策經常發生,因爲R1是該主機的默認路由。

    2. R1收到數據報並且檢查它的路由表,發現R2是發送該數據報的下一站。當它把數據報發送給R2時,R1檢測到它正在發送的接口與數據報到達接口是相同的(即主機和兩個路由器所在的LAN)。這樣就給路由器發送改變路由報文給原始發送端提供了線索。

    3. R1發送一份ICMP改變路由報文給主機,告訴它以後把數據報發送給R2而不是R1

 

9.3 ICMP改變路由例子

 

    改變路由一般用來讓具有很少路由選擇信息的主機逐漸建立更完善的路由表。主機啓動時路由表中可以只有一個默認表項(在圖9.3的例子中,爲R1R2),一旦默認路由發生差錯,默認路由器將通知它進行改變路由,允許主機對路由表作相應的改動。ICMP改變路由允許TCP/IP主機在進行路由選擇時不需要具備智能特性,而把所有的智能特性放在路由器端。顯然,在我們的例子中,R1R2 必須知道有關相連網絡的更多拓撲結構的信息,但是連在LAN上的所有主機在啓動時只需一個默認路由,通過接收改變路由報文來逐步學習。

一個例子

    我們可以在我們的網絡上觀察到ICMP改變路由的操作過程(見封二的圖)。儘管我們在拓撲圖中只畫出了三臺主機(aix, solarisgemini)和兩臺路由器(gatewaynetb),但是整個網絡有超過150臺主機和10臺另外的路由器。大多數的主機都把gateway指定爲默認路由器,因爲它提供了Internet的入口。

    子網140.252.1上的主機是如何訪問作者所在子網(圖中底下的四臺主機)的呢?首先,如果在SLIP鏈路的一端只有一臺主機,那麼就要使用代理ARP4.6節)。這意味着位於拓撲圖頂部的子網(140.252.1)中的主機不需要其他特殊條件就可以訪問主機sun140.252.1.29)。位於netb上的代理ARP軟件處理這些事情。

    但是,當網絡位於SLIP鏈路的另一端時,就要涉及到路由選擇了。一個辦法是讓所有的主機和路由器都知道路由器netb是網絡140.252.13的網關。這可以在每個主機的路由表中設置靜態路由,或者在每個主機上運行守護程序來實現。另一個更簡單的辦法(也是實際採用的方法)是利用ICMP改變路由報文來實現。

    讓我們在位於網絡頂部的主機solaris上運行ping程序到主機bsdi(140.252.13.35)。由於子網號不相同,代理ARP不能使用。假定沒有安裝靜態路由,發送的第一個分組將採用到路由器gateway的默認路由。下面是我們運行ping程序之前的路由表:

 

(見原書p.121的①)

 

    224.0.0.0所在的表項是IP廣播地址。我們將在第12章討論。)如果爲ping程序指定-v選項,我們可以看到主機接收到的任何ICMP報文。我們需要指定該選項以觀察發送的改變路由報文。

 

(見原書p.121的②)

 

在我們收到ping程序的第一個響應之前,主機先收到一份來自默認路由器gateway發來的ICMP改變路由報文。如果我們這時查看路由表,會發現已經插入了一個到主機bsdi的新路由。(該表項如下黑體字所示。)

 

(見原書p.121的③)

 

這是我們第一次看到D標誌,表示該路由是被ICMP改變路由報文創建的。G標誌說明這是一份到達gateway(netb)的間接路由,H標誌則說明這是一個主機路由(正如我們期望的那樣),而不是一個網絡路由。

    由於這是一個被主機改變路由報文增加的主機路由,因此它只處理到達主機bsdi的報文。如果我們接着訪問主機svr4,那麼就要產生另一個ICMP改變路由報文,創建另一個主機路由。類似地,訪問主機slip也創建另一個主機路由。位於子網上的三臺主機(bsdi, svr4slip)還可以由一個指向路由器sun的網絡路由來進行處理。但是ICMP改變路由報文創建的是主機路由,而不是網絡路由,這是因爲在本例中,產生ICMP改變路由報文的路由器並不知道位於140.252.13網絡上的子網信息。

 

更多的細節

    ICMP改變路由報文的格式如圖9.4所示。

 

9.4 ICMP改變路由報文

 

    有四種不同類型的改變路由報文,有不同的代碼值,如圖9.5所示。

 

9.5 ICMP改變路由報文的不同代碼值

 

    ICMP改變路由報文的接收者必須查看三個IP地址:(1)導致改變路由的IP地址(即ICMP改變路由報文的數據位於IP數據報的首部);(2)發送改變路由報文的路由器的IP地址(包含改變路由信息的IP數據報中的源地址;(3)應該採用的路由器IP地址(在ICMP報文中的4-7字節)。

    關於ICMP改變路由報文有很多規則。首先,改變路由報文只能由路由器生成,而不能由主機生成。另外,改變路由報文是爲主機而不是爲路由器使用的。假定路由器和其他一些路由器共同參與某一種路由選擇協議,則該協議就能消除改變路由的需要。(這意味着在圖9.1中的路由表應該消除或者能被路由選擇守護程序修改,或者能被改變路由報文修改,但不能同時被二者修改。)

    4.4BSD系統中,當主機作爲路由器使用時,要進行下列檢查,在生成ICMP改變路由報文之前這些條件都要滿足。

    1. 出接口必須等於入接口。

    2. 用於向外傳送數據報的路由不能被ICMP改變路由報文創建或修改過,而且不能是路由器的默認路由。

    3. 數據報不能用源站選路來轉發。

    4. 內核必須配置成可以發送改變路由報文。

 

(下面是原書p.123①的譯文)

    內核變量取名爲ip_sendredirects或其他類似的名字。(參見附錄E。)大多數當前的系統(例如BSD, SunOS 4.1.x, Solaris 2.x, AIX 3.2.2)在默認條件下都設置該變量使系統可以發送改變路由報文。其他系統如SVR4則關閉了該項功能。

 

    另外,一臺4.4BSD主機收到ICMP改變路由報文後,在修改路由表之前要作一些檢查。這是爲了防止路由器或主機的誤操作,以及惡意用戶的破壞,導致差錯地修改系統路由表。

    1. 新的路由器必須直接與網絡相連接。

    2. 改變路由報文必須來自當前到目的地所選擇的路由器。

    3. 改變路由報文不能讓主機本身作爲路由器。

    4. 被修改的路由必須是一個間接路由。

 

    關於改變路由最後要指出的是,路由器應該發送的只是對主機的改變路由(代碼13,如圖9.5所示),而不是對網絡的改變路由。子網的存在使得難於準確指明何時應發送對網絡的改變路由而不是對主機的改變路由。只當路由器發送了錯誤的類型時,一些主機才把收到的對網絡的改變路由當作對主機的改變路由來處理。

 

9.6  ICMP路由器發現報文

    我們在本章前面已提到過一種初始化路由表的方法,即在配置文件中指定靜態路由。這種方法經常用來設置默認路由。另一種新的方法是利用ICMP路由器通告和請求報文。

    一般認爲,主機在引導以後要廣播或多播傳送一份路由器請求報文。一臺或更多臺路由器響應一份路由器通告報文。另外,路由器定期地廣播或多播傳送它們的路由器通告報文,允許每個正在監聽的主機相應地更新它們的路由表。

    RFC 1256 [Deering 1991]確定了這兩種ICMP報文的格式。ICMP路由器請求報文的格式如圖9.6所示。ICMP路由器通告報文的格式如圖9.7所示。

    路由器在一份報文中可以通告多個地址。地址數指的是報文中所含的地址數。地址項大小指的是每個路由器地址32-bit字的數目,始終爲2。生命週期指的是通告地址有效的時間(秒數)。

 

9.6 ICMP路由器請求報文格式

 

9.7 ICMP路由器通告報文格式

 

    接下來是一對或多對IP地址和優先級。IP地址必須是發送路由器的某個地址。優先級是一個有符號的32-bit整數,指出該IP地址作爲默認路由器地址的優先等級,這是與子網上的其他路由器相比較而言的。值越大說明優先級越高。優先級爲0x80000000說明對應的地址不能作爲默認路由器地址使用,儘管它也包含中通告報文中。優先級的默認值一般爲0

 

路由器操作

    當路由器啓動時,它定期在所有廣播或多播傳送接口上發送通告報文。準確地說,這些通告報文不是定期發送的,而是隨機傳送的,以減小與子網上其他路由器發生衝突的概率。一般每兩次通告間隔450600秒。一份給定的通告報文默認生命週期是30分鐘。

    使用生命週期域的另一個時機是當路由器上的某個接口被關閉時。在這種情況下,路由器可以大該接口上發送最後一份通告報文,並把生命週期值設爲0

    除了定期發送主動提供的通告報文以外,路由器還要監聽來自主機的請求報文,併發送路由器通告報文以響應這些請求報文。

    如果子網上有多臺路由器,由系統管理員爲每個路由器設置優先等級。例如,主默認路由器就要比備份路由器具有更高的優先級。

 

主機操作

    主機在引導期間一般發送三份路由器請求報文,每三秒鐘發送一次。一旦接收到一個有效的通告報文,就停止發送請求報文。

    主機也監聽來自相鄰路由器的請求報文。這些通告報文可以改變主機的默認路由器。另外,如果沒有接收到來自當前默認路由器的通告報文,那麼默認路由器會超時。

只要有一般的默認路由器,該路由器就會每隔10分鐘發送通告報文,報文的生命週期是30分鐘。這說明主機的默認表項是不會超時的,即使錯過一份或兩份通告報文。

 

實現   

    路由器發現報文一般由用戶進程(守護程序)創建和處理。這樣,在圖9.1中就有另一個修改路由表的程序,儘管它只增加或刪除默認表項。守護程序必須把它配置成一臺路由器或主機來使用。

 

(下面是原書 p.125①的譯文)

    這兩種ICMP報文是新加的,不是所有的系統都支持它們。在我們的網絡中,只有Solaris 2.x支持這兩種報文( in.rdisc守護程序)。儘管RFC建議用儘可能用IP多播傳送,但是路由器發現還可以利用廣播報文來實現。

 

9 .7 小結

    IP路由操作對於運行TCPIP的系統來說是最基本,不管是主機還是路由器。路由表項的內容很簡單,它包括:5 bit標誌,目的IP地址(主機,網絡,或默認),下一站路由器的IP地址(間接路由)或者本地接口的IP地址(直接路由),指向本地接口的指針。主機表項比網絡表項具有更高的優先級,而網絡表項比默認項具有更高的優先級。

    系統產生的或轉發的每份IP數據報都要搜索路由表,它可以被路由守護程序或ICMP改變路由報文修改。系統在默認情況下不轉發數據報,除非進行特殊的配置。用route命令可以進入靜態路由,可以利用新ICMP路由器發現報文來初始化默認表項,並進行動態修改。主機在啓動時只有一個簡單的路由表,它可以被來自默認路由器的ICMP改變路由報文動態修改。

    在本章,我們集中討論了單個系統是如何利用路由表的。在下一章,我們將討論路由器之間是如何交換路由信息的。

 

習題

9.1 爲什麼你認爲存在兩類ICMP改變路由報文——網絡和主機?

9.2 9 .4節開頭列出的svr4主機上的路由表中,到主機slip140.252.13.65)的特定路由是必需的嗎?如果把這一項從路由表中刪除會有什麼變化?

9.3 考慮有一電纜連接4.2BSD主機和4.3BSD主機。假定網絡號是140.14.2BSD主機把主機號爲全0的地址識別的廣播地址(140.1.0.0)。另外,4.2BSD主機在默認條件下要盡力轉發接收到的數據報,儘管它們只有一個接口。

    請描述當4.2BSD主機收到一份目的地址爲140.1.255.255IP數據報時會發生什麼事。

9.4 繼續前一個習題,假定有人在子網140.1上的某個系統ARP高速緩存中增加了一項(用arp命令)內容,指定IP地址140.1.255.255對應的以太網地址爲全1(以太網廣播地址)。請描述此時發生的情況。

9.5 檢查你所使用的系統上的路由表,並解釋每一項內容。

 

 

   

96

10 動態選路協議

 

10.1 引言

    在前面各章中,我們討論了靜態選路。在配置接口時,以默認方式生成路由表項(對於直接連接的接口),並通過route命令增加表項(通常從系統自引導程序文件),或是通過ICMP改變路由生成表項(通常是在默認方式出錯的情況下)。

    在網絡很小時,與其它網絡只有單個連接點且沒有多餘路由時(若主路由失敗時,可以使用備用路由),採用這種方法是可行的。如果上述三種情況不能全部滿足的話,通常使用動態選路。

    本章討論動態選路協議,它用於路由器間的通信。我們主要討論RIP,即選路信息協議(Routing Infromation Protocol),大多數TCP/IP實現都提供的這個應用廣泛的協議。然後我們討論兩種新的選路協議,OSPFBGP。本章的最後研究了一種名叫無分類域間選路的新的選路技術,現在Internet上正在開始採用該協議以保持B類網絡的數量。

 

10.2 動態選路

    當相鄰路由器之間進行通信,以告知對方每個路由器當前所連接的網絡,這時就出現了動態選路。路由器之間必須採用選路協議進行通信,這種選路協議有很多種。路由器上有一個進程稱爲路由守護程序(routing daemon),它運行選路協議,並與其相鄰的一些路由器進行通信。正如圖9.1所示,路由守護程序根據它從相鄰路由器接收到的信息,更新內核中的路由表。

    動態選路並不改變我們在9.2節中所描述的內核在IP層的選路方式。我們這種選路方式稱爲選路機制(routing mechanism)。內核搜索路由表,查找主機路由、網絡路由以及默認路由的方式並沒有改變。僅僅是放置到路由表中的信息改變了——當路由隨時間變化時,路由是由路由守護程序動態地增加或刪除,而不是來自於自引導程序文件中的route命令。

    正如我們前面所描述的那樣,路由守護程序將選路策略(routing policy)加入到系統中,選擇路由並加入到內核的路由表中。如果守護程序發現前往同一信宿存在多條路由,那麼它(以某種方法)將選擇最佳路由並加入內核路由表中。如果路由守護程序發現一條鏈路已經斷開(可能是路由器崩潰或電話線路不好),它可以刪除受影響的路由或增加另一條路由以繞過該問題。

    在像Internet這樣的系統中,目前採用了許多不同的選路協議。Internet是以一組自治系統ASAutonomous System)的方式組織的,每個自治系統通常由單個實體管理。常常將一個公司或大學校園定義爲一個自治系統。NSFNETInternet骨幹網形成一個自治系統,這是因爲骨幹網中的所有路由器都在單個的管理控制之下。

    每個自治系統可以選擇該自治系統中各個路由器之間的選路協議。這種協議我們稱之爲內部網關協議IGPInterior Gateway Protocol)或域內選路協議(intradomain routing protocol)。最常用的IGP是選路信息協議RIP。一種新的IGP是開放最短路徑優先OSPFOpen Shortest Path First)協議。它意在取代RIP。另一種1986年在原來NSFNET骨幹網上使用的IGP協議——HELLO,現在已經不用了。

 

(下面是原書p.128①的譯文)

    新的RFC [Almquist 1993]規定,實現任何動態選路協議的路由器必須同時支持OSPFRIP,還可以支持其它IGP協議。

 

    外部網關協議EGPExterier Gateway Protocol)或域內選路協議的分隔選路協議用於不同自治系統之間的路由器。在歷史上,(令人容易混淆)改進的EGP有着一個與它名稱相同的協議:EGP。新EGP是當前在NSFNET骨幹網和一些連接到骨幹網的區域性網絡上使用的是邊界網關協議BGPBorder Gateway Protocol)。BGP意在取代EGP

 

10.3  Unix選路守護程序

    Unix系統上常常運行名爲routed 路由守護程序。幾乎在所有的TCP/IP實現中都提供該進程。該程序只使用RIP進行通信,我們將在下一節中討論該協議。這是一種用於小型到中型網絡中的協議。

    另一個程序是gatedIGPEGP都支持它。[Fedor 1998]描述了早期開發的gated。圖10.1routed和兩種不同版本的gated所支持的不同選路協議進行了比較。大多數運行路由守護程序的系統都可以運行routed,除非它們需要支持gated所支持的其它協議。

 

10.1 routedgated所支持的選路協議

 

    我們在下一節中描述RIP 版本1,在10.5中描述它與RIP版本2的不同點,10.6節描述OSPF,在10.7節描述BGP

 

10.4  RIP:選路信息協議

    本節對RIP進行了描述,這是因爲它是最廣爲使用(也是最受攻擊)的選路協議。對於RIP的正式描述文件是RFC 1058 [Hedrick 1988a],但是該RFC是在該協議實現數年後纔出現的。

 

報文格式

    RIP報文包含中在UDP數據報中,如圖10.2所示。(我們在第11章中對UDP進行更爲詳細的描述。)

 

10.2 封裝在UDP數據報中的RIP報文

 

    10.3給出了使用IP地址時的RIP報文格式。

    命令字段爲1表示請求,2表示回答。還有兩個捨棄不用的命令(34),兩個非正式的命令:輪詢(5)和輪詢表項(6)。請求表示要求其它系統發送其全部或部分路由表。回答則包含發送者全部或部分路由表。

    版本字段通常爲1,而第2RIP10.5節)將此字段設置爲2

    緊跟在後面的20字節指定地址系列(address family)(對於IP地址來說,其值是2),IP地址以及相應的度量。我們在本節的後面可以看出,RIP的度量是以跳計數的。

    採用這種20字節格式的RIP報文可以通告多達25條路由。上限25是用來保證RIP報文的總長度爲20×25 + 4 = 504,小於512字節。由於每個報文最多攜帶25個路由,因此爲了發送整個路由表,經常需要多個報文。

 

正常運行

    讓我們來看一下采用RIP協議的routed程序正常運行的結果。RIP常用的UDP端口號是520

    ·初始化:在啓動一個路由守護程序時,它先判斷啓動了哪些接口,並在每個接口上發送一個請求報文,要求其它路由器發送完整路由表。在點對點鏈路中,該請求是發送給其它終點的。如果網絡支持廣播的話,這種請求是以廣播形式發送的。目的UDP端口號是520(這是其它路由器的路由守護程序端口號)。

    這種請求報文的命令字段爲1,但地址系列字段設置爲0,而度量字段設置爲16。這是一種要求另一端完整路由表的特殊請求報文。

    ·接收到請求。如果這個請求是我們剛纔提到的特殊請求,那麼路由器就將完整的路由表發送給請求者。否則的話,就處理請求中的每一個表項:如果我們有連接到指明地址的路由,則將度量(metric)設置成我們的值,否則將度量置爲16。(度量爲16是一種稱爲“無窮大”的特殊值,它意味着我們沒有到達目的的路由。)然後發回響應。

    ·接收到響應。使響應生效,可能會更新路由表。可能會增加新表項,對已有的表項進行修改,或是將已有表項刪除。

    ·定期選路更新。每過30秒,所有或部分路由器會將其完整路由表發送給相鄰路由器。發送路由表可以是廣播形式的(如在以太網上),或是發送給點對點鏈路的其它終點的。

    ·觸發更新。每當一條路由的度量發生變化時,就對它進行更新。不需要發送完整路由表,而只需要發送那些發生變化的表項。

    每條路由都有與之相關的定時器。如果運行RIP的系統發現一條路由在3分鐘內未更新,就將該路由的度量設置成無窮大(16),並標註爲刪除。這意味着我們已經在630秒更新時間裏沒收到通告該路由的路由器的更新了。再過60秒,將從本地路由表中刪除該路由,以保證該路由的失效已被傳播開。

 

度量

    RIP所使用的度量是以跳(hop)計算的。所有直接連接接口的跳數爲1。考慮圖10.4所示的路由器和網絡。我們畫出的4條虛線是廣播RIP報文。

 

10.4 路由器和網絡示例

 

    路由器R1通過發送廣播到N1通告它與N2之間的跳數是1。(發送給N1的廣播中通告它與N1之間的路由是無用的。)它同時也通過發送廣播給N2通告它與N1之間的跳數爲1。同樣,R2通告它與N2的度量爲1,與N3的度量爲1

    如果相鄰路由器通告它與其它網絡路由的跳數爲1,那麼我們與那個網絡的度量就是2,這是因爲爲了發送報文到該網絡,我們必須經過那個路由器。在我們的例子中,R2N1的度量是2,與R1N3的度量一樣。

    由於每個路由器都發送其路由表給鄰站,因此,可以判斷在同一個自治系統AS內到每個網絡的路由。如果在該AS內從一個路由器到一個網絡有多條路由,那麼路由器將選擇跳數最小的路由,而忽略其它路由。

    跳數的最大值是15,這意味着RIP只能用在主機間最大跳數值爲15AS內。度量爲16表示到無路由到達該IP地址。

 

問題

    這種方法看起來很簡單,但它有一些缺陷。首先,RIP沒有子網地址的概念。例如,如果標準的B類地址中16 bit的主機號不爲0,那麼RIP無法區分非零部分是一個子網號,或者是一個主機地址。有一些實現中通過接收到的RIP信息,來使用接口的網絡掩碼,而這有可能出錯。

    其次,在路由器或鏈路發生故障後,需要很長的一段時間才能穩定下來。這段時間通常需要幾分鐘。在這段建立時間裏,可能會發生路由環路。在實現RIP時,必須採用很多微妙的措施來防止路由環路的出現,並使其儘快建立。RFC 1058 [Hedrick 1988a]中指出了很多實現RIP的細節。

    採用跳數作爲路由度量忽略了其它一些應該考慮的因素。同時,度量最大值爲15則限制了可以使用RIP的網絡的大小。

 

例子

    我們將使用ripquery程序來查詢一些路由器中的路由表,該程序可以從gated中得到。ripquery程序通過發送一個非正式請求(圖10.3中命令字段爲5的“poll”)給路由器,要求得到其完整的路由表。如果在5秒內未收到響應,則發送標準的RIP請求(command字段爲1)。(我們前面提到過的,將地址系列字段置爲0,度量字段置爲16的請求,要求其它路由器發送其完整路由表。)

    10.5給出了我們將從sun主機上查詢其路由表的兩個路由器。如果我們在主機 sun上執行ripquery程序,以得到其下一站路由器netb的選路信息,那麼我們可以得到下面的結果:

 

sun % ripquery -n netb

504 bytes from netb (140.252.1.183):   第一份報文包含504字節

                                                                                這裏刪除了許多行

              140.252.1.0, metric 1           10.5上面的以太網

              140.252.13.0, metric 1          10.5下面的以太網

244 bytes from netb (140.252.1.183):   第二份報文包含剩下的244字節

                                                  下面刪除了許多行  

 

    正如我們所猜想的那樣,netb告訴我們子網的度量爲1。另外,與netb相連的位於機端的以太網(140.252.1.0)的metric也是1。(-n參數表示直接打印IP地址而不需要去查看其域名。)在本例中,將netb配置成認爲所有位於140.252.13子網的主機都與其直接相連——即,netb並不知道哪些主機真正與140.252.13子網相連。由於與140.252.13子網只有一個連接點,因此,通告每個主機的度量實際上沒有太大意義。

 

10.5 我們將要查詢其路由表內容的兩個路由器netbgateway

 

    10.6給出了使用tcpdump交換的報文。我們採用-i s10參數指定SLIP接口。

 

10.6 運行ripquery程序的tcpdump輸出結果

 

    第一個請求發出一個RIP輪詢命令(第1行)。這個請求在5秒後超時,發出一個常規的RIP請求(第2行)。第1行和第2行最後的24表示請求報文的長度:4個字節的RIP首部(包括命令和版本),然後是單個20字節的地址和度量。

    3行是第一個回答報文。該行最後的25表示包含了25個地址和度量對,我們在前面已經計算過,其字節數爲504。這是上面的ripquery程序所打印出來的結果。我們爲tcpdump程序指定-s600選項,以讓它從網絡中讀取600個字節。這樣,它可以接收整個UDP數據報(而不是報文的前半部),然後打印出RIP響應的內容。我們將該輸出結果省略了。

    4行是來自路由器的第二個響應報文,它包含後面的12個地址和度量對。我們可以計算出,該報文的長度爲12×20 + 4=244,這正是ripquery程序前面所打印出來的結果。

    如果我們越過netb路由器,到gateway,那麼可以預測到我們子網(140.252.13.0)的度量爲2。我們可以運行下面的命令來進行驗證:

 

sun % ripquery -n gateway

504 bytes from gateway (140.252.1.4):

                                                                                這裏刪除了許多行

                        140.252.1.0, metric 1           10.5上面的以太網

              140.252.13.0, metric 1          10.5下面的以太網

 

    這裏,位於圖10.5上面的以太網(140.252.1.0)的度量依然是1,這是因爲該以太網直接與gatewaynetb相連。而我們的子網140.252.13.0正如預想的一樣,其度量爲2

 

另一個例子

    我們現在察看以太網上所有非主動請求的RIP更新,以看一看RIP定期給其鄰站發送的信息。圖10.7noao.edu網絡的多種排列情況。爲了簡化,我們不用本文其它地方所採用的路由器表示方式,而以Rn來代表路由器,其中n是子網號。我們以虛線表示點對點鏈路,並給出了這些鏈路對端的IP地址。

 

10.7  noao.edu 140.252的多個網絡

 

    我們在主機solaris上運行Solaris 2.xsnoop程序,它與tcpdump相類似。我們可以在不需要超用戶權限的條件下運行該程序,但它只捕獲廣播報文、多播報文,以及發送給主機的報文。圖10.8給出了在60秒內所捕獲的報文。在這裏,我們將大部分正式的主機名以Rn來表示。

 

10.8  solaris60秒內所捕獲到的RIP廣播報文

 

    -P 標誌以非混雜模式捕獲報文,-tr 打印出相應的時戳,而udp port 520 只捕獲信源或信宿端口號爲520UDP數據報。

    來自R6R4R2R7R8R3的前6個報文,每個報文只通告一個網絡。查看這些報文,我們可以發現R2通告前往140.252.6.0的跳數爲1的一條路由,R4通告前往140.252.4.0的跳數爲1的一條路由,等等。

    但是,gateway路由器卻通告了15條路由。我們可以通過運行 snoop程序時加上-v參數來查看RIP報文的全部內容。(這個標誌輸出全部報文的全部內容:以太網首部,IP首部,UDP首部,以及RIP報文。我們只保留了RIP信息而刪除了其它信息。)圖10.9給出了輸出結果。

    把這些子網140.252.1上通告報文經過的路由與圖10.7中的拓撲結構進行比較。

    使人迷惑不解的一個問題是爲什麼圖10.8輸出結果中,R10通告其有4個網絡而在圖10.7中顯示的只有3個。如果我們查看帶snoopRIP報文,就會得到以下通告路由:

 

RIP Address        Metric

RIP:  140.251.0.0    16 (not reachable)

RIP:  140.252.9.0    1

RIP:  140.252.10.0   1

    RIP:  140.252.11.0   1

 

    前往B類網絡140.251的路由是假的,不應該通告它。(它屬於其它機構而不是noao.edu。)

 

10.9 來自gatewayRIP響應

 

    10.8中,對於 R10發送的RIP報文,snoop輸出“BROADCAST”符號,它表示目的IP地址是有限的廣播地址255.255.255.25512.2節),而不是其它路由器用來指向子網的廣播地址(140.252.1.255)。

 

10.5  RIP協議版本2

    RFC 1388 [Malkin 1993a]中對RIP定義進行了擴充,通常稱其結果RIP-2。這些擴充並不改變協議本身,而是利用圖10.3中的一些標註爲“必須爲0的字段來傳遞一些額外的信息。如果RIP忽略這些必須爲0的字段,那麼,RIPRIP-2可以互操作。

    10.10重新給出了由RIP-2定義的圖。對於RIP-2來說,其版本字段爲2

    選路域(routing domain)是一個選路守護程序的標識符,它指出了這個數據報的所有者。在一個Unix實現中,它可以是選路守護程序的進程號。該域允許管理者在單個路由器上運行多個RIP實例,每個實例在一個選路域內運行。

    選路標記(routing tag)是爲了支持外部網關協議而存在的。它攜帶着一個EGPBGP的自治系統號。

    每個表項的子網掩碼應用於相應的IP地址上。下一站IP地址指明發往目的IP地址的報文該發往哪裏。該字段爲0意味着發往目的地址的報文應該發給發送RIP報文的系統。

 

10.10 RIP-2報文格式

 

    RIP-2提供了一種簡單的鑑別機制。可以指定RIP報文的前20字節表項地址系列爲0xffff,路由標記爲2。表項中的其餘16字節包含一個明文口令。

    最後,RIP-2除了廣播(第12章)外,還支持多播。這可以減少不收聽RIP-2報文的主機的負載。

 

10.6 OSPF:開放最短路徑優先

    OSPF是除RIP外的另一個內部網關協議。它克服了RIP的所有限制。RFC 1247 [Moy 1991]中對第2OSPF進行了描述。

    與採用距離向量的RIP協議不同的是,OSPF是一個鏈路狀態協議。距離向量的意思是,RIP發送的報文包含一個距離向量(跳數)。每個路由器都根據它所接收到鄰站的這些距離向量來更新自己的路由表。

    在一個鏈路狀態協議中,路由器並不與其鄰站交換距離信息。它採用的是每個路由器主動地測試與其鄰站相連鏈路的狀態,將這些信息發送給它的其它鄰站,而鄰站將這些信息在自治系統中傳播出去。每個路由器接收這些鏈路狀態信息,並建立起完整的路由表。

    從實際角度來看,二者的不同點是鏈路狀態協議總是比距離向量協議收斂更快。收斂的意思是在路由發生變化後,例如在路由器關閉或鏈路出故障後,可以穩定下來。[Perlman 1992]9.3節對這兩種類型的選路協議的其它方面進行了比較。

    OSPFRIP(以及其它選路協議)的不同點在於,OSPF直接使用IP。也就是說,它並不使用UDPTCP。對於IP首部的protocol字段,OSPF有其自己的值(圖3.1)。

    另外,作爲一種鏈路狀態協議而不是距離向量協議,OSPF還有着一些優於RIP的特點。

    1. OSPF可以對每個IP服務類型計算(圖3.2)計算各自的路由集。這意味着對於任何目的,可以有多個路由表表項,每個表項對應着一個IP服務類型。

    2. 給每個接口指派一個無維數的費用。可以通過吞吐率、往返時間、可靠性或其它性能來進行指派。可以給每個IP服務類型指派一個單獨的費用。

    3. 當對同一個目的地址存在着多個相同費用的路由時,OSPF在這些路由上平均分配流量。我們稱之爲流量平衡。

    4. OSPF支持子網:子網掩碼與每個通告路由相送連。這樣就允許將一個任何類型的IP地址分割成多個不同大小的子網。(我們在3.7節中給出了這樣的一個例子,稱之爲變長度子網。)到一個主機的路由是通過全1子網掩碼進行通告的。默認路由是以IP地址爲0.0.0.0,網絡掩碼爲全0進行通告的。

    5. 路由器之間的點對點鏈路不需要每端都有一個IP地址。我們稱之爲無編號網絡。這樣可以節省IP地址——現在非常緊缺的一種資源。

    6. 採用了一種簡單鑑別機制。可以採用類似於RIP-2機制(10.5節)的方法指定一個明文口令。

    7. OSPF採用多播(第12章),而不是廣播形式,以減少不參與OSPF的系統負載。

隨着大部分廠商支持OSPF,在很多網絡中OSPF將逐步取代RIP

 

10.7 BGP:邊界網關協議

    BGP是一種不同自治系統之間網關進行通信的外部網關協議。BGPARPANET所使用的老EGP的取代品。RFC1267 [Lougheed and Rekhter 1991] 對第3版的BGP進行了描述。

    RFC 1268 [Rekhter and Gross 1991] 描述瞭如何在Internet中使用BGP。下面對於BGP的大部分描述都來自於這兩個RFC文檔。同時,1993年正在開發第4版的BGP(見RFC 1467 [Topolcic 1993]),以支持我們將在10.8節中所描述的CIDR

    BGP系統與其它BGP系統之間交換網絡可到達信息。這些信息包括數據到達這些網絡所必須經過的自治系統AS中的所有路徑。這些信息足以構造一幅自治系統連接圖。然後,可以根據連接圖刪除選路環,制訂選路策略。

    首先,我們將一個自治系統中的IP數據報分成本地流量和通過流量。在自治系統中,本地流量是起始或終止於該自治系統的流量。也就是說,其信源IP地址或信宿IP地址所指確定的主機位於該自治系統中。其它的流量則稱爲通過流量。在Internet中使用BGP的一個目的就是減少通過流量。

可以將自治系統分爲以下幾種類型:

    1. 殘樁自治系統(stub AS),它與其它自治系統只有單個連接。stub AS只有本地流量。

    2. 多接口自治系統(multihomed AS),它與其它自治系統有多個連接,但拒絕傳送通過流量。

    3. 轉送自治系統(transit AS),它與其它自治系統有多個連接,在一些策略準則之下,它可以傳送本地流量和通過流量。

    這樣,可以將Internet的總拓撲結構看成是由一些殘樁自治系統、多接口自治系統以及轉送自治系統的任意互連。殘樁自治系統和多接口自治系統不需要使用BGP——它們通過運行EGP在自治系統之間交換可到達信息。

    BGP允許使用基於策略的選路。由自治系統管理員制訂策略,並通過配置文件將策略指定給BGP。制訂策略並不是協議的一部分,但指定策略允許BGP實現在存在多個可選路徑時選擇路徑,並控制信息的重發送。選路策略與政治、安全或經濟因素有關。

    BGPRIPOSPF的不同之處在於BGP使用TCP作爲其傳輸層協議。兩個運行BGP的系統之間建立一條TCP連接,然後交換整個BGP路由表。從這個時候開始,在路由表發生變化時,再發送更新信號。

    BGP是一個距離向量協議,但是與(通告到目的地址跳數的)RIP不同的是,BGP列舉了到每個目的地址的路由(自治系統到達目的地址的序號)。這樣就排除了一些距離向量協議的問題。採用16 bit數字表示自治系統標識。

    BGP通過定期發送keepalive報文給其鄰站來檢測TCP連接對端的鏈路或主機失敗。兩個報文之間的時間間隔建議值爲30秒。應用層的keepalive報文與TCPkeepalive選項(第23章)是獨立的。

 

10.8 CIDR:無類型域間選路(Classless Interdomain Routing

    在第3章中,我們指出了B類地址的缺乏,因此現在的多個網絡站點只能採用多個C類網絡號,而不採用單個B類網絡號。儘管分配這些C類地址解決了一個問題(B類地址的缺乏),但它卻帶來了另一個問題:每個C類網絡都需要一個路由表表項。無類型域間選路(CIDR)是一個防止Internet路由表膨脹的方法。它也稱爲超網(supernetting),在RFC 1518 [Rekher and Li 1993] RFC 1519 [Fuller et al. 1993]中對它進行了描述,而[Ford, Rekhter, and Braun 1993]是它的綜述。CIDR有一個InternetArchitecture Board's blessing [Huitema 1993]RFC 1467 [Topolcic 1993] InternetCIDR開發狀況進行了小結。

    CIDR的基本觀點是採用一種分配多個IP地址的方式,使其能夠將路由表中的許多表項總和(summarization)成更少的數目。例如,如果給單個站點分配16C類地址,以一種可以用總和的方式來分配這16個地址,這樣,所有這16個地址可以參照Internet上的單個路由表表項。同時,如果有8個不同的站點是通過同一個Internet服務提供商的同一個連接點接入Internet的,且這8個站點分配的8個不同IP地址可以進行總和,那麼,對於這8個站點,在Internet上,只需要單個路由表表項。

    要使用這種總和,必須滿足以下三種特性。

    1. 爲進行選路要對多個IP地址進行總和時,這些IP地址必須具有相同的高位地址比特。

    2. 路由表和選路算法必須擴展成根據32 bitIP地址和32 bit掩碼做出選路決策的。

    3. 必須擴展選路協議使其除了32 bit地址外,還要有32 bit掩碼。OSPF10.6節)和RIP-210.5節)都能夠攜帶第4BGP所提出的32 bit掩碼。

    例如,RFC 1466 [Gerich 1993] 建議歐洲新的C類地址的範圍是194.0.0.0195.255.255.255。以16進製表示,這些地址的範圍是0xc20000000xc3ffffff。它代表了65536個不同的C類網絡號,但他們地址的高7 bit是相同的。在歐洲以外的國家裏,可以採用IP地址爲0xc200000032 bit0xfe000000 (254.0.0.0) 爲掩碼的單個路由表表項來對所有這些65536C類網絡號選路到單個點上。C類地址的後面各比特位(即在194195後面各比特)也可以進行層次分配,例如以國家或服務提供商分配,以允許在歐洲路由器之間,使用除了這32 bit掩碼的高7 bit外的其它比特進行概括。

    CIDR同時還使用一種技術,使最佳匹配總是最長的匹配:即在32 bit掩碼中,它具有最大值。我們繼續採用上一段中所用的例子,歐洲的一個服務提供商可能會採用一個與其它歐洲服務提供商不同的接入點。如果給該提供商分配的地址組是從194.0.16.0194.0.31.255 (16C類網絡號),那麼可能只有這些網絡的路由表項的IP地址是194.0.16.0,掩碼爲255.255.240.0 (0xfffff000)。發往194.0.22.1地址的數據報將同時與這個路由表表項與其它歐洲C類地址的表項進行匹配。但是由於掩碼255.255.240254.0.0.0更“長”,因此將採用具有更長掩碼的路由表表項。

    “無類型”的意思是現在的選路決策是基於整個32 bitIP地址的掩碼操作。而不管其IP地址是A類、B類或是C類,都沒有什麼區別。

    CIDR的最初是針對新的C類地址提出的。這種變化將使Internet路由表增長的速度緩慢下來,但對於現存的選路則沒有任何幫助。這是一個短期解決方案。作爲一個長期解決方案,如果將CIDR應用於所有IP地址,並根據各洲邊界和服務提供商對已經存在的IP地址進行重新分配(且所有現有主機重新進行編址!),那麼[Ford, Rekhter, and Braun 1993] 是宣稱,目前包含10,000網絡表項的路由表將會減少成只有200個表項。

 

10.9 小結

    有兩種基本的選路協議,即用於同一自治系統各路由器之間的內部網關協議(IGP)和用於不同自治系統內路由器通信的外部網關協議(EGP)。

    最常用的IGP是路由信息協議(RIP),而OSPF是一個正在得到廣泛使用的新IGP。一種新近滸的EGP是邊界網關協議(BGP)。在本章中,我們考慮了RIP及其交換的報文類型。第2版是RIP是其最近的一個改進版,它支持子網,還有一些其它改進技術。我閃同時也對OSPFBGP和無類型域間選路(CIDR)進行了描述,CIDR是一種新技術,採用它可以減小Internet路由表的大小。

    你可能還會遇到一些其它的OSI選路協議。域間選路協議(IDRP)最開始時,是一個爲了使用OSI地址而不是IP地址,而進行修改的BGP版本。Intermediate System to Intermediate System 協議(IS-IS)是OSI的標準IGP。可以用它來選路CLNP(無連接網絡協議),這是一種與IP類似的OSI協議。IS-ISOSPF相似。

    動態選路仍然是一個網間互連的研究熱點。對使用的選路協議和運行的路由守護程序進行選擇,是一項複雜的工作。[Perlman 1992]提供了許多細節。

 

習題:

10.1 在圖10.9中哪些路由是從路由器kpno進入gateway的?

10.2 假設一個路由器要使用RIP通告30個路由,這需要一個包含25條路由和另一個包含5條路由的數據報。如果每過一個小時,第一個包含25條路由的數據報丟失一次,那麼其結果如何?

10.3 OSPF報文格式中有一個校驗和字段,而RIP報文則沒有此項,這是爲什麼?

10.4 OSPF這樣的負載平衡,對於傳輸層的影響是什麼?

10.5 查閱RFC 1058 關於實現RIP的其它資料。在圖10.8中,140.252.1網絡的每個路由器只通告它所提供的路由,而它並不能通過其它路由器的廣播中知道任何其它路由。這種技術的名稱是什麼?

10.6 3.4節中,我們說過除了圖10.7中所示的8個路由器外,140.252.1子網上還有超過100個主機。那麼這100個主機是如何處理每30秒到達它們的8個廣播信息呢(圖10.8

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章