1. 程式人生 > >一個非典型的Linux路由配置方案

一個非典型的Linux路由配置方案

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

                       

上週幫人解決了一個問題,這個問題絕對是非典型性的,採用了非常規的方法。雖然最終的方案非常不符合常規非常不通用,充滿了各種藏得很深的技巧或者說是trick,但是這個問題卻是一個學習Linux路由的絕好機會。事後想了很久,還是決定分享出來,本文並不主張使用奇技淫巧去解決通用問題,但是本文主張遇到問題後至少要有折騰到該領域的原子級別。

  清晨馬上就要天亮,聽著窗外小鳥兒在歌唱,我把問題重新整理,形成一個新的問題。先看需求,以下是一個拓撲:
這裡寫圖片描述

現在的需求是:

hostA和hostB之間雙向互聯互通!

這難道不是把Router做成Bridge(這是Linux的術語,正確的說法應該是switch)或者為hostA到Router之間另開闢一個IP地址段麼??為什麼沒有這麼做本文不深究也不會暴露,現在的問題是,就上面這個拓撲,怎麼能通吧。

  誠然,如果你已經很熟悉Linux路由的方方面面,那麼下面的內容你早就耳熟能詳,但我相信大部分做不到。另外,本文將體現一種解決問題的方法和精神,即見招拆招。畫出流程圖或者時序圖,哪裡有阻礙,就清除哪裡。


為了不扯過多哲學上的論述,避免進入形而上的爭辯,我先把一個顯然的配置配在Router上,即Router到hostA的路由:

ip route add 192.168.0.1/32 dev eth1 src 192.168.0.2
   
  • 1

畢竟eth1連IP地址都沒有,我們只能把經由它的資料包強行推給它,不然還能怎麼做呢?攜帶src引數是因為為了讓資料包到達hostA的時候,讓hostA覺得這個資料包看上去是從同一網段來的,即經由了Link路由到達的本機,而不是被強行扭送到了本機。僅此,事先說明。
  然後呢?


然後我們來分兩種情況看一下到達hostB的192.168.0.3的資料包如何從hostA出去。

  首先,第一種方法是一個顯而易見的方法,即通過鏈路層發現的路由出去,但因為這個太顯然了,因此我準備先介紹第二種方法,即通過預設路由讓Router中轉到達hostB

  為了去dig一下第二種方法,我決定對hostA進行如下配置:

ip addr add dev eth0 192.168.0.1/24ip route add 0.0.0.0/0 via 192.168.0.2# 刪除鏈路層路由,避免直接ARP同網段目標IPip route del 192.168.0.0/24 
   
  • 1
  • 2
  • 3
  • 4

或者更加trick一點:

ip addr add dev eth0 192.168.0.1/30# 佔用.3廣播,你要親自試試 :-)...
   
  • 1
  • 2
  • 3

假設我採用了第一個配置,那麼接下來事情就要慢慢起變化了。

  我準備採用時序圖來描述這一切是為什麼發生的,首先我要將hostA,hostB以及Router的各個網絡卡抽象成各種Object,同時Router的路由邏輯我也抽象成了一個單獨的Object,這樣時序圖就可以更好地演繹了。另外的假設是,我假定在通訊開始時,所有涉事裝置的所有ARP表都是空的。下面開始演繹:

這裡寫圖片描述

一切都非常流轉,只要注意紅色部分就好了,這部分是唯一被拆招的地方,其它的都是例行公事而已。然而就這個地方你要是不懂,整個鏈路就不會通,道理就這麼簡單。

  好了,接下來看看從hostB反過來ping hostA時一路上會發生什麼,宣告一點,我把時序圖左右顛倒反過來畫了,這是為了和上面的情況好做對比:

這裡寫圖片描述

也不難,也很容易,流程清晰了就都清晰了。不是嗎?

  下面該介紹第二種情況了,即hostA直接廣播的情況,我們知道,這只是影響了從hostA到hostB的流程,而對反向的hostB到hostA的流程絲毫沒有任何影響,因此在這種情況下,只有一幅時序圖。

  先給出hostA的配置:

ip addr add dev eth0 192.168.0.1/24
   
  • 1

僅此而已,如此一來,當在hostA上發起到達hostB的ping時,路由邏輯會首選自動生成的鏈路層路由,落實到鏈路層,即直接請求hostB的MAC,而該請求會被Router的eth1首先捕獲到,它該怎麼做呢?請看圖:

這裡寫圖片描述

好了,到底位置,問題全部解決。總結下來幾乎什麼都沒說,因為這個問題確實是沒有難度但很詭異,屬於能讓人走火入魔的那種,不管怎麼說吧,本文的目標是想介紹以下的協議棧引數:

  • arp_announce
  • arp_ignore
  • proxy_arp
  • ip_forward

以及以下的命令:

  • arptables

最終總結下來就是兩種方式:

方法1:使用Router預設路由中轉

#### hostAip addr add dev eth0 192.168.0.1/24ip route add 0.0.0.0/0 via 192.168.0.2   # 刪除鏈路層路由,避免直接ARP同網段目標IPip route del 192.168.0.0/24 #### Routerip route add 192.168.0.1/32 dev eth1 src 192.168.0.2sysctl -w net.ipv4.conf.eth0.proxy_arp=1sysctl -w net.ipv4.conf.eth1.proxy_arp=1sysctl -w net.ipv4.ip_forward=1arptables -A OUTPUT -o eth1 -j mangle --mangle-ip-s 192.168.0.2
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

方法2:預設路由

#### hostAip addr add dev eth0 192.168.0.1/24ip route add 0.0.0.0/0 via 192.168.0.2ip route del 192.168.0.0/24 #### Router:ip route add 192.168.0.1/32 dev eth1 src 192.168.0.2sysctl -w net.ipv4.conf.eth0.proxy_arp=1sysctl -w net.ipv4.conf.eth1.arp_ignore=3sysctl -w net.ipv4.ip_forward=1arptables -A OUTPUT -o eth1 -j mangle --mangle-ip-s 192.168.0.2
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

arp_ignore和proxy_arp有什麼區別?

  • arp_ignore:IP地址在本機,但是不在本網絡卡上,是否回覆自己的MAC;
  • proxy_arp:IP地址不在本機,但路由可達,是否回覆自己的MAC

最後宣傳下iproute2,勸你放棄iputils…這是潮流。iptoute2指的是統一由ip命令分發子命令的操作,很多的主流網路操作平臺都是這種方式,比如Cisco,華為VRP,甚至微軟的netsh等都是這樣的風格,而iputils則是之前獨立的命令列方式,比如ifconfig,arp,route這些都是獨立的命令,這種目前是不提倡的,這是古老的風格…

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述