久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Linux Tcp內核協議棧Packet Drill基本原理是什么

160次閱讀
沒有評論

共計 5081 個字符,預計需要花費 13 分鐘才能閱讀完成。

本篇內容介紹了“Linux Tcp 內核協議棧 Packet Drill 基本原理是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

Linux TCP 內核協議棧是一個非常復雜的實現,  不但沉淀了過去 20 多年的設計與實現,同時還在不停的更新。相關的 RFC 與優化工作一直還在進行中。如何研究和學習 Linux  TCP 內核協議棧這樣一塊硬骨頭就成了一大難題。

當然最重要也是最基本的還是要閱讀相關的 RFC 和內核中的代碼實現。這個是最最基本的要求。想要馴服 TCP 內核協議棧這樣的 monster   僅僅瀏覽和靜態分析代碼是完全不夠的。因為整個實現中充斥著各種邊界條件和異常的處理(這里有部分原因是因為 TCP 協議本身設計造成的),尤其是 TCP 是有狀態的協議,  很多邊界條件的觸發需要一系列的報文來構成,同時還需要滿足時延等其它條件。

幸運的是 Google 在 2013 年替大家解決了這個難題。Google 在 2013 年發布了 TCP 內核協議棧 測試工具 Packet  Drill。這個工具是名副其實,大大的簡化了學習和測試 TCP 內核協議棧的難度。基本可以隨心所欲的觸摸 TCP   內核協議棧的每個細節。Google 的這件工具真是造福了人類。

使用 Packet Drill,用戶可以隨心所欲的構造報文序列,可以指定所有的報文格式 (類似 tcpdump 語法) 然后通過 TUN 接口和目標系統的 TCP   內核協議棧來通信,并對接收到的來自目標系統 TCP 內核協議棧 的報文進行校驗,來確定是否通過測試。再進一步結合 wireshark+Packet Drill   用戶可以獲得最直觀而且具體的體驗。每個報文的每個細節都在掌控之中,溜得飛起,人生瞬間到達了巔峰。

Packet Drill 基本原理

TUN 網絡設備

TUN 是 Linux 下的虛擬網絡設備,可以直通到網絡層。使得應用程序可以直接收發 IP 報文。

Linux Tcp 內核協議棧 Packet Drill 基本原理是什么

Packet Drill 腳本解析 / 執行引擎

首先 Packet Drill 腳本必須要被解析和分解為 通過傳統 socket 接口收發報文的部分和通過 TUN 接口收發報文的部分

在傳統 socket 接口執行對應的動作。

在 TUN 接口執行對應的動作,并對收到的數據進行比對。

在本文中 socket 接口主要扮演的是 server  side 的角色。TUN 接口扮演的是 client 的角色。因而我們可以通過 TUN 接口完全掌控我們將要發送出去的 IP 報文,并受到 TCP 協議棧的反饋。并和預設數據進行比對。

Packet Drill 語法簡介

相對時間順序

Packet Drill 每一個事件 (發送 / 接收 / 發起系統調用) 都有相對前后事件的時間便宜。一般使用 +number 來表達。例如 +0   就是在之前的事件結束之后立即發起。+.1 表示為在之前時間結束 0.1 秒之后發起。以此類推

系統調用

Packet Drill 中集成了系統調用,可以通過腳本來完成例如 socket,bind,read,write,getsocketoption   等等系統調用。熟悉 socket 編程的同學很容易理解并使用。

報文的發送與接受

通過內核棧側。可以通過調用系統調用 read/write   來完成報文的發送與接受。但是因為 tcp 是有狀態的協議棧,所以內核棧本身也會根據協議棧所處狀態發送報文(例如 ACK/SACK).

TUN 設備側. Packet Drill 使用 表示發送報文,使用 表示接收報文。

報文的格式描述

報文格式的表達比較類似 tcpdump。例如 S 0:0(0) win 1000 表示 syn 包 win 大小為 1000,同時 tcp 的選項 mss (max  segment size)為 1000. 

下面我們通過 2 個例子來進一步學習

Handshake and Teardown

我們通過 packet drill 的腳本 復習一下這個經典的流程。

首選來回顧一下 TCP 協議標準的 handshake 和 treardown 流程

Linux Tcp 內核協議棧 Packet Drill 基本原理是什么

接下來我們結合 packet drill 的腳本來重現 整個過程

// 創建 server 側 socket, server 側 socket  將通過內核協議棧來通信  //  注意這里使用的是傳統的系統調用  0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 // 設置對應的 socket options //  注意這里使用的是傳統的系統調用  +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 //bind socket //  注意這里使用的是傳統的系統調用  +0 bind(3, ..., ...) = 0 //listen on the socket //  注意這里使用的是傳統的系統調用  +0 listen(3, 1) = 0 // client 側(TUN)發送  syn  握手的第一個報文  //  注意這里的語法  syn seq 都是相對的,從 0 開始。 +0   S 0:0(0) win 1000  mss 1000  // client 側(TUN)期望收到的報文格式  syn+ack  且  ack.no=ISN(c)+1 //  參考標準流程圖   最后的 ...   表示任何 tcp option 都可以  //  這里是握手的第二步  +0   S. 0:0(0) ack 1  ...  // client 側(TUN)發送  ack  報文  seq = ISN(c)+1, ack = ISN(c) +1 //  這里是握手的第三步  +.1   . 1:1(0) ack 1 win 1000 // 握手成功,server 側  socket  返回  established socket // 這時通過 accept  系統調用拿到這個 stream  的 socket +0 accept(3, ..., ...) = 4 //server 側向 stream  寫入  10 bytes // 通過系統調用來完成寫操作  +0 write(4, ..., 10)=10 //client 側期望收到 receive 10 bytes +0   P. 1:11(10) ack 1 //client 側應答  ack  表示接收到  10 bytes +.0   . 1:1(0) ack 11 win 1000 // client  關閉連接   發送 fin 包  +0   F. 1:1(0) ack 11 win 4000 // client 側期望接收到 server 端的對于 fin 的 ack 報文  //  這里由內核協議棧發回。ack = server seq +1, seq = server ack //  參考標準流程圖  +.005   . 11:11(0) ack 2 // server  關閉連接   通過系統調用完成  +0 close(4) = 0 // client 期望接收到的 fin 包格式  +0   F. 11:11(0) ack 2 // client  發送 server 端 fin 包的應答 ack 包  +0   . 2:2(0) ack 12 win 4000

至此,我們純手動的完成了全部的發起和關閉連接的過程。然后我們用 wireshark 來驗證一下

Linux Tcp 內核協議棧 Packet Drill 基本原理是什么

通過結合 packetdrill 與 wireshark 使得每一步都在我們的掌控之中,

SACK

我們將使用 packet drill 來探索一些更為復雜的案例。例如內核協議棧對于 SACK 中各種排列組合的響應。

SACK 是 TCP 協議中優化重傳機制的一個重要選項(該選項一般都在報頭的 options 部分)。

最原始的情況下如果發送方對于 每一個報文接受到 ACK 之后再發送下一個報文,效率將是極為低下的。引入滑動窗口之后允許發送方一次發送多個報文   但是如果中間某個報文丟失 (沒有收到其對應的 ACK) 那么從那個報文開始,其后所有發送過的報文都要被重新發送一次。造成了極大的浪費。

SACK 是一種優化措施,用來避免不必要的重發,告知發送方那些報文已經收到,不用再重發。tcp   的選項中允許帶有最多 3 個 SACK 的 options。也就是三個已經收到了得報文區間信息。說了這么多,還是有一些抽象,我們來看一個具體的示例。

示例說明

在下面的這個例子中,我們需要發送報文的順序是 1,3,5,6,8,4,7,2   也就是測試一下內核 tcp 協議棧的 SACK 邏輯是否如同 RFC 中所描述的一樣。

//  初始化部分建立服務器端 socket,  不再贅述  +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0 bind(3, ..., ...) = 0 +0 listen(3, 1) = 0 // Client  端發送   握手報文以及接受服務器響應,不再贅述。這里注意激活了 SACK +.1   S 0:0(0) win 50000  mss 1000, sackOK,nop,nop,nop,wscale 7  +0   S. 0:0(0) ack 1 win 32000  mss 1000,nop,nop,sackOK  +0   . 1:1(0) ack 1 win 50000 // Server  端就緒  +.1 accept(3, ..., ...) = 4 // 發送報文 1  +0   . 1:1001(1000) ack 1 win 50000 // 發送報文 3,  報文 2   被調整到最后發送  +0   . 2001:3001(1000) ack 1 win 50000 // 發送報文 5   報文 4   被調整亂序  +0   . 4001:5001(1000) ack 1 win 50000 // 發送報文 6  +0   . 5001:6001(1000) ack 1 win 50000 // 發送報文 8   報文 7   被調整亂序  +0   P. 7001:8001(1000) ack 1 win 50000 // 發送報文 4  +0   . 3001:4001(1000) ack 1 win 50000 // 發送報文 7  +0   . 6001:7001(1000) ack 1 win 50000 //  接收到第一個報文的 ACK +0   . 1:1(0) ack 1001 //  接收到 SACK,  報告收到了亂序的報文 3,但是沒報文 2。 +0   . 1:1(0) ack 1001 win 31000  nop,nop,sack 2001:3001  //  接收到 SACK,  報告收到了亂序的報文 3,報文 5,但是沒報文 2。沒報文 4  +0   . 1:1(0) ack 1001 win 31000  nop,nop,sack 4001:5001 2001:3001  //  接收到 SACK,  報告收到了亂序的報文 3,報文 5,但是沒報文 2。沒報文 4  +0   . 1:1(0) ack 1001 win 31000  nop,nop,sack 4001:6001 2001:3001  //  接收到 SACK,  報告收到了亂序的報文 3,報文 5,6,  報文 8,但是沒報文 2。沒報文 4,沒報文 7  +0   . 1:1(0) ack 1001 win 31000  nop,nop,sack 7001:8001 4001:6001 2001:3001  //  接收到 SACK,  報告收到了亂序的報文 3,4,5,6,  報文 8,但是沒報文 2。沒報文 7  +0   . 1:1(0) ack 1001 win 31000  nop,nop,sack 2001:6001 7001:8001  //  接收到 SACK,  報告收到了亂序的報文 3,4,5,6,7,8,但是沒報文 2  +0   . 1:1(0) ack 1001 win 31000  nop,nop,sack 2001:8001  // 發送報文 2   至此所有報文完結  +0   . 1001:2001(1000) ack 1 win 50000 +0   . 1:1(0) ack 8001`

隨后我們再來用 wireshark 驗證一下。

Linux Tcp 內核協議棧 Packet Drill 基本原理是什么

果然完全匹配。

Packet Drill 其實還有非常復雜而且更精巧的玩法,可以充分測試各種邊界條件。以后有機會再和大家進一步分享

“Linux Tcp 內核協議棧 Packet Drill 基本原理是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注丸趣 TV 網站,丸趣 TV 小編將為大家輸出更多高質量的實用文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-25發表,共計5081字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 昌吉市| 东乌珠穆沁旗| 广水市| 梁平县| 鹤壁市| 五寨县| 望都县| 乌鲁木齐县| 武义县| 唐山市| 永昌县| 自贡市| 吴江市| 喀喇沁旗| 麟游县| 阜南县| 同心县| 瑞昌市| 西充县| 桦川县| 武陟县| 桂阳县| 民勤县| 化隆| 泰州市| 韶关市| 成武县| 大田县| 枣庄市| 连平县| 济南市| 中方县| 武义县| 司法| 杨浦区| 乌兰县| 南雄市| 台东市| 洛川县| 新蔡县| 铜陵市|