自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux Tcp 內(nèi)核協(xié)議棧學(xué)習(xí)三種武器 之 Packet Drill

系統(tǒng) Linux
Linux TCP 內(nèi)核協(xié)議棧是一個(gè)非常復(fù)雜的實(shí)現(xiàn), 不但沉淀了過去20多年的設(shè)計(jì)與實(shí)現(xiàn),同時(shí)還在不停的更新。相關(guān)的RFC與優(yōu)化工作一直還在進(jìn)行中。如何研究和學(xué)習(xí)Linux TCP內(nèi)核協(xié)議棧這樣一塊硬骨頭就成了一大難題。

[[351019]]

Linux TCP 內(nèi)核協(xié)議棧是一個(gè)非常復(fù)雜的實(shí)現(xiàn), 不但沉淀了過去20多年的設(shè)計(jì)與實(shí)現(xiàn),同時(shí)還在不停的更新。相關(guān)的RFC與優(yōu)化工作一直還在進(jìn)行中。如何研究和學(xué)習(xí)Linux TCP內(nèi)核協(xié)議棧這樣一塊硬骨頭就成了一大難題。

當(dāng)然最重要也是最基本的還是要閱讀相關(guān)的RFC和內(nèi)核中的代碼實(shí)現(xiàn)。這個(gè)是最最基本的要求。想要馴服TCP 內(nèi)核協(xié)議棧這樣的monster 僅僅瀏覽和靜態(tài)分析代碼是完全不夠的。因?yàn)檎麄€(gè)實(shí)現(xiàn)中充斥著各種邊界條件和異常的處理(這里有部分原因是因?yàn)門CP協(xié)議本身設(shè)計(jì)造成的),尤其是TCP是有狀態(tài)的協(xié)議, 很多邊界條件的觸發(fā)需要一系列的報(bào)文來構(gòu)成,同時(shí)還需要滿足時(shí)延等其它條件。

幸運(yùn)的是Google在2013年替大家解決了這個(gè)難題。Google 在2013 年發(fā)布了TCP 內(nèi)核協(xié)議棧 測(cè)試工具 Packet Drill。這個(gè)工具是名副其實(shí),大大的簡化了學(xué)習(xí)和測(cè)試TCP 內(nèi)核協(xié)議棧的難度。基本可以隨心所欲的觸摸TCP 內(nèi)核協(xié)議棧的每個(gè)細(xì)節(jié)。Google的這件工具真是造福了人類。PacketDrill GitHub link:

https://github.com/google/packetdrill/

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

Packet Drill 基本原理

TUN 網(wǎng)絡(luò)設(shè)備

TUN 是Linux 下的虛擬網(wǎng)絡(luò)設(shè)備, 可以直通到網(wǎng)絡(luò)層。使得應(yīng)用程序可以直接收發(fā)IP報(bào)文。

 

Packet Drill 腳本解析/執(zhí)行引擎

  • 首先 Packet Drill 腳本必須要被解析和分解為 通過傳統(tǒng)socket 接口收發(fā)報(bào)文的部分和通過TUN接口收發(fā)報(bào)文的部分
  • 在傳統(tǒng)socket 接口執(zhí)行對(duì)應(yīng)的動(dòng)作。
  • 在TUN接口執(zhí)行對(duì)應(yīng)的動(dòng)作,并對(duì)收到的數(shù)據(jù)進(jìn)行比對(duì)。
  • 在本文中 socket 接口主要扮演的是 server side的角色。TUN接口扮演的是client的角色。因而我們可以通過TUN接口完全掌控我們將要發(fā)送出去的IP報(bào)文,并受到TCP協(xié)議棧的反饋。并和預(yù)設(shè)數(shù)據(jù)進(jìn)行比對(duì)。

Packet Drill 語法簡介

相對(duì)時(shí)間順序

Packet Drill 每一個(gè)事件(發(fā)送/接收/發(fā)起系統(tǒng)調(diào)用)都有相對(duì)前后事件的時(shí)間便宜。一般使用+number 來表達(dá)。例如+0 就是在之前的事件結(jié)束之后立即發(fā)起。+.1 表示為在之前時(shí)間結(jié)束0.1秒之后發(fā)起。以此類推

系統(tǒng)調(diào)用

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

報(bào)文的發(fā)送與接受

  • 通過內(nèi)核棧側(cè)??梢酝ㄟ^調(diào)用系統(tǒng)調(diào)用 read/write 來完成報(bào)文的發(fā)送與接受。但是因?yàn)閠cp是有狀態(tài)的協(xié)議棧,所以內(nèi)核棧本身也會(huì)根據(jù)協(xié)議棧所處狀態(tài)發(fā)送報(bào)文(例如ACK/SACK).
  • TUN 設(shè)備側(cè). Packet Drill 使用 < 表示發(fā)送報(bào)文, 使用 > 表示接收?qǐng)?bào)文。

報(bào)文的格式描述

報(bào)文格式的表達(dá)比較類似tcpdump。例如 S 0:0(0) win 1000表示syn包 win大小為1000, 同時(shí)tcp的選項(xiàng) mss (max segment size)為1000. 如果不熟悉報(bào)文格式, 可以先復(fù)習(xí)一下《TCP/IP協(xié)議詳解》 卷1.

進(jìn)一步的信息請(qǐng)參考 Drilling Network Stacks with packetdrill:

https://storage.googleapis.com/pub-tools-public-publication-data/pdf/41848.pdf

實(shí)戰(zhàn)示例

下面我們通過2個(gè)例子來進(jìn)一步學(xué)習(xí)

Handshake and Teardown

我們通過packet drill的腳本 復(fù)習(xí)一下這個(gè)經(jīng)典的流程。

首選來回顧一下 TCP協(xié)議標(biāo)準(zhǔn)的 handshake 和 treardown 流程

 

接下來我們結(jié)合packet drill 的腳本來重現(xiàn) 整個(gè)過程

  1. //創(chuàng)建server側(cè)socket, server側(cè)socket 將通過內(nèi)核協(xié)議棧來通信 
  2.  
  3. // 注意這里使用的是傳統(tǒng)的系統(tǒng)調(diào)用 
  4.  
  5. 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 
  6.  
  7.  
  8.  
  9.  
  10. //設(shè)置對(duì)應(yīng)的socket options 
  11.  
  12. // 注意這里使用的是傳統(tǒng)的系統(tǒng)調(diào)用 
  13.  
  14. +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 
  15.  
  16.  
  17.  
  18.  
  19. //bind socket 
  20.  
  21. // 注意這里使用的是傳統(tǒng)的系統(tǒng)調(diào)用 
  22.  
  23. +0 bind(3, ..., ...) = 0 
  24.  
  25.  
  26.  
  27.  
  28. //listen on the socket 
  29.  
  30. // 注意這里使用的是傳統(tǒng)的系統(tǒng)調(diào)用 
  31.  
  32. +0 listen(3, 1) = 0 
  33.  
  34.  
  35.  
  36.  
  37. // client側(cè)(TUN)發(fā)送 syn 握手的第一個(gè)報(bào)文 
  38.  
  39. // 注意這里的語法 syn seq都是相對(duì)的,從0開始。 
  40.  
  41. +0 < S 0:0(0) win 1000 <mss 1000> 
  42.  
  43.  
  44.  
  45.  
  46. // client側(cè)(TUN)期望收到的報(bào)文格式 syn+ack 且 ack.no=ISN(c)+1 
  47.  
  48. // 參考標(biāo)準(zhǔn)流程圖 最后的<...> 表示任何tcp option都可以 
  49.  
  50. // 這里是握手的第二步 
  51.  
  52. +0 > S. 0:0(0) ack 1 <...> 
  53.  
  54.  
  55.  
  56.  
  57. // client側(cè)(TUN)發(fā)送 ack 報(bào)文 seq = ISN(c)+1, ack = ISN(c) +1 
  58.  
  59. // 這里是握手的第三步 
  60.  
  61. +.1 < . 1:1(0) ack 1 win 1000 
  62.  
  63.  
  64.  
  65.  
  66. //握手成功,server側(cè) socket 返回 established socket 
  67.  
  68. //這時(shí)通過accept 系統(tǒng)調(diào)用拿到這個(gè)stream 的socket 
  69.  
  70. +0 accept(3, ..., ...) = 4 
  71.  
  72.  
  73.  
  74.  
  75. //server側(cè)向stream 寫入 10 bytes 
  76.  
  77. //通過系統(tǒng)調(diào)用來完成寫操作 
  78.  
  79. +0 write(4, ..., 10)=10 
  80.  
  81.  
  82.  
  83.  
  84. //client側(cè)期望收到receive 10 bytes 
  85.  
  86. +0 > P. 1:11(10) ack 1 
  87.  
  88.  
  89.  
  90.  
  91. //client側(cè)應(yīng)答 ack 表示接收到 10 bytes 
  92.  
  93. +.0 < . 1:1(0) ack 11 win 1000 
  94.  
  95.  
  96.  
  97.  
  98. // client 關(guān)閉連接 發(fā)送fin包 
  99.  
  100. +0 < F. 1:1(0) ack 11 win 4000 
  101.  
  102.  
  103.  
  104.  
  105. // client側(cè)期望接收到server端的對(duì)于fin的ack報(bào)文 
  106.  
  107. // 這里由內(nèi)核協(xié)議棧發(fā)回。ack = server seq +1, seq = server ack 
  108.  
  109. // 參考標(biāo)準(zhǔn)流程圖 
  110.  
  111. +.005 > . 11:11(0) ack 2 
  112.  
  113.  
  114.  
  115.  
  116. // server 關(guān)閉連接 通過系統(tǒng)調(diào)用完成 
  117.  
  118. +0 close(4) = 0 
  119.  
  120.  
  121.  
  122.  
  123. // client期望接收到的fin包格式 
  124.  
  125. +0 > F. 11:11(0) ack 2 
  126.  
  127.  
  128.  
  129.  
  130. // client 發(fā)送server端fin包的應(yīng)答ack包 
  131.  
  132. +0 < . 2:2(0) ack 12 win 4000 

至此, 我們純手動(dòng)的完成了全部的發(fā)起和關(guān)閉連接的過程。然后我們用wireshark 來驗(yàn)證一下

 

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

SACK

我們將使用packet drill 來探索一些更為復(fù)雜的案例。例如內(nèi)核協(xié)議棧對(duì)于 SACK中各種排列組合的響應(yīng)。

SACK 是TCP協(xié)議中優(yōu)化重傳機(jī)制的一個(gè)重要選項(xiàng)(該選項(xiàng)一般都在報(bào)頭的options部分)。

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

SACK 是一種優(yōu)化措施, 用來避免不必要的重發(fā), 告知發(fā)送方那些報(bào)文已經(jīng)收到,不用再重發(fā)。tcp 的選項(xiàng)中允許帶有最多3個(gè)SACK的options。也就是三個(gè)已經(jīng)收到了得報(bào)文區(qū)間信息。說了這么多, 還是有一些抽象, 我們來看一個(gè)具體的示例。

示例說明

在下面的這個(gè)例子中, 我們需要發(fā)送報(bào)文的順序是 1,3,5,6,8,4,7,2 也就是測(cè)試一下內(nèi)核tcp協(xié)議棧的SACK邏輯是否如同RFC中所描述的一樣。

  1. // 初始化部分建立服務(wù)器端socket, 不再贅述 
  2.  
  3. +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 
  4.  
  5. +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 
  6.  
  7. +0 bind(3, ..., ...) = 0 
  8.  
  9. +0 listen(3, 1) = 0 
  10.  
  11.  
  12.  
  13.  
  14. // Client 端發(fā)送 握手報(bào)文以及接受服務(wù)器響應(yīng),不再贅述。這里注意激活了SACK 
  15.  
  16. +.1 < S 0:0(0) win 50000 <mss 1000, sackOK,nop,nop,nop,wscale 7> 
  17.  
  18. +0 > S. 0:0(0) ack 1 win 32000 <mss 1000,nop,nop,sackOK> 
  19.  
  20. +0 < . 1:1(0) ack 1 win 50000 
  21.  
  22.  
  23.  
  24.  
  25. // Server 端就緒 
  26.  
  27. +.1 accept(3, ..., ...) = 4 
  28.  
  29.  
  30.  
  31.  
  32. //發(fā)送報(bào)文1 
  33.  
  34. +0 < . 1:1001(1000) ack 1 win 50000 
  35.  
  36. //發(fā)送報(bào)文3, 報(bào)文2 被調(diào)整到最后發(fā)送 
  37.  
  38. +0 < . 2001:3001(1000) ack 1 win 50000 
  39.  
  40. //發(fā)送報(bào)文5 報(bào)文4 被調(diào)整亂序 
  41.  
  42. +0 < . 4001:5001(1000) ack 1 win 50000 
  43.  
  44. //發(fā)送報(bào)文6 
  45.  
  46. +0 < . 5001:6001(1000) ack 1 win 50000  
  47.  
  48. //發(fā)送報(bào)文8 報(bào)文7 被調(diào)整亂序 
  49.  
  50. +0 < P. 7001:8001(1000) ack 1 win 50000 
  51.  
  52. //發(fā)送報(bào)文4 
  53.  
  54. +0 < . 3001:4001(1000) ack 1 win 50000 
  55.  
  56. //發(fā)送報(bào)文7 
  57.  
  58. +0 < . 6001:7001(1000) ack 1 win 50000 
  59.  
  60. // 接收到第一個(gè)報(bào)文的ACK 
  61.  
  62. +0 > . 1:1(0) ack 1001 
  63.  
  64.  
  65.  
  66.  
  67. // 接收到SACK, 報(bào)告收到了亂序的報(bào)文3,但是沒報(bào)文2。 
  68.  
  69. +0 > . 1:1(0) ack 1001 win 31000 <nop,nop,sack 2001:3001> 
  70.  
  71. // 接收到SACK, 報(bào)告收到了亂序的報(bào)文3,報(bào)文5,但是沒報(bào)文2。沒報(bào)文4 
  72.  
  73. +0 > . 1:1(0) ack 1001 win 31000 <nop,nop,sack 4001:5001 2001:3001> 
  74.  
  75. // 接收到SACK, 報(bào)告收到了亂序的報(bào)文3,報(bào)文5,但是沒報(bào)文2。沒報(bào)文4 
  76.  
  77. +0 > . 1:1(0) ack 1001 win 31000 <nop,nop,sack 4001:6001 2001:3001> 
  78.  
  79. // 接收到SACK, 報(bào)告收到了亂序的報(bào)文3,報(bào)文5,6, 報(bào)文8,但是沒報(bào)文2。沒報(bào)文4,沒報(bào)文7 
  80.  
  81. +0 > . 1:1(0) ack 1001 win 31000 <nop,nop,sack 7001:8001 4001:6001 2001:3001> 
  82.  
  83. // 接收到SACK, 報(bào)告收到了亂序的報(bào)文3,4,5,6, 報(bào)文8,但是沒報(bào)文2。沒報(bào)文7 
  84.  
  85. +0 > . 1:1(0) ack 1001 win 31000 <nop,nop,sack 2001:6001 7001:8001> 
  86.  
  87. // 接收到SACK, 報(bào)告收到了亂序的報(bào)文3,4,5,6,7,8,但是沒報(bào)文2 
  88.  
  89. +0 > . 1:1(0) ack 1001 win 31000 <nop,nop,sack 2001:8001> 
  90.  
  91.  
  92.  
  93.  
  94. //發(fā)送報(bào)文2 至此所有報(bào)文完結(jié) 
  95.  
  96. +0 < . 1001:2001(1000) ack 1 win 50000 
  97.  
  98.  
  99.  
  100.  
  101. +0 > . 1:1(0) ack 8001` 

隨后我們?cè)賮碛脀ireshark 驗(yàn)證一下。

 

果然完全匹配。

Packet Drill 其實(shí)還有非常復(fù)雜而且更精巧的玩法, 可以充分測(cè)試各種邊界條件。以后有機(jī)會(huì)再和大家進(jìn)一步分享

參考信息

例子腳本的鏈接:

https://gitee.com/block_chainsaw/linux-kernel-tcp-study.git

本文轉(zhuǎn)載自微信公眾號(hào)「Linux閱碼場(chǎng)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系Linux閱碼場(chǎng)公眾號(hào)。  

 

責(zé)任編輯:武曉燕 來源: Linux閱碼場(chǎng)
相關(guān)推薦

2010-08-31 11:14:32

2010-09-06 13:06:08

DB2 9.7

2010-06-13 14:54:40

TCP IP協(xié)議棧linux

2019-09-30 09:28:26

LinuxTCPIP

2023-03-06 15:43:56

2018-05-01 09:00:21

比特幣數(shù)字貨幣區(qū)塊鏈

2025-02-24 08:00:28

2021-07-06 21:29:16

TCPIP協(xié)議棧

2019-07-01 08:51:49

TCPIPLinux

2021-07-09 08:55:23

LinuxTCPIP

2010-08-03 17:23:00

DB2 9.7三種武器

2020-07-09 08:14:43

TCPIP協(xié)議棧

2009-11-10 13:19:09

動(dòng)態(tài)路由協(xié)議

2010-09-08 15:11:36

TCP IP協(xié)議棧

2019-09-18 08:53:55

2019-08-21 05:48:06

TCPIP協(xié)議棧

2020-01-06 11:22:06

TCPLinux內(nèi)核

2009-12-23 17:10:26

2011-11-08 16:32:24

LinuxFreeBSDTCP

2009-11-11 17:40:33

路由器協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)