17.2. 閘道與路徑

Contributed by Coranth Gryphon . 6 October 1995.

為了讓一部電腦能找到另一部電腦,因此必需要有一種機制, 讓這部電腦知道該怎麼做,這個機制就是路徑選擇(routing)。 一個路徑("route")是由一對位址所定義的:一個 "目標"以及一個閘道("gateway")。 這對位址表示要送到目標的封包, 必須經過閘道。 目標分為三種類型:主機、子網路(subnet)和預設路徑 ("default route")。 如果沒有其它的路徑可以使用,這時就會使用預設路徑, 稍後我們會對預設路徑作進一步的說明。此外,閘道也有三種類型: 主機、傳輸介面(interface,也稱為 "links") 和乙太網路硬體位址。

17.2.1. 範例

為了說明不同類型的路徑選擇, 我們將使用由netstat -r指令取得的資料作為範例:

    Destination      Gateway            Flags     Refs     Use     Netif Expire
    
    default          outside-gw         UGSc       37      418      ppp0
    localhost        localhost          UH          0      181       lo0
    test0            0:e0:b5:36:cf:4f   UHLW        5    63288       ed0     77
    10.20.30.255     link#1             UHLW        1     2421 
    foobar.com       link#1             UC          0        0 
    host1            0:e0:a8:37:8:1e    UHLW        3     4601       lo0
    host2            0:e0:a8:37:8:1e    UHLW        0        5       lo0 =>
    host2.foobar.com link#1             UC          0        0
    224              link#1             UC          0        0

第一行是預設路由(我們會在下一段說明), 第二行則是localhost路徑。

Netif可以知道localhost 所使用的介面是lo0,也就是loopback設備。 這表示所有的封包不會被送上網路,而是在內部處理。

接下來是0:e0:...這些位址。 這些都是乙太網路硬體位址,FreeBSD會自動識別在同一個乙太網路中的主機 (如test0),並且將它加入路徑表,然後經由 ed0這個介面直接與它通訊, 這種路徑都會有一個保留時間(Expire), 如果與那部主機間一直沒有任何通訊,在超過保留時間之後, 這筆路徑會自動被刪除。這些主機就是用一種稱為RIP (Routing Information Protocol)的機制來識別, 經由RIP我們可以得到與本地主機通訊的最佳路徑。

FreeBSD也會替本地網路設定路徑 (10.20.30.255是網路 10.20.30的廣播位址, foobar.com則是網域名稱)。 link#1代表主機的第一片乙太網路卡, 你也許也注意到了,這些路徑都沒有指定介面。

主機和本地網路的路徑是由routed這個daemon 自動設定的,如果沒有執行routed, 那就只有靜態路徑存在。

由乙太網路位址可以知道host1這一行就是我們的主機 因為我們的主機是發送端,FreeBSD知道該使用loopback介面 (lo0),而非送到乙太網路介面。

host2這兩行是為了示範當我們使用ifconfig 別名時的狀況(這麼做的原因請參見乙太網路這個部份)。 lo0之後的 =>符號表示我們所使用的loopback是個別名。 這種路徑只有在支援別名的主機上會被顯示出來, 其它本地主機對這種路徑只會簡單的顯示一行link#1

最後一行(目標子網路224)是用於MultiCasting, 我們會再說明。

另外就是Flags所代表的意思, 每一個路徑的屬性都在這裡顯示,下面的表格是這些屬性的簡短說明:

U啟動(Up):代表正常運作。
H主機(Host):通向一部主機的路徑。
G閘道(Gateway):任何送到目標的封包都會先被這部主機接收, 然後再由這部主機轉送。
S靜態(Static):這種路徑是人工設定的,並非由系統自動產生。
CClone:以此路徑為基礎產生新的路徑, 這種路徑通常只在本地網路使用。
WWasCloned:表示這個路徑是以屬性為C(Clone)的路徑為基礎自動產生的。
LLink:路徑參考到乙太網路硬體。

17.2.2. 預設路徑

當本地主機需要與遠端主機通連時, 本地主機會先到路徑表裡頭去尋找是否已經有可以使用的路徑, 如果遠端主機位於我們已經知道的子網路(Cloned routes), 系統就會檢查是否能經由這條路徑進行通連。

如果所有已知路徑都無法使用,系統只有一個最後的選擇:預設路徑。 預設路徑是一種特別的閘道路徑(通常也是系統中唯一的一個), 而且一定會伴隨著一個屬性c, 位於區域網路中的主機可以將閘道設定成任何與外界直接通連的機器 (無論是用PPP或是一部與專線連接的硬體)。

如果一部機器是通往外介的閘道,而你又將這部機器的預設路徑設為機器自 這個時候ISP(Internet Service Provider)的閘道器就會變成預設路徑。

讓我們看看一個預設路徑的例子,這是一個常見的狀況:

[Local2]  <--ether-->  [Local1]  <--PPP--> [ISP-Serv]  <--ether-->  [T1-GW]
      

Local1Local2 這兩部主機都和你在同一個地方,並且使用點對點通訊協定(PPP)與ISP相連, 這家ISP有他們自己的區域網路, 包括與你連接的伺服器以及與網際網路相連的硬體裝置(T1-GW)。

這兩部主機的預設路徑如下:

主機預設閘道介面
Local2Local1ethernet
Local1T1-GWPPP

一個常見的問題;"為什麼將預設路徑設成T1-GW, 而不是我們所連接的伺服器呢?"

別忘了,既然PPP介面使用的位址是屬於ISP的區域網路, 在這個區域網路中所有主機的路徑就會自動產生, 因此自然也就得到T1-GW這部機器的路徑,所以多餘的設定是不需要的。

一般都是把...1 這個位址做為本地網路的閘道位址,因此, 如果你的class-C位址是10.20.30, 而ISP是用10.9.9,這時預設路徑就是:

Local2 (10.20.30.2)             -->  Local1 (10.20.30.1)
Local1 (10.20.30.1, 10.9.9.30)  -->  T1-GW (10.9.9.1)
      

17.2.3. Dual homed主機

還有一種配置方式是我們應該知道的, 那就是一部連接兩個不同網路的主機, 技術上來來,任何做為閘道的機器都可以視為daul-homed主機, 但是這個名詞僅用來表示同時連接兩個區域網路的機器。

舉例來說,一部機器插了兩片網路卡, 兩片網路卡的位址都在不同的子網路上; 另外一個例子就是,一部機器只插了一片網路卡,但是用了ifconfig加上別名。 第一個例子是在同時使用兩個實體乙太網路時, 第二個例子是只有一個實體網路, 但是在邏輯上有兩個子網路。

此外, 可以設定路徑表讓每個子網路知道這臺機器是通往另一個子網路的閘道, 將機器做為兩個子網路的橋接器時,通常會用這種方法來設置封包過濾 (packet filtering)或防火牆(firewall)。

17.2.4. 路徑傳播(Routing propagation)

我們知道如何設定通向外頭的路徑, 但是還不知道別人是怎麼找到我們的。

我們知道經由設定路徑表,所有送到某段位址的封包 (在範例中是一個class-C的網路)都會被送到一部位於目標網路的特定主機, 接著這部主機會將封包轉送給真正的接收者。

當你為子網路取得一段位址時,ISP會設定他們的路徑表, 所以所有送給你的封包都會經由PPP送到你的網路。 但是位於其他國家的電腦是如何知道要將封包送給你的ISP呢?

有一個系統(與DNS的架構很像)不斷的記錄所有分配的位址, 並且為它們設定網際網路骨幹(Internet Backbone)的連接點, ``Backbone''是負責全球網際網路通訊的骨幹線路, 每一部位於骨幹線路上的機器(backbone machine)都保存一份對應表, 有了這份對應表,封包就可以送到你的ISP,最後到達你的網路。

此外,ISP也必須讓骨幹線路上的機器知道你是經由這家ISP連上網路的。 這個程序就是路徑傳播。

17.2.5. 解決問題

有時候路徑傳播(routing propagation)出了問題, 導致某些地方的電腦無法與你通連, 也許traceroute(8)這個最有用的指令可以幫你找出路徑是在哪裡中斷, 這個指令在你無法與遠端主機通連時一樣有用(例如當ping(8)失敗時)。

traceroute(8)這個指令是以你要連接的遠端主機做為參數, traceroute(8)會將封包所經過的閘道顯示出來, 無論最後是否能成功到達遠端主機。

請參考線上手冊(manual page)取得更多關於traceroute(8)的資訊。