三十天學不會TCP,UDP/IP網絡編程-TraceRoute的哲學

新年快樂,繼續來部分粘貼複製個人這一系列文章啦,若是對和程序員有關的計算機網絡知識,和對計算機網絡方面的編程有興趣,歡迎去gitbook(https://rogerzhu.gitbooks.io/-tcp-udp-ip/content/)star個人這一系列文章,雖說如今這種「看不見」的東西真正能在實用中遇到的機會很少,可是我始終以爲不管計算機的語言,熱點方向怎麼變化,做爲一個程序員,不少基本的知識都應該有所瞭解。而當時在網上搜索資料的時候,這方面的資料真的是少的可憐,因此,我有幸前兩年接觸了這方面的知識,我以爲我應該把我知道的記錄下來,雖然寫的不必定很好,可是但願能給須要幫助的人多個參考。個人計劃是用半年時間來寫完這一系列文章,這個標題也是我對太多速成文章的一種態度,好了,廢話再也不多扯了,下面是其中的一節內容,更多內容能夠去gitbook上找到。linux

 

TraceRoute 是另一個利用ICMP的程序,目的爲了找到一個端點到另外一個端點的路線,其設計理念我我的是以爲十分的巧妙。並且這個程序在windows和linux上還使用了稍微有點點不一樣的方法,可是卻能夠看到有殊途同歸之妙的地方。git

TraceRoute的起源

TraceRout這個網絡工具主要是由一個叫Van Jacobson的大牛完成的,這位大牛應該算是互聯網名人堂級人物,他最出名的應該是提出了TCP裏面的Jacobson算法用以解決擁塞問題,而這個算法在今天百分之九十的TCP終端上面都在運用。 1987年,他在另一位大牛Steve Deering的建議下寫了這樣一個探測網絡路徑的工具。一樣,在第二大部分,程序的時候,我會用raw socket寫一個玩具版的traceroute程序,來闡述其基本原理。程序員

TTL和ICMP在windows上的結合

在介紹IP頭格式的時候,裏面有一個字段叫TTL,Time to live,這個字段起初是規定一個IP數據包在網絡中的生存週期的,防止一個數據包無限制佔用網絡資源,畢竟要想一切有秩序,一個上限是不可避免要設置的,所謂的紅線就是這個道理。而隨着網絡基礎設施的升級和網絡規模的增加,鏈接每一個網絡的路由器處理一個數據包的時間基本都遠遠小於1秒鐘,而數據包在路由器之間的網線的上的傳輸時間更是能夠忽略不計,因此這個字段就演化成了通過多少個路由器的計數器。每通過一個路由器,TTL的值就會減1,當這個值爲0的時候,也就是這個IP數據包消亡的時候。算法

好比舉個例子,若是某個IP包中TTL設置爲1,那麼這個數據包就只能在這個一個子網內傳輸,由於一旦通過了一個路由器,TTL就會變成0,該數據包就會消失了。而當這個數據包消失的時候,一個ICMP消息就會被產生,在上個部分裏表裏,ICMP頭裏的Type值爲11的時候表示超時,而這個就是當TTL爲0的時候被回覆的ICMP消息。Windows 的TraceRoute程序就是利用了這個原理,先仍是來看一下windows上運行traceroute是啥樣的,不過windows的traceroute程序真名叫tracert,其運行結果以下:編程

 

 

我尋找的是從我這裏到局域網的某一個路由器的地址,能夠看到,從個人主機到這個路由器要通過三個路由器,因此有三行輸出,而每行有三個往返時間,這是由於traceroute會發三次ICMP的echo消息,而這個輸出值得咱們逐行分析一下。windows

第一行是到個人局域網路由器(熱點),往返時間是6-8ms之間,這個時候TTL被設置成1,從下面抓到的數據包中能夠看到其具體的數據:安全

從截圖中能夠看出,第一個數據包TTL是1,雖然dest IP是100.97.2.9,但實際上在192.168.8.1這個路由器中這個數據包就已經消失了,由於這個時候該IP數據包中的TTL的值已經減爲0,192.168.8.1隨即回覆一個ICMP消息報告超時。上一節中介紹了ICMP echo的格式,很是簡單,而ICMP超時的數據包的格式比Echo稍微多一點點信息,可是依然是並不複雜,其格式以下:網絡

 

 

 

其中前4個字節和echo是同樣的,只不過這裏type變成了11(十進制)標識超時錯誤消息,code爲0表示ttl爲0發生了超時。接下來4個字節做爲保留字節根本沒有用處,目的是和全部ICMP報文格式統一併兼容。而接着後面的數據部分就和echo不一樣了,而這些被選擇中的數據也是這個數據頭格式的精妙之所在。ICMP的超時消息會把發送方的IP數據頭和IP數據包中頭64個bit做爲數據部分傳回給發送方。其做用是可讓發送方的更上層的進程在若有須要的時候篩選出本身須要的信息和數據包。好比說,有了這個部分,裏面就有了IP頭中的TTL信息,發送端就知道是第幾個TTL到期,數據包消失的。而接着的64個bit的數據在特定狀況下更是有妙用,特別是在後面要介紹的端口不可達的ICMP消息之中。socket

第二行就是TTL爲2的回覆,而這一行全是星號,這是由於有的網關/路由器不會返回ICMP超時報文,甚至爲了安全考慮,不少帶有防火牆的路由器不返回各類ICMP報文,因此你會看到上面輸出的星號,而這種暫時的不返回並不妨礙繼續向更深的一層探測,因此在三次沒有返回後,traceroute會將TTL遞增1,繼續發送ICMP的echo報文。tcp

第三行就是TTL爲3的結果,而這個時候數據包已經到達目標網絡,因爲探測的時候發的是ICMP echo request的消息,因此這個時候發送端能夠獲得ICMP echo reply消息,具體請參見上一節(你到底在ping什麼)。因此發送端就能知道他的數據包已經到達了目的地,也就不會再繼續增長TTL,探測活動中止,這個從抓獲的數據包中也能獲得體現。

 

TTL和ICMP在linux上的結合

前面說過traceroute這個程序在linux上和windows上採用一個有一點點不同的設計,可是都是利用了ICMP消息和TTL。

Linux上traceroute程序就是使用traceroute這個命令,看起來像句廢話,而linux上追蹤數據包路徑的方法是採用的UDP,而不是ICMP的echo消息。這樣的一個不一樣點就是,使用UDP的時候,若是對方的端口是沒有的,那麼ICMP就會返回端口不可達消息,type是3。而在linux上會在這個UDP消息中使用一個30000以上端口號,這樣當時數據包到達目的主機的時候,因爲對方主機並無打開這個UDP端口,因此ICMP會返回一個端口不可達的消息,這樣發送端收到端口不可達的時候就知道不須要繼續探測le。其格式和超時的格式是如出一轍的,不一樣點只是type的數值是3,code的數值3標識端口不可達。

其他中間的探測過程和windows同樣,都是使用ICMP的超時消息。

這裏我想要稍微更多的介紹一下端口不可達的ICMP消息之中的data部分了,這個部分包含IP數據頭和IP數據包的前8個字節,那麼若是發送端發送的是UDP消息的話,回一下前面介紹的UDP頭的格式,前8個字節正好UDP的頭部,其中含有發送端的Port的到達端的Port,而UDP是IP的data部分,因此說發送端就能夠從這個ICMP的錯誤消息中獲得更多的信息。從下面這個抓包中能夠看出這樣一個data的返回(忽略port號,哈哈):

 

 

傳統的traceroute利用ICMP消息有不少弊端,其中之一就是前面說的有不少網關或者路由器因爲安全的設置不會返回任何ICMP錯誤消息,因此如今也有不少探測方法是利用TCP,有興趣能夠去搜索一下。

相關文章
相關標籤/搜索