路由條目的意義


路由條目的意義

  路由的設計遠比一般的理解要復雜的多。典型的路由條目包括了源IP,目的IP,網關IP,scope,dev和type六個要素。

  網關IP就是在配置路由的時候指定的via后面的地址,在路由表中叫Gateway,這是說明這條路由的下一跳是這個IP地址。這個IP地址之所以出現,是因為目的地址不是當前自己出口可以直接可達的,需要經過網關路由到下個網絡才能投遞。

  也就是因此,如果這個via域配置為0.0.0.0,或者是用*表示,總之是代表一定的通配,那么就意味着這個路由的目的地和自己在一個二層的網絡,到達那個目的地並不需要網關轉發,只需要配置MAC地址從端口上發出去即可。這個發送出去的過程顯然是去查ARP表,通過IP地址查詢目標的MAC地址。很容易理解網關在路由條目中的意義,如果到達一個目標地址是需要通過網關轉發出去的,via就要指定網關。大部分的個人局域網中,都會指定一個默認網關,目的IP填寫了0.0.0.0,也就是所有的目的地址(通常使用命令的時候,這個詞語叫做default),via后面填寫網關地址。這樣在其他的更精確的路由條目都不命中的情況下,就一定會命中這個默認路由條目。因為這個條目的目的IP設置是通配。使用ip命令設置這樣的默認路由是例如ip route add default via 10.0.0.1。

  假設一個路由條目指定了gateway,那么決策還需要知道這個gateway到底是從哪個網口發出去可達的,這就是dev的作用。既然到一個gateway必然要從一個設備出去,而其他的地方並不能指定這個gateway和設備的對應關系,於是就在路由表這里就指定了。通過dev可以到達該gateway。

  如果gateway不指定,也就是該路由在同一個二層,那么仍然需要指定dev,因為即使是發送出去,也需要查從哪里發送出去。因為在收到一個數據包的時候,進入系統的時候目的IP不是自己就需要根據目的IP來查找路由,這個路由會決定這個目的IP是要轉發給哪個端口(通常通過目的IP和網關IP和dev來決定)。

  Dev是相對於gateway的一個更小的約束。同樣起到約束作用的還有scope。Scope是一個更小程度的約束,指明了該路由在什么場景下才有效。也是用於約束目的地址的。例如不指定網關的二層路由,通常對應的scope類型是scope link。scope link的意義就是說明在同一個二層。這個意義與網關不指定的效果是呼應的。

  有四種scope,global是在任何的場景下都有效,link是在鏈路上才有效,這個鏈路是指同一個端口,也就是說接收和發送都是走的同一個端口的時候,這條路由才會生效(也就是說在同一個二層)。Global則可以轉發,例如從一個端口收到的包,可以查詢global的路由條目,如果目的地址在另外一個網卡,那么該路由條目可以匹配轉發的要求,進行路由轉發。Link的scope路由條目是不會轉發任何匹配的數據包到其他的硬件網口的。還有就是host,host表示這是一條本地路由,典型的是回環端口,loopback設備使用這種路由條目,該路由條目比link類型的還要嚴格,約定了都是本機內部的轉發,不可能轉發到外部。Site則是ipv6專用的路由scope。

  源IP是一個路由條目的重要組成部分,這個源IP的意義在於一個補充作用。匹配還是根據目的IP進行匹配,但是由於在查找路由條目的時候很可能源地址還沒有指定。典型的就是沒有進行bind的發送情況,通常是隨機選擇端口和按照一定的規則源地址。這個一定的規則就是在這里的路由條目的src域可以影響。也就是如果進程沒有bind一個源地址,將會使用這里src域里面的源地址作為數據包的源地址進行發送。但是如果進程提前bind了,命中了這個條目,就仍然會使用進程bind的源地址作為數據包的源地址。所以說這里的src只是一個建議的作用。

# ip route
default via 115.238.122.129 dev eth1 
115.238.122.128/25 dev eth1  proto kernel  scope link  src 115.238.122.163 
192.168.0.160/24 dev dpdk0.kni  proto kernel  scope link  src 192.168.0.163 
192.168.1.160/24 dev dpdk1.kni  proto kernel  scope link  src 192.168.1.163 

  舉一個例子,從本機發出的目的地址是192.168.0.160/24網段的數據包將匹配第三條路由,如果在查詢路由表之前沒有設置bind,這個查詢路由表的操作就會把數據包的源地址設置為192.168.0.163 。如果設置了bind,就保留bind的結果(所以你可以很容易的在Linux的主機上偽造原地址發送數據)。

  src域在處理轉發的數據包的時候,由於數據包是從外部收到的,外部進來的數據包也會查找路由表,也能命中同一個路由條目。但是由於外部進來的數據包已經有了明確的源地址,這里的src源地址建議就不會起作用了。所以關鍵就是理解src只是一個源地址的一個建議的作用即可。

  對於路由表,是一個匹配的過程。一個數據包去查找匹配自己最能夠匹配哪條路由表,然后就使用該路由條目指定的路由方法進行路由轉發。匹配的方法就是鼎鼎大名的LPM,簡單的說,就是匹配最匹配的那一個。

  所以整個過程可以看到,核心的是對目的地址的限制,其他的域都是用於輔助這個限制,甚至可以輔助決策。

  我們看一個虛擬機里的默認路由表:

root@ubuntu:~/# ip route show

default via 192.168.142.2 dev ens33 proto static metric 100

169.254.0.0/16 dev ens33 scope link metric 1000

192.168.142.0/24 dev ens33 proto kernel scope link src 192.168.142.135 metric 100

  跳過default,后面兩條的第一個域都是目的地址,確切的說,這里指定的是目的網段,然后約束了設備,也就是ens33,這個路由條目是scope link的,也就是說當主機收到目標地址是169.254.0.0/16 這個網段的時候,通過ens33這個設備將包轉發出去。

  雖然理論上是如此,但是實際上,例如在linux中,這個dev ens33是沒有在路由中起到任何作用的,也就是說你改了ens33的名字,而不改路由表,那這個路由表項一樣命中,從改名后的網口發送出去。所以dev的這個限制相當於不存在,也就是只是一個命名的作用。但是並不確定在其他的實現中是否有限制的意義。

  Default路由本質上就是目標地址填了0.0.0.0的路由。Default路由有兩種添加方式,一種是約束網關地址,另外一種是約束源IP。因為要添加到網關地址的默認路由,是需要在添加的時候發一個arp請求到網絡上,看這個網關的地址是否存在於二層的,但是這個arp請求也是需要首先經過路由的。也就是一個雞生蛋,蛋生雞的問題。所以一個空的路由表是不能直接配置默認路由是一個網關的。但是明明網關確實是和當前的主機在同一個網段的。

  如果要配置默認網關,首先需要先讓這個網絡通。這個通的方法一個是配一個scope link的路由,也就是目的地址是該網段的發包,都可以匹配這個路由。因為是link scope的,所有的請求都會走二層的路由表,這就解決了arp不能到達網關的問題。Link scope的特點是所有的數據請求走二層arp,而不是走三層路由。所以在配置了這條路由之后,再配置網關就可以了。

  但是還有一個思路是使用源地址約束,我們要的只是這個查詢能命中一個可以出去的路由,當我們使用源地址約束,不指定目標地址,也就是源地址是自己設備的IP的地址的包全部走link scope,同樣也可以匹配,由於是link scope,也就可以觸發arp請求了。

  所以我們看到,整個過程的關鍵在於區分同二層和三層轉發。Link scope的作用是用在二層轉發,命中該路由條目的可以觸發arp查找,但是如果是網關式的,就是一個三層轉發,雖然也會觸發arp查找,但是目標MAC地址永遠是網關的地址,這樣下一跳就鎖死了。

  但是這里有一個問題是如果先添加了link scope的路由條目,然后又添加了gateway的路由,這個時候再把link scope的路由條目刪除,那么gateway的路由條目仍然存在並且生效,這個時候,所有的轉發都會匹配這個gateway的路由條目,包括本來應該走二層轉發的數據包。也就是說,原本應該在同一個二層傳輸走arp的數據包,在這種情況下,也會直接走網關,網關回復一個icmp redirect,但是網關仍然會把這個數據包轉發到同一個二層的目標地址。

  理論上,收到icmp redirect的主機應當更新自己的arp表,但是並不會更新路由表,而arp表是要先經過路由表查詢的,所以這個icmp redirect相當於沒有意義。Arp表里面即使是有了IP到MAC的映射關系,但是由於路由沒有命中link scope,所以永遠不會查詢ARP表。

  另外linux下的路由條目還會有一個proto的域,一般有proto kernel和proto dhcp兩種。Proto表明的是這個路由條目是由誰添加,例如給一個linux設備添加一個IP的時候會自動添加一條有這個源IP約束的Link scope的路由。前面說了,也正是有了這條路由才能夠使得配置網關的路由條目可以進行。這個內核自動添加的路由就是proto kernel了。

  需要理解的是,路由表和網絡設備是兩個實體,路由表在決策的時候,由路由表看到的網絡設備是獨立於路由表存在的。他們是並行的關系,先要查詢了路由表,找到滿足路由表的路由條目,才有可能按照條目約定的路由路徑去找到對應的設備。路由過程並不是發生在設備邏輯的內部,而是外部。所以實際上給設備添加了一個IP地址的時候,同時生成的路由條目實際上是兩個操作被在上層進行了組合。技術上,完全可以分別的添加IP地址和路由條目,上面也說了這個添加的路由條目可以被刪除,然后再次添加回去


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM