本文已不再維護,更新文章請參考這裡

如果說 IP 是門牌,那麼郵差如何走到你家就是『路由』的功能啦!區域網路如果想成是條巷子,那麼路由器就是那間巷子內的郵局! 其實本章應該是第二章網路基礎的延伸,將網路的設定延伸到整個區網的路由器上而已。那何時會用到路由器? 如果你的環境中需要將整批 IP 再區隔出不同的廣播區段時,那麼就得要透過路由器的封包轉遞能力了。 本章是下一章防火牆與 NAT 的基礎,得先看完才比較容易理解下一章想要討論的事情喔!

8.1 路由
  8.1.1 路由表產生的類型
  8.1.2 一個網卡綁多個 IP:IP Alias 的測試功能
  8.1.3 重複路由的問題
8.2 路由器架設
  8.2.1 什麼是路由器與 IP 分享器sysctl.conf
  8.2.2 何時需要路由器
  8.2.3 靜態路由之路由器
8.3 動態路由器架設:quagga (zebra + ripd)
8.4 特殊狀況:路由器兩邊界面是同一個 IP 網段:ARP Proxy
8.5 重點回顧
8.6 本章習題
8.7 參考資料與延伸閱讀
8.8 針對本文的建議:http://phorum.vbird.org/viewtopic.php?t=26428

8.1 路由

我們在第二章網路基礎裡面談到過路由的相關概念, 他最大的功能就是在幫我們規劃網路封包的傳遞方式與方向。至於路由的觀察則可以使用 route 這個指令來查閱與設定。 好了,那麼路由的形式有哪些?你又該如何確認路由是否正確呢?


8.1.1 路由表產生的類型

如同第二章網路基礎裡面談到的,每一部主機都有自己的路由表, 也就是說,你必須要透過你自己的路由表來傳遞你主機的封包到下一個路由器上頭。 若傳送出去後,該封包就得要透過下一個路由器的路由表來傳送了,此時與你自己主機的路由表就沒有關係啦! 所以說,如果網路上面的某一部路由器設定錯誤,那...封包的流向就會發生很大的問題。 我們就得要透過 traceroute 來嘗試瞭解一下每個 router 的封包流向囉。

OK!那你自己主機的路由表到底有哪些部分呢?我們以底下這個路由表來說明:

[root@www ~]# route -n
Kernel IP routing table
Destination  Gateway        Genmask         Flags Metric Ref  Use Iface
192.168.1.0  0.0.0.0        255.255.255.0   U     0      0      0 eth0 <== 1
169.254.0.0  0.0.0.0        255.255.0.0     U     0      0      0 eth0 <== 2
0.0.0.0      192.168.1.254  0.0.0.0         UG    0      0      0 eth0 <== 3

首先,我們得知道在 Linux 系統下的路由表是由小網域排列到大網域, 例如上面的路由表當中,路由是由『 192.168.1.0/24 --> 169.254.0.0/16 --> 0.0.0.0/0 (預設路由) 』來排列的。 而當主機的網路封包需要傳送時,就會查閱上述的三個路由規則來瞭解如何將該封包傳送出去。 那你會不會覺得奇怪,為什麼會有這幾個路由呢?其實路由表主要有這幾種情況來設計的:

事實上,在 Linux 的路由規則都是透過核心來達成的,所以這些路由表的規則都是在核心功能內啊!也就是在記憶體當中喔! ^_^


8.1.2 一個網卡綁多個 IP: IP Alias 的測試用途

我們在 第五章的 ifconfig 指令裡面談過 eth0:0 這個裝置吧?這個裝置可以在原本的 eth0 上面模擬出一個虛擬介面出來,以讓我們原本的網路卡具有多個 IP ,具有多個 IP 的功能就被稱為 IP Alias 了。而這個 eth0:0 的裝置可以透過 ifconfigip 這兩個指令來達成, 關於這兩個指令的用途請翻回去之前的章節閱讀,這裡不再浪費篇幅啊!

那你或許會問啊:『這個 IP Alias 有啥用途啊?』好問題!這個 IP Alias 最大的用途就是可以讓你用來『應急』! 怎麼說呢?我們就來聊一聊他的幾個常見的用途好了:

不過,你需要知道的是:所有的 IP Alias 都是由實體網卡模擬來的,所以當要啟動 eth0:0 時,eth0 必須要先被啟動才行。而當 eth0 被關閉後,所以 eth0:n 的模擬網卡將同時也被關閉。這得先要瞭解才行, 否則常常會搞錯啟動的裝置啊!在路由規則的設定當中,常常需要進行一些測試,那這個 IP Alias 就派的上用場了。 尤其是學校單位的練習環境當中!

基本上,除非有特殊需求,否則建議你要有多個 IP 時,最好在不同的網卡上面達成,如果你真的要使用 IP Alias 時,那麼如何在開機的時候就啟動 IP alias 呢?方法有很多啦!包括將上面用 ifconfig 啟動的指令寫入 /etc/rc.d/rc.local 檔案中 (但使用 /etc/init.d/network restart 時,該 IP alias 無法被重新啟動), 但鳥哥個人比較建議使用如下的方式來處理:

透過這個簡單的方法,你就可以在開機的時候啟動你的虛擬介面而取得多個 IP 在同一張網卡上了。不過需要注意的是, 如果你的這張網卡分別透過 DHCP 以及手動的方式來設定你的 IP 參數,那麼 dhcp 的取得務必使用實體網卡,亦即是 eth0 之類的網卡代號,而手動的就以 eth0:0 之類的代號來設定較佳。

在舊版的 CentOS 4.x 中,如果你的 eth0 是使用 DHCP 來取得 IP 參數的話,那麼由於 ifup 及 /etc/init.d/network 這兩個 script 內程式碼撰寫的方式,將會導致 ifcfg-eth0:0 這個設定檔不會被使用到喔!不過這個問題在 CentOS 5.x 中已經被克服囉!

8.1.3 重複路由的問題

很多朋友可能都有一個可愛的想法,那就是:『我可不可以利用兩張網卡, 利用兩個相同網域的 IP 來增加我這部主機的網路流量』?事實上這是一個可行的方案, 不過必須要透過許多的設定來達成,若你有需求的話,可以參考網中人大哥寫的這一篇 (註1):

如果只是單純的以為設定好兩張網卡的 IP 在同一個網域就能夠增加你主機的兩倍流量,那可就大錯特錯了∼ 為什麼呢?還記得我們在路由表規則裡面提過網路封包的傳遞主要是依據主機內的路由表規則吧! 那如果你有兩張網路卡時,假設:

那你的路由規則會是如何呢?理論上會變成這樣:
[root@www ~]# route -n
Kernel IP routing table
Destination     Gateway   Genmask         Flags Metric Ref   Use Iface
192.168.0.0     0.0.0.0   255.255.255.0   U     0      0       0 eth1
192.168.0.0     0.0.0.0   255.255.255.0   U     0      0       0 eth0

也就是說,(1)當要主動發送封包到 192.168.0.0/24 的網域時,都只會透過第一條規則 ,也就是透過 eth1 來傳出去! (2)在回應封包方面,不管是由 eth0 還是由 eth1 進來的網路封包,都會透過 eth1 來回傳!這可能會造成一些問題,尤其是一些防火牆的規則方面,很可能會發生一些嚴重的錯誤, 如此一來,根本沒有辦法達成負載平衡,也不會有增加網路流量的效果! 更慘的是,還可能發生封包傳遞錯誤的情況吶!所以說,同一部主機上面設定相同網域的 IP 時, 得要特別留意你的路由規則,一般來說,不應該設定同一的網段的不同 IP 在同一部主機上面。 例如上面的案例就是一個不好的示範啊!

為什麼會特別強調這個觀念呢?大約十年前 (2000) 鳥哥剛接觸 Linux 時,由於當時的網路速度相當緩慢, 為了提升網路流量鳥哥費盡心思啊∼後來想到說,如果有兩片網卡,不就可以增加流量了嗎?於是就設定了兩個同網域的 IP 在一部主機的兩張網卡上,結果呢?很多服務都無法連通了!就是因為痛過,所以才有更強烈的印象啊!錯誤經驗學習法則 ^_^!

8.2 路由器架設

我們知道在區域網路裡面的主機可以透過廣播的方式來進行網路封包的傳送,但在不同網段內的主機想要互相連線時,就得要透過路由器了。 那麼什麼是路由器?他的主要功能是什麼?底下我們就來聊一聊!


8.2.1 什麼是路由器與 IP 分享器

既然主機想要將資料傳送到不同的網域時得透過路由器的幫忙,所以啦,路由器的主要功能就是:『轉遞網路封包』囉!也就是說,路由器會分析來源端封包的 IP 表頭,在表頭內找出要送達的目標 IP 後,透過路由器本身的路由表 (routing table) 來將這個封包向下一個目標 (next hop) 傳送。這就是路由器的功能。 那麼路由器的功能可以如何達成呢?目前有兩種方法可以達成:

高階的路由器可以連結不同的硬體設備,並且可以轉譯很多不同的封包格式,通常...價格也不便宜啊! 在這個章節裡面,我們並沒有要探討這麼高階的咚咚,僅討論在乙太網路裡頭最簡單的路由器功能: 連接兩個不同的網域。嘿嘿!這個功能 Linux 個人電腦就可以達成了!那怎麼達成呢?

就如同路由表是由 Linux 的核心功能所提供的,這個轉遞封包的能力也是 Linux 核心所提供, 那如何觀察核心是否已經有啟動封包轉遞呢?很簡單啊,觀察核心功能的顯示檔案即可,如下所示:

[root@www ~]# cat /proc/sys/net/ipv4/ip_forward
0  <== 0 代表沒有啟動, 1 代表啟動了

要讓該檔案的內容變成啟動值 1 最簡單的方是就是使用:『echo 1 > /proc/sys/net/ipv4/ip_forward』即可。 不過,這個設定結果在下次重新開機後就會失效。因此,鳥哥建議您直接修改系統設定檔的內容,那就是 /etc/sysctl.conf 來達成開機啟動封包轉遞的功能喔。

[root@www ~]# vim /etc/sysctl.conf
# 將底下這個設定值修改正確即可! (本來值為 0 ,將它改為 1 即可)
net.ipv4.ip_forward = 1

[root@www ~]# sysctl -p  <==立刻讓該設定生效

sysctl 這個指令是在核心工作時用來直接修改核心參數的一個指令,更多的功能可以參考 man sysctl 查詢。 不要懷疑!只要這個動作,你的 Linux 就具有最簡單的路由器功能了。而由於 Linux 路由器的路由表設定方法的不同,通常路由器規劃其路由的方式就有兩種:

瞭解了路由器之後,接下來你可能需要瞭解到什麼是 NAT (Network Address Translation, 網路位址轉譯) 伺服器, NAT 是啥?其實 IP 分享器就是最簡單的 NAT 伺服器啦!嘿嘿,瞭解了嗎?沒錯, NAT 可以達成 IP 分享的功能, 而 NAT 本身就是一個路由器,只是 NAT 比路由器多了一個『 IP 轉換』的功能。怎麼說呢?

所以說,當路由器兩端的網域分別是 Public 與 Private IP 時,才需要 NAT 的功能! NAT 功能我們會在防火牆章節時談及,這個章節僅談論一下路由器而已啊! ^_^


8.2.2 何時需要路由器

一般來說,電腦數量小於數十部的小型企業是無須路由器的,只需要利用 hub/switch 串接各部電腦, 然後透過單一線路連接到 Internet 上即可。不過,如果是超過數百部電腦的大型企業環境, 由於他們的環境通常需要考慮如下的狀況,因此才需要路由器的架設:

路由器就只是一個設備,要如何使用端看你的網路環境的規劃!上面僅是舉出一些應用案例。 底下我們先就架設一個靜態路由的路由器來玩一玩吧!


8.2.3 靜態路由之路由器

假設在貴公司的網路環境當中,除了一般職員的工作用電腦是直接連接到對外的路由器來連結網際網路, 在內部其實還有一個部門需要較安全的獨立環境,因此這部份的網路規劃可能是這樣的情況:

靜態路由之路由器架構示意圖
圖 8.2-1、靜態路由之路由器架構示意圖

以上圖的架構來說,這家公司主要有兩個 class C 的網段,分別是:

其中 192.168.1.0/24 是用來做為一般員工連接網際網路用的,至於 192.168.10.0/24 則是給特殊的部門用的。PC1 代表的是一般員工的電腦, PC2 及 PC3, PC4 則是特殊部門的工作用電腦, Linux Router 則是這個特殊部門用來連接到公司內部網域的路由器。在這樣的架構下, 該特殊部門的封包就能夠與公司其他部門作實體的分隔了。

由上圖你也不難發現,只要是具有路由器功能的設備 (Router A, Linux Router) 都會具有兩個以上的介面, 分別用來溝通不同的網域,同時該路由器也都會具有一個預設路由啊! ^_^! 另外,你還可以加上一些防火牆的軟體在 Linux Router 上,以保護 PC2~PC4 的內部電腦呢!

那我們先來探討一下連線的機制好了,先從 PC2 這部電腦談起。如果 PC2 想要連上 Internet ,那麼他的連線情況會是如何?

觀察一下兩部 Router 的設定,要達到上述功能,則 Router A 必須要有兩個介面,一個是對外的 Public IP 一個則是對內的 Private IP ,因為 IP 的類別不同,因此 Router A 還需要額外增加 NAT 這個機制才行,這個機制我們在後續章節會繼續談到。 除此之外,Router A 並不需要什麼額外的設定。至於 Linux Router 就更簡單了!什麼事都不用作,將兩個網路介面卡設定兩個 IP , 並且啟動核心的封包轉遞功能,立刻就架設完畢了!非常簡單!我們就來談一談這幾個機器的設定吧!



在這部主機內需要有兩張網卡,鳥哥在這裡將他定義為:

# 1. 先處理 eth0 
[root@www ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
IPADDR=192.168.1.100
NETMASK=255.255.255.0
GATEWAY=192.168.1.254   <==最重要的設定啊!透過這部主機連出去的!
ONBOOT=yes

# 2. 再先處理 eth1 
[root@www ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
BOOTPROTO=none
ONBOOT=yes
IPADDR=192.168.10.254
NETMASK=255.255.255.0

# 3. 啟動 IP 轉遞
[root@www ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
# 找到上述的設定值,將預設值 0 改為上述的 1 即可!儲存後離開去!
[root@www ~]# sysctl -p
[root@www ~]# cat /proc/sys/net/ipv4/ip_forward
1   <==這就是重點!要是 1 才可以呦!

# 4. 重新啟動網路,並且觀察路由與 ping Router A
[root@www ~]# /etc/init.d/network restart
[root@www ~]# route -n
Kernel IP routing table
Destination     Gateway        Genmask        Flags Metric Ref  Use Iface
192.168.1.0     0.0.0.0        255.255.255.0  U     0      0      0 eth0
192.168.10.0    0.0.0.0        255.255.255.0  U     0      0      0 eth1
169.254.0.0     0.0.0.0        255.255.0.0    U     0      0      0 eth1
0.0.0.0         192.168.1.254  0.0.0.0        UG    0      0      0 eth0
# 上面的重點在於最後面那個路由器的設定是否正確呦!

[root@www ~]# ping -c 2 192.168.1.254
PING 192.168.1.254 (192.168.1.254) 56(84) bytes of data.
64 bytes from 192.168.1.254: icmp_seq=1 ttl=64 time=0.294 ms
64 bytes from 192.168.1.254: icmp_seq=2 ttl=64 time=0.119 ms <==有回應即可

有夠簡單吧!而且透過最後的 ping 我們也知道 Linux Router 可以連上 Router A 囉!這樣你的 Linux Router 就 OK 了吶!接下來則是要設定 PC2 這個被保護的內部主機網路囉。



不論你的 PC2 是哪一種作業系統,你的環境都應該是這樣的:

以 Linux 作業系統為例,並且 PC2 僅有 eth0 一張網卡時,他的設定是這樣的:

[root@www ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
IPADDR=192.168.10.20
NETMASK=255.255.255.0
GATEWAY=192.168.10.254   <==這個設定最重要啦!
ONBOOT=yes

[root@www ~]# /etc/init.d/network restart
[root@www ~]# route -n
Kernel IP routing table
Destination   Gateway         Genmask         Flags Metric Ref  Use Iface
192.168.10.0  0.0.0.0         255.255.255.0   U     0      0      0 eth0
169.254.0.0   0.0.0.0         255.255.0.0     U     0      0      0 eth0
0.0.0.0       192.168.10.254  0.0.0.0         UG    0      0      0 eth0

[root@www ~]# ping -c 2 192.168.1.254

最後一個動作有問題呦!怎麼會連 ping 都沒有辦法 ping 到 Router A 的 IP 呢?如果連 ping 都沒有辦法給予回應的話, 那麼表示我們的連線是有問題的!再從剛剛的回應連線需求流程來看一下吧!

發現了嗎?網路是雙向的,此時封包出的去,但是非常可憐的,封包回不來∼那怎辦呢?只好告知 Router A 當路由規則碰到 192.168.10.0/24 時,要將該封包傳 192.168.1.100 就是了!所以你要這樣進行。



假設我的 Router A 對外的網卡為 eth1 ,而內部的 192.168.1.254 則是設定在 eth0 上頭。 那怎麼在 Router A 增加一條路由規則呢?很簡單啊!直接使用 route add 去增加即可!如下所示的情況:

[root@www ~]# route add -net 192.168.10.0 netmask 255.255.255.0 \
>  gw 192.168.1.100

不過這個規則並不會寫入到設定檔,因此下次重新開機這個規則就不見了!所以,你應該要建立一個路由設定檔。 由於這個路由是依附在 eth0 網卡上的,所以設定檔的檔名應該要是 route-eth0 喔!這個設定檔的內容當中,我們要設定 192.168.10.0/24 這個網域的 gateway 是 192.168.1.100 ,且是透過 eth0 ,那麼寫法就會變成:

[root@www ~]# vim /etc/sysconfig/network-scripts/route-eth0
192.168.10.0/24 via 192.168.1.100 dev eth0
目標網域            透過的gateway     裝置

[root@www ~]# route -n
Kernel IP routing table
Destination   Gateway         Genmask         Flags Metric Ref    Use Iface
120.114.142.0 0.0.0.0         255.255.255.192 U     0      0        0 eth1
192.168.1.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.10.0  192.168.1.100   255.255.255.0   UG    0      0        0 eth0
169.254.0.0   0.0.0.0         255.255.0.0     U     0      0        0 eth1
0.0.0.0       120.114.142.254 0.0.0.0         UG    0      0        0 eth1

上述觀察的重點在於有沒有出現 192.168.10.0 那行路由!如果有的話,請 ping 192.168.10.20 看看能不能有回應? 然後再到 PC2 上面去 ping 192.168.1.254 看看有沒有回應,你就知道設定成功囉!好了,既然內部保護網路已經可以連上 Internet 了, 那麼是否代表 PC2 可以直接與一般員工的網域,例如 PC1 進行連線呢?我們依舊透過路由規則來探討一下,當 PC2 要直接連線到 PC1 時,他的連線方向是這樣的:

有沒有發現一個很可愛的傳輸流程?連線發起是沒有問題啦,不過呢,回應連線竟然會偷偷透過 Router A 來幫忙呦! 這是因為 PC1 與當初的 Router A 一樣,並不知道 192.168.10.0/24 在 192.168.1.100 裡面啦!不過,反正 Router A 已經知道了該網域在 Linux Router 內,所以,該封包還是可以順利的回到 PC2 就是了。



如果你不想要讓 PC1 得要透過 Router A 才能夠連線到 PC2 的話,那麼就得要與 Router A 相同,增加那一條路由規則囉! 如果是 Linux 的系統,那麼如同 Router A 一樣的設定如下:

[root@www ~]# vim /etc/sysconfig/network-scripts/route-eth0
192.168.10.0/24 via 192.168.1.100 dev eth0

[root@www ~]# /etc/init.d/network restart
[root@www ~]# route -n
Kernel IP routing table
Destination    Gateway        Genmask         Flags Metric Ref  Use Iface
192.168.1.0    0.0.0.0        255.255.255.0   U     0      0      0 eth0
192.168.10.0   192.168.1.100  255.255.255.0   UG    0      0      0 eth0
169.254.0.0    0.0.0.0        255.255.0.0     U     0      0      0 eth0
0.0.0.0        192.168.1.254  0.0.0.0         UG    0      0      0 eth0

最後只要 PC2 使用 ping 可以連到 PC1,同樣的, PC1 也可以 ping 到 PC2 的話,就表示你的設定是 OK 的啦!搞定!而透過這樣的設定方式,你也可以發現到一件事,那就是:『路由是雙向的,你必須要瞭解出去的路由與回來時的規則』。 舉例來說,在預設的情況下 (Router A 與 PC1 都沒有額外的路由設定時),其實封包是可以由 PC2 連線到 PC1 的,但是 PC1 卻沒有相關的路由可以回應到 PC2 ∼所以上頭才會要你在 Router A 或者是 PC1 上面設定額外的路由規則啊!這樣說,瞭了吧? ^_^

用 Linux 作一個靜態路由的 Router 很簡單吧!以上面的案例來說,你在 Linux Router 上面幾乎沒有作什麼額外的工作,只要將網路 IP 與網路介面對應好啟動,然後加上 IP Forward 的功能, 讓你的 Linux 核心支援封包轉遞,然後其他的工作咱們的 Linux kernel 就主動幫你搞定了!真是好簡單!

不過這裡必須要提醒的是,如果你的 Linux Router 有設定防火牆的話, 而且還有設定類似 NAT 主機的 IP 偽裝技術,那可得特別留意,因為還可能會造成路由誤判的問題∼ 上述的 Linux Router 當中『並沒有使用到任何 NAT 的功能』喔!特別給他留意到!


8.3 動態路由器架設:quagga (zebra + ripd)

在一般的靜態路由器上面,我們可以透過修改路由設定檔 (route-ethN) 來設定好既定的路由規則,讓你的路由器運作順利。不過, 這樣的方法總是覺得很討厭!如果某天因為組織的再造導致需要重新規劃子網路網段,如此一來,你就得要在圖 8.2-1 的 Router A 與 Linux Router 再次的處理與檢查路由規則,真是有夠麻煩的∼ 那能不能讓路由器自己學習新的路由,來達成自動增加該筆路由的資訊呢?

上述的功能就是所謂的動態路由。動態路由通常是用在路由器與路由器之間的溝通,所以要讓你的路由器具有動態路由的功能, 你必須要瞭解到對方路由器上面所提供的動態路由協定才行,這樣兩部路由器才能夠透過該協定來溝通彼此的路由規則。 目前常見的動態路由協定有:RIPv1, RIPv2, OSPF, BGP 等。

想要在 CentOS 上面搞定這些動態路由的相關機制,那就得要使用 quagga 這個軟體啦!這個軟體是 zebra 計畫的延伸, 相關的官網說明可以參考文後的參考資料(註3)。既然要玩 quagga ,自然就得要先安裝他囉!趕緊處理吧!

[root@www ~]# yum install quagga
[root@www ~]# ls -l /etc/quagga
-rw-r--r-- 1 root   root      410 10月 21  2010 ripd.conf.sample
-rw-r----- 1 quagga quagga     29  5月 23 16:14 zebra.conf
-rw-r--r-- 1 root   root      373 10月 21  2010 zebra.conf.sample
.....(其他省略).....

這個軟體所提供的各項動態路由協定都放置到 /etc/quagga/ 目錄內,底下我們以較為簡單的 RIPv2 協定來處理動態路由, 不過你得要注意的是,不論你要啟動什麼動態路由協定,那個 zebra 都必須要先啟動才行!這是因為:

而各個路由服務的設定檔都必須要以 /etc/quagga/*.conf 的檔名來儲存才行,如上表我們可以發現 zebra 這個服務是有設定好了,不過 ripd 的檔名卻不是 .conf 結尾。所以我們必須要額外作些設定才行。

為了練習一下我們的 quagga ,當然得要設計一下可能的網路連線囉∼假設網路連線的圖示如下,共有三個區網的網段, 其中最大的是 192.168.1.0/24 這個外部區網,另有兩個內部區網分別是 192.168.10.0/24 及 192.168.5.0/24 。

練習動態路由所設定的網路連線示意圖
圖 8.3-1、練習動態路由所設定的網路連線示意圖

上圖的兩部 Linux Router 分別負責不同的網域,且可以透過 192.168.1.0/24 這個網域來溝通。在沒有設定額外路由規則的情況下,那個 PC1 與 PC2 是無法溝通的!另外,quagga 必須要同時安裝在兩部 Linux Router 上頭才行, 而且我們只要設定好這兩部主機的網路介面 (eth0, eth1) 後,不需要手動輸入額外的路由設定喔!可以透過 RIP 這個路由協定來搞定的!


透過這個 quagga 以及 RIPv2 的路由協定的輔助,我們可以輕鬆的就將路由規則分享到附近區網的其他路由器上頭, 比起單純使用 route 去修改 Linux 的核心路由表,這個動作當然要快速很多!不過,如果是很小型的網路環境,那麼不要使用這個 quagga 啊!因為有點多此一舉的感覺。如果你的企業環境真的有夠大,那麼玩一玩這個 quagga 配合一些動態路由協定,嘿嘿!也是可行的啦!

鳥哥差一點被這一版的 ripd.conf 設定內容搞死∼因為 CentOS 5.x 預設的 RIPv2 會去進行身份驗證,所以原先在 CentOS 4.x 的設定是不能用的,偏偏登錄檔又看不出個所以然..後來查到可以透過 ripd.conf 內的 debug 參數去設定除錯登錄, 才發現 RIPv2 的認證問題!最終 google 一下才解決問題∼好累啊!

8.4 特殊狀況:路由器兩邊界面是同一個 IP 網段: ARP Proxy

如果你一開始設計的網路環境就是同一個 Class C 的網域,例如 192.168.1.0/24 , 後來因為某些因素必須要將某些主機搬到比較內部的環境中,例如圖 8.2-1的 PC2 ~ PC4 。 然後又因為某些因素,所以你不能變更 PC2 ~ PC4 的 IP ,此時你的同一網域就會橫跨在一個路由器的左右兩邊了! 舉例來說,連線圖示有點像底下這樣:

在路由器兩個介面兩邊的 IP 是在同一個網域的設定情況
圖 8.4-1、在路由器兩個介面兩邊的 IP 是在同一個網域的設定情況

初次見面∼看到眼睛快要掉下來哩!怎麼路由器的兩邊的主機 IP 設定都在同一個網域內?而且還被規定不能夠更改原先的 IP 設定, ...真是一個頭兩個大啊∼如此一來,在 Linux Router 兩邊要如何製作路由啊?好問題!真是好問題∼ 因為 OSI 第三層網路層的路由是一條一條去設定比對的,所以如果兩塊網卡上面都是同一個網域的 IP 時, 就會發生錯誤。那如何處理啊?

我們先從兩方面來說,第一個,當從正確的網段 (PC1) 要連線到 PC2~PC4 時,他應該是要透過 Linux Router 那部主機的對外 IP (192.168.1.100) 才行!而且 Linux Router 還必須要讓該封包透過內部 IP (192.168.1.200) 連線到 PC2~PC4 。 此時,封包傳遞的圖示有點像這樣:

正常的網段想要傳送到內部電腦去的封包流向
圖 8.4-2、正常的網段想要傳送到內部電腦去的封包流向

在這個階段,我們可以設定PC2~PC4 的 IP 所對應的網卡卡號 (MAC) 都設定在 router 的對外網卡上, 因此, router 的對外介面可以將給 PC2~PC4 的封包給『騙』過來。接下來,就簡單的透過路由設定,讓封包轉個介面發送出去即可。 這樣 PC1 --> PC2 的問題解決了,但是 PC2 怎麼傳送到 PC1 呢?我們可以透過底下的圖示來想像一下:

內部電腦想要傳送到正常網域時的封包流向
圖 8.4-3、內部電腦想要傳送到正常網域時的封包流向

當 PC2 要傳送的封包是給 PC3, PC4 的,那麼這個封包得要能夠直接傳遞。但是如果需要傳送到正常網域的封包,就得要透過 router 的對內網卡,再透過路由規則來將該封包導向外部介面來傳遞才行!這個時候就變成內部的介面欺騙 PC2 說, PC1 與 Router A 的 IP 是在內部這張介面上就是了,然後再透過路由判斷將該封包透過外部介面來對外傳遞出去即可。 假設 Linux router 的對外介面為 eth0 而對內為 eth1 時,我們可以這樣說:

  1. 當 Linux Router 的 eth0 那個網域主機想要連接到 PC2~PC4 的主機時,由 Linux Router 負責接收;
  2. 當 Linux Router 要傳送資料到 PC2~PC4 時,務必要由 eth1 來傳送;
  3. 當內部電腦想要連接到 PC1 或 Router A 時,由 Linux router 的 eth1 負責接收;
  4. 當 Linux Router 要傳送的資料為 192.168.1.0/24 ,但並非 PC2~PC4 時,需由 eth0 傳送。

上列的步驟與圖示內的線條上的順序相符合呦!得要對照著看看。其中的 (1) 與 (3) 就是透過 ARP Proxy (代理) 的功能啦! 那啥是 ARP Proxy 呢?簡單的說,就是讓我的某張介面卡的 MAC 代理其他主機的 IP 對應,讓想要連接到這個 IP 的 MAC 封包由我幫他接下來的意思。舉我們圖 8.4-1 的例子來說,就是在 Linux Router 的 eth0 介面上,規定 192.168.1.20, 192.168.1.30, 192.168.1.40 這三個 IP 都對應到 eth0 的 MAC 上,所以三個 IP 的封包就會由 eth0 代為收下,因此才叫做 ARP 代理人嘛!所以啦,每一部在 eth0 那端的主機都會『誤判』那三個 IP 是 Linux Router 所擁有,這樣就能夠讓封包傳給 Linux Router 啦!

再接下來,咱們的 Linux Router 必須要額外指定路由,設定情況為:

也就是說,你必須要指定路由規則當中,那個 PC2~PC4 具有優先選擇權,然後其他的同網域封包才由 eth0 來傳送。 這樣就能夠達成我們所想要的結局啦!^_^!看樣子似乎很難,其實設定方面還挺簡單的,你可以透過 arp 以及 route 這兩個指令來達成喔!

# 1. 先設定外部 eth0 的 ARP Proxy,讓三個 IP 對應到自己的 MAC
[root@www ~]# arp -i eth0 -s 192.168.1.20 00:E0:81:71:7C:D6 pub
[root@www ~]# arp -i eth0 -s 192.168.1.30 00:E0:81:71:7C:D6 pub
[root@www ~]# arp -i eth0 -s 192.168.1.40 00:E0:81:71:7C:D6 pub
[root@www ~]# arp -n
Address             HWtype  HWaddress      Flags Mask       Iface
192.168.1.30        *       *              MP               eth0
192.168.1.40        *       *              MP               eth0
192.168.1.20        *       *              MP               eth0
# 首先需要讓外部介面擁有三個 IP 的操控權,透過這三個指令來建立 ARP 對應!

# 2. 開始處理路由,增加 PC2~PC4 的單機路由經過內部的 eth1 來傳遞
[root@www ~]# route add -host 192.168.1.20 eth1
[root@www ~]# route add -host 192.168.1.30 eth1
[root@www ~]# route add -host 192.168.1.40 eth1
[root@www ~]# route -n
Kernel IP routing table
Destination    Gateway        Genmask         Flags Metric Ref  Use Iface
192.168.1.40   0.0.0.0        255.255.255.255 UH    0      0      0 eth1
192.168.1.30   0.0.0.0        255.255.255.255 UH    0      0      0 eth1
192.168.1.20   0.0.0.0        255.255.255.255 UH    0      0      0 eth1
192.168.1.0    0.0.0.0        255.255.255.0   U     0      0      0 eth0
192.168.1.0    0.0.0.0        255.255.255.0   U     0      0      0 eth1
169.254.0.0    0.0.0.0        255.255.0.0     U     0      0      0 eth1
0.0.0.0        192.168.1.254  0.0.0.0         UG    0      0      0 eth0
# 這樣就處理好單向的單機路由囉!不過有個問題啊!那就是 192.168.1.0/24
# 的網域,兩個介面都可以傳送!因此,等一下第四個步驟得要將他刪除才行!

3. 設定一下內部的 ARP Proxy 工作 (綁在 eth1 上頭囉)!
[root@www ~]# arp -i eth1 -s 192.168.1.10  00:E0:4C:F0:B5:5B pub
[root@www ~]# arp -i eth1 -s 192.168.1.254 00:E0:4C:F0:B5:5B pub
# 這樣可以騙過 PC2 ~ PC4 ,讓這三部主機傳遞的封包可以透過 router 來傳遞!

4. 開始清除掉 eth1 的 192.168.1.0/24 路由
[root@www ~]# route del -net 192.168.1.0 netmask 255.255.255.0 eth1

所有的電腦都在同一個網域內,因此 default gatway 都是 192.168.1.254 ,而 netmask 都是 255.255.255.0, 只有 IP 不一樣而已。最後,所有的電腦都可以直接跟對方連線,也能夠順利的連上 Internet ! 這樣的設定就能夠滿足上述的功能需求囉!如果一切都沒有問題,那麼將上述的指令寫成一個腳本檔, 例如 /root/bin/network.sh ,然後將該檔案設定為可執行,並將它寫入 /etc/rc.d/rc.local , 同時每次重新啟動網路後,就得要重新執行一次該腳本,即可達到你的需求囉!

透過這個案例你也可以清楚的知道,能不能連線其實與路由的關係才大哩! 而路由是雙向的,你必須要考量到這個封包如何回來的問題喔!


重點回顧

本章習題

參考資料與延伸閱讀

2002/08/09:第一次完成日期!
2003/08/22:重新編輯文章,並增加重點回顧與課後練習
2006/08/21:將舊的文章移動到 此處
2006/08/30:加入了 zebra 以及 ARP Proxy 等與 Router 比較相關的議題!
2010/09/23:將舊的基於 CentOS 4.x 的版本移動到 此處
2010/10/26:修訂了部分資料,尤其是 ARP 的說明部分!不過,重點於題目都還沒有更新!