天天看點

Traceroute in OpenFlow based SDN OpenFlow based SDN

Traceroute是一個非常便利的網絡診斷工具。它可以輸出以下三個内容:

1 網絡資料包的從源位址到目的位址的整個傳輸路徑。

2 傳輸路徑上的路由裝置的資訊(IP位址或者hostname)

3 網絡資料包在路由裝置間的延時(Latency)

從這些功能可以看出,traceroute通常可以用于判斷網絡故障,檢測網絡傳輸路徑等場合。Traceroute現在基本随linux系統發行,是以使用起來非常友善。在Windows系統下,對應的工具是TRACERT.

Traceroute的一個優點是,它不需要你發送實際的資料到目的位址,就能幫你輸出整個網絡路徑(實際上還是要發送資料,隻是發送的不是你的實際資料)。

在基于OpenFlow的SDN中,要實作traceroute功能,實際上就是要在SDN中實作traceroute所依賴的網絡功能。那麼接下來看看traceroute所依賴的網絡功能有哪些?

TTL(hop limit)

在IP協定(Internet Protocol)中,TTL(Time To Live)是一個8bit的字段,IPv4協定中,協定頭有20個8bit的字段,TTL占第9個8bit;IPv6協定中,協定頭有40個8bit的字段,TTL占第8個8bit。是以,TTL在IP協定中,最大值是255,通常的預設值是64。下圖是IPv4協定的字段。

Traceroute in OpenFlow based SDN OpenFlow based SDN

TTL存在的意義是什麼?我們假設我們的網絡系統中,每個路由裝置都有預設路由,我們發出一個以不存在的位址作為目的位址的IP資料包,那麼這個資料包将永遠在我們的網絡系統中轉發。把網絡系統看成Internet,那麼随着時間推移,Internet必然會被大量這樣的“永生”IP資料包淹沒。正是為了避免這個問題,IP協定中提出了TTL,當TTL為0,IP資料包會被丢棄。

TTL被設計為IP資料包在Internet中最長的存活時間。但是實際上,每個轉發了IP資料包的裝置,都需要将TTL減1,也就是說TTL等于IP資料包能經曆的最大跳(hop)數,而不是時間(秒數)。是以,為了避免誤解,在IPv6中,将TTL改名為hop limit。為了省事,我們還是叫它TTL吧。

回過來看前面的描述,有兩個問題:

什麼是hop?

Hop是指IP資料包傳輸過程中的一段路徑。當IP資料包從一個網絡裝置傳輸至另一個網絡裝置,這可以認為是一個hop(跳)。

IP資料包被誰丢棄了?

被路由裝置丢棄了,根據RFC1812,路由裝置在轉發IP資料包的時候,會将TTL減1,如果減完之後的結果是0,那麼IP資料包會被丢棄。是以說,在IP網絡中,路由裝置需要丢棄TTL為1的資料包。

路由裝置在丢棄TTL為1的資料包之後,還會向資料包的源位址發送一個ICMP Time exceeded message(ICMP type 11),在這條資訊中,路由裝置會将自己的IP位址作為源位址。

總的來說traceroute就是基于TTL和路由裝置的特性來實作的。 

Traceroute原理

基本實作原理

根據前面的描述,隻要發送一個IP資料包,将TTL設為1,就能收到第一個路由裝置傳回的ICMP TTL exceeded message。将TTL設為2,就能收到第二個路由裝置的。以此類推,當TTL大到一定數的時候……,IP資料包就被目的裝置收到,并且目的裝置會做出響應。是以traceroute的原理,簡單來說,如下圖所示:

Traceroute in OpenFlow based SDN OpenFlow based SDN

探測包(UDP)

Traceroute會發送什麼樣的IP資料包?預設是UDP資料包。除了前面說過的TTL,這個UDP資料包會包含:

  • 源位址
  • 目的位址
  • 一個UDP端口,端口号在33434和33534之間,這個區間的端口号對UDP來說是無效的端口号。是以目的位址收到了這個UDP資料包,會傳回ICMP UDP Port Unreachable(ICMP type 3)的資訊。這麼一個别緻的傳回資訊,traceroute在收到了它之後,就知道網絡路徑探測該結束了。 

實際的資料流

描述的差不多了,我們來看一個簡單拓撲下traceroute背後的資料流吧。網絡拓撲:

Traceroute in OpenFlow based SDN OpenFlow based SDN

tcpdump抓包:

http://paste.ubuntu.com/23803412/

除了前面已經描述過的,有三點需要注意。

  • 每個TTL都發了三個探測包出來,這是為了對同一個hop獲得三次的延時資料,使得結果更加客觀。
  • 每次發出的探測包,UDP端口都不一樣。這是為了将傳回的資訊跟發出的資訊進行比對。以計算IP資料包從發出到接收的延時(Latency)。在上面的示例中,這似乎沒有必要,因為探測包都是一發一收,串行執行。那是因為我用的是簡版的traceroute,在高版本的traceroute中,預設是并行發送16個探測包。來感受一下并行發送的淩亂感吧。

https://paste.ubuntu.com/23791252/

Traceroute收到了ICMP資訊,都包含有内層資訊,内層資訊似乎有探測包的大部分資訊。

探測包:
IP (tos 0x0, ttl 1, id 2143, offset 0, flags [DF], proto UDP (17), length 46)
10.0.0.10.33875 > 10.0.1.10.33435: UDP, length 18

回複包:
IP (tos 0xc0, ttl 64, id 15477, offset 0, flags [none], proto ICMP (1), length 74)
10.0.0.1 > 10.0.0.10: ICMP time exceeded in-transit, length 54
    IP (tos 0x0, ttl 1, id 2143, offset 0, flags [DF], proto UDP (17), length 46)
    10.0.0.10.33875 > 10.0.1.10.33435: UDP, length 18
           

根據RFC777,ICMP協定要求将産生ICMP error的原資料包的至少前28位元組拷貝至ICMP error message的payload,是以我們能看到探測包的内容。28個位元組包括了20個位元組的IP報頭,和8個位元組的UDP報頭。

三種traceroute的實作方式

之前介紹的都是基于UDP協定的traceroute實作,而實際中traceroute還可以基于ICMP和TCP協定。首先要說的是,這三種方式的基本實作原理是一樣的,都是基于TTL和路由裝置傳回的資訊。差別是探測包不一樣。為什麼會有三種實作方式?因為你的防火牆可能阻止了UDP,為了讓traceroute在這樣的環境下也能工作,才有了别的實作。

ICMP traceroute

與UDP traceroute的差別就在于:

  • 探測包就是ICMP echo request
  • 目的裝置傳回的就是ICMP echo reply

linux下的traceroute可以通過指定參數來用ICMP做traceroute,而windows下的tracert預設就是用ICMP來做traceroute。

TCP traceroute

與UDP traceroute的差別在于:

  • 探測方式是與tcp 80(預設)端口建立連接配接
  • 目的裝置的傳回時連接配接成功,或者80端口關閉

即使目的裝置傳回連接配接成功,traceroute程式會立即斷開連接配接,因為沒有必要。

Traceroute with NAT

問題

這是個比較有意思的方向。前面說過,路由裝置傳回的ICMP time exceeded message會将探測包的前28個位元組拷貝至ICMP的payload。那如果路由裝置做了NAT(network address translation),會發生什麼結果?為了把問題描述清楚,我搭了一個如下的網絡拓撲:

Traceroute in OpenFlow based SDN OpenFlow based SDN

我們來看看TTL=2的探測包是怎麼發送的:

第一個路由器上觀察到的資料:

IP (tos 0x0, ttl 2, id 6596, offset 0, flags [DF], proto UDP (17), length 46)
20.0.0.12.51016 > 192.168.31.94.33438: UDP, length 18
           

第二個路由器上觀察到的資料:

IP (tos 0x0, ttl 1, id 6596, offset 0, flags [DF], proto UDP (17), length 46)
172.24.4.3.51016 > 192.168.31.94.33438: UDP, length 18
           

可以看到,同一個探測包(端口号,ID一緻),在第一個路由器,TTL=2,第二個路由器TTL=1,這跟前面的描述一緻。并且在第二個路由器上,探測包變成了由172.24.4.3發送了。這是因為第一個路由器對探測包做了源位址NAT。

那第二個路由器如何知道将ICMP time exceeded message傳回給20.0.0.12?

外層NAT

我們來看看第二個路由器(上面那個)傳回的ICMP time exceeded message。

IP (tos 0xc0, ttl 64, id 55039, offset 0, flags [none], proto ICMP (1), length 74)
172.24.4.1 > 172.24.4.3: ICMP time exceeded in-transit, length 54
    IP (tos 0x0, ttl 1, id 6596, offset 0, flags[DF], proto UDP (17), length 46)
    172.24.4.3.51016 > 192.168.31.94.33438: UDP, length 18
           

第二個路由器不關心資料包從哪來,隻是将目前它收到的資料包的前28位元組拷貝到了ICMP payload。是以ICMP内層資料是從172.24.4.3到192.168.31.94。

第一個路由器(下面那個),自然會對資料包做反向NAT,即将外層的目的位址轉換成20.0.0.12。是以,第一個路由器做完外層NAT之後,資料包應該是這樣的:

IP (tos 0xc0, ttl 63, id 55039, offset 0, flags [none], proto ICMP (1), length 74)
172.24.4.1 > 20.0.0.12: ICMP time exceeded in-transit, length 54
    IP (tos 0x0, ttl 1, id 6596, offset 0, flags[DF], proto UDP (17), length 46)
    172.24.4.3.51016 > 192.168.31.94.33438: UDP,length 18
           

内層NAT

但是實際上,第一個路由器收到的ICMP time exceeded message是這樣的:

IP (tos 0xc0, ttl 63, id 55039, offset 0, flags [none], proto ICMP (1), length 74)
172.24.4.1 > 20.0.0.12: ICMP time exceeded in-transit, length 54
    IP (tos 0x0, ttl 1, id 6596, offset 0, flags[DF], proto UDP (17), length 46)
    20.0.0.12.51016 > 192.168.31.94.33438: UDP,length 18
           

内層的位址也被反向NAT了。也就是說對于ICMP time exceeded message,支援NAT的路由器需要同時對外層包和内層包做反向NAT。這樣,對于源裝置20.0.0.12,它感覺不到外面發生了什麼,但是同時又能擷取各個路由裝置的資訊。

RFC5508對此作了明确的定義:

NAT Behavioral Requirements for ICMP

完整的tcpdump記錄在:

http://paste.ubuntu.com/23803870/

可以看到ICMP包在經過NAT裝置後,内層資料也做了NAT轉換。如果不對内層資料做NAT,ICMP包将會是個無效的資料包。

OpenFlow based SDN

前面說的所有的都是基于IP協定棧,而OpenFlow沒有這個東西。那就意味着,如果要對基于OpenFlow的router實作traceroute,需要手動實作前面說到的功能。這包括:

  • 路由轉發時對IP資料包的TTL減1
  • 路由轉發時,對TTL=1的資料包丢棄
  • 丢棄了TTL=1的資料包時,傳回ICMP time exceeded message。
  • 由于SDN中的虛拟路由器端口可能是虛拟的,是以要求SDN中的虛拟路由器響應UDP和TCP請求,傳回ICMP Port Unreachable。
  • 如果router支援NAT功能,還需要對ICMP error message做内層資料包NAT。

TTL減1

這個在OpenFlow中已經支援這樣的action,可以在路由的時候對TTL進行減1。

丢棄invalid TTL packet,并傳回ICMP time exceeded message

從OpenFlow 1.2起,支援将TTL invalid packet上送至OpenFlow控制器,在控制器内,可以生成ICMP time exceeded message,并傳回給送入端口。

虛拟路由器響應UDP和TCP請求,傳回ICMP Port Unreachable

比對虛拟路由器的端口上的UDP和TCP請求,上送OpenFlow控制器,在控制器内,可以生成ICMP Port Unreachable message,并傳回給送入端口。

對ICMP error message做内層資料包NAT

比對NAT請求中的ICMP error message,上送OpenFlow控制器,在控制器内對内層資料包做NAT,再送到相應的輸出端口。

上面有關實作的描述比較簡單,具體的實作可以參考到我在Dragonflow項目的代碼。

Support traceroute in dragonflow network

本文轉載自:https://zhuanlan.zhihu.com/p/24982540