亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-11-23 15:52:44 來源:億速云 閱讀:186 作者:iii 欄目:系統運維

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

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基本原理是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

古丈县| 上林县| 乳源| 如东县| 云阳县| 平定县| 黑河市| 鸡西市| 石林| 兰州市| 南宫市| 前郭尔| 锡林郭勒盟| 嵊州市| 新疆| 图木舒克市| 伊吾县| 惠来县| 淮南市| 察隅县| 密山市| 曲松县| 安阳县| 古浪县| 龙井市| 常德市| 阜新| 土默特左旗| 彭州市| 毕节市| 黔江区| 日喀则市| 康乐县| 温宿县| 革吉县| 水城县| 东源县| 肇东市| 普兰店市| 拜城县| 庐江县|