Traceroute in 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協議的欄位。

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的數據包之後,還會向數據包的源地址發送一個ICMPTime exceeded message(ICMP type 11,在這條信息中,路由設備會將自己的IP地址作為源地址。

總的來說traceroute就是基於TTL和路由設備的特性來實現的。

Traceroute原理

基本實現原理

根據前面的描述,只要發送一個IP數據包,將TTL設為1,就能收到第一個路由設備返回的ICMP TTL exceededmessage。將TTL設為2,就能收到第二個路由設備的。以此類推,當TTL大到一定數的時候……,IP數據包就被目的設備收到,並且目的設備會做出響應。所以traceroute的原理,簡單來說,如下圖所示:

探測包(UDP)

Traceroute會發送什麼樣的IP數據包?默認是UDP數據包。除了前面說過的TTL,這個UDP數據包會包含:

  • 源地址

  • 目的地址

  • 一個UDP埠,埠號在33434和33534之間,這個區間的埠號對UDP來說是無效的埠號。因此目的地址收到了這個UDP數據包,會返回ICMP UDP Port Unreachable(ICMP type 3)的信息。這麼一個別緻的返回信息,traceroute在收到了它之後,就知道網路路徑探測該結束了。

實際的數據流

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

tcpdump抓包:

paste.ubuntu.com/238034

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

  • 每個TTL都發了三個探測包出來,這是為了對同一個hop獲得三次的延時數據,使得結果更加客觀。

  • 每次發出的探測包,UDP埠都不一樣。這是為了將返回的信息跟發出的信息進行匹配。以計算IP數據包從發出到接收的延時(Latency)。在上面的示例中,這似乎沒有必要,因為探測包都是一發一收,串列執行。那是因為我用的是簡版的traceroute,在高版本的traceroute中,默認是並行發送16個探測包。來感受一下並行發送的凌亂感吧。

paste.ubuntu.com/237912

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

與UDPtraceroute的區別就在於:

  • 探測包就是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),會發生什麼結果?為了把問題描述清楚,我搭了一個如下的網路拓撲:

我們來看看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 exceededmessage返回給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位元組拷貝到了ICMPpayload。所以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記錄在:

paste.ubuntu.com/238038

可以看到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請求,返回ICMPPort Unreachable。

  • 如果router支持NAT功能,還需要對ICMPerror message做內層數據包NAT。

TTL減1

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

丟棄invalid TTL packet,並返回ICMP timeexceeded message

從OpenFlow 1.2起,支持將TTL invalid packet上送至OpenFlow控制器,在控制器內,可以生成ICMPtime 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


推薦閱讀:

NFV 閑聊(基礎技術篇)
SDN興起對於我們這些已經多年的CCIE,不知道未來該何去何從?
SDN興起對於我們這些已經多年的CCIE,不知道未來該何去何從11?
VXLAN在數據中心大量VM互聯場景下,能否免去flood-learn學習?

TAG:SDN | 计算机网络 |