所有互聯(lián)網(wǎng)服務(wù),均依賴(lài)于TCP/IP協(xié)議棧。懂得數(shù)據(jù)是如何在協(xié)議棧傳輸?shù)模瑢?huì)幫助你提升互聯(lián)網(wǎng)程序的性能和解決TCP相關(guān)問(wèn)題的能力。
我們講述在Linux場(chǎng)景下數(shù)據(jù)包是如何在協(xié)議層傳輸?shù)摹?/p>
1、發(fā)送數(shù)據(jù)
應(yīng)用層發(fā)送數(shù)據(jù)的過(guò)程大致如下:
我們把上述處理過(guò)程的區(qū)域大致分為:
- User區(qū)域
- Kernel 區(qū)域
- Device區(qū)域
在user和kernel區(qū)域的任務(wù)都是由本機(jī)cpu執(zhí)行,這兩個(gè)區(qū)域合并稱(chēng)為host區(qū)域,以區(qū)分device區(qū)域(網(wǎng)絡(luò)接口卡上有單獨(dú)的cpu)。device是接收和發(fā)送數(shù)據(jù)包的網(wǎng)絡(luò)接口卡(Network Interface Card),一般也稱(chēng)為L(zhǎng)AN card。
當(dāng)應(yīng)用程序調(diào)用write(fd, buf, len)來(lái)發(fā)送數(shù)據(jù)時(shí),用戶(hù)態(tài)區(qū)域會(huì)進(jìn)入內(nèi)核態(tài)區(qū)域,建立這個(gè)關(guān)系的紐帶是socket fd和系統(tǒng)調(diào)用write。
在內(nèi)核態(tài)的socket有兩個(gè)buffer:
- send socket buffer,用于發(fā)送數(shù)據(jù)
- receive socket buffer,用于接收數(shù)據(jù)
當(dāng)write系統(tǒng)調(diào)用被執(zhí)行,用戶(hù)態(tài)的數(shù)據(jù)(buf,長(zhǎng)度)會(huì)被拷貝到內(nèi)核區(qū)域的內(nèi)存,并被放入到send socket buffer的末尾(見(jiàn)下圖,發(fā)送是按照順序發(fā)送的),然后TCP就會(huì)被調(diào)用。
TCP中的數(shù)據(jù)結(jié)構(gòu)是TCB(TCP Control Block)。TCB包含了執(zhí)行TCP會(huì)話(huà)所需要的信息,包括TCP連接狀態(tài),接收窗口,擁塞窗口,序號(hào),重傳timer 等。
TCP會(huì)創(chuàng)建TCP數(shù)據(jù)分段,而TCP數(shù)據(jù)分段包括TCP header和payload,如下圖:
Payload是待發(fā)送的socket buffer中的數(shù)據(jù),而TCP header是為了TCP可靠發(fā)送數(shù)據(jù)而加的輔助信息。
這些數(shù)據(jù)分段會(huì)進(jìn)入到IP層,IP層會(huì)加上IP頭部信息到數(shù)據(jù)分段,如下圖:
IP在執(zhí)行路由之前會(huì)去檢查Netfilter LOCAL_OUT鉤子,看是否需要執(zhí)行iptables相關(guān)配置。之后執(zhí)行IP路由。IP路由主要功能是尋找下一跳(例如網(wǎng)關(guān)或路由器)的IP地址,而路由的目的是到達(dá)目的地IP地址所在的機(jī)器。
IP執(zhí)行路由之后,檢查Netfilter POST_ROUTING鉤子,如果有iptables在這方面的配置,就會(huì)去執(zhí)行相關(guān)操作。委托給數(shù)據(jù)鏈路層之前,IP層還會(huì)執(zhí)行ARP(網(wǎng)絡(luò)地址轉(zhuǎn)換),通過(guò)下一跳IP地址來(lái)查找目的MAC地址,并把Ethernet頭部添加到IP數(shù)據(jù)包,如下圖。
IP層同時(shí)還給用戶(hù)提供了raw socket接口,即發(fā)送數(shù)據(jù)包的接口。raw socket發(fā)送的數(shù)據(jù)包與正常流程的數(shù)據(jù)包不一樣,在執(zhí)行Netfilter的時(shí)候,會(huì)跳過(guò)這些鉤子。
IP層做完工作以后,會(huì)把數(shù)據(jù)包(上圖中的數(shù)據(jù)包,一般稱(chēng)frame)委托給數(shù)據(jù)鏈路層。
由于ARP已經(jīng)把目的MAC地址寫(xiě)入到數(shù)據(jù)包頭部,這樣就減輕了驅(qū)動(dòng)driver的工作。進(jìn)入數(shù)據(jù)鏈路層后,內(nèi)核會(huì)去檢測(cè)是否有抓包工具在監(jiān)聽(tīng)抓包(例如tcpdump),如果有,內(nèi)核會(huì)拷貝數(shù)據(jù)包信息到抓包工具的內(nèi)存地址空間。
之后,根據(jù)一定的協(xié)議規(guī)則,驅(qū)動(dòng)driver會(huì)要求NIC傳遞這個(gè)數(shù)據(jù)包。當(dāng)NIC收到這個(gè)請(qǐng)求后,NIC復(fù)制數(shù)據(jù)包到自己的內(nèi)存里,并且發(fā)送給網(wǎng)絡(luò)。當(dāng)NIC發(fā)送完一個(gè)數(shù)據(jù)包,會(huì)產(chǎn)生一個(gè)中斷, 主機(jī) cpu去執(zhí)行中斷處理程序,完成后續(xù)工作。
2、接收數(shù)據(jù)
應(yīng)用程序接收數(shù)據(jù)的過(guò)程大致如下:
首先NIC把數(shù)據(jù)包寫(xiě)入自己的內(nèi)存,并校驗(yàn)數(shù)據(jù)包是不是有效的,如果是有效的,把數(shù)據(jù)包寫(xiě)入主機(jī)的內(nèi)存空間,然后NIC給主機(jī)操作系統(tǒng)發(fā)送一個(gè)中斷信號(hào),這時(shí)就進(jìn)入到kernel區(qū)域。
在數(shù)據(jù)鏈路層,內(nèi)核首先會(huì)做數(shù)據(jù)包檢測(cè),然后Driver驅(qū)動(dòng)把數(shù)據(jù)包進(jìn)行改裝,以便后續(xù)TCP/IP能夠理解這個(gè)數(shù)據(jù)包。改裝完以后,根據(jù)Ethernet頭部信息中的Ethertype分發(fā)給上層,假設(shè)為IPv4,去除Ethernet頭部,并發(fā)送給IP層。值得注意的是,委托給IP層之前,如果有抓包工具在監(jiān)聽(tīng)抓包,那么內(nèi)核就會(huì)拷貝數(shù)據(jù)包信息到抓包工具的內(nèi)存地址空間。
IP層通過(guò)計(jì)算checksum來(lái)校驗(yàn)IP頭部的checksum是否有效,如果有效,接著檢查PRE_ROUTING鉤子(比如查看是否有iptables的相應(yīng)配置需要執(zhí)行),然后執(zhí)行IP路由,IP路由會(huì)判斷這個(gè)數(shù)據(jù)包是本地處理還是轉(zhuǎn)發(fā)當(dāng)前數(shù)據(jù)包到其它主機(jī)。如果是轉(zhuǎn)發(fā)數(shù)據(jù)包,執(zhí)行FORWARD和POST_ROUTING鉤子,并轉(zhuǎn)發(fā)給數(shù)據(jù)鏈路層;如果是本地處理,IP還會(huì)檢查L(zhǎng)OCAL_IN鉤子,執(zhí)行完以后,根據(jù)IP頭部信息的proto值,假設(shè)為T(mén)CP,去除IP頭部,并把數(shù)據(jù)包傳遞給上層TCP。值得注意的是,委托給TCP層之前,如果有raw socket在監(jiān)聽(tīng)抓包,那么內(nèi)核會(huì)拷貝數(shù)據(jù)包信息到raw socket的內(nèi)存地址空間(默認(rèn)tcpcopy利用raw socket來(lái)監(jiān)聽(tīng)I(yíng)P層的數(shù)據(jù)包)。
TCP層會(huì)根據(jù)TCP checksum來(lái)檢測(cè)數(shù)據(jù)包是否有效(如果采用了checksum offload,NIC會(huì)去做相關(guān)計(jì)算),然后就給這個(gè)數(shù)據(jù)包查找相應(yīng)的TCB(TCP control block),查找的方法是通過(guò)如下組合信息來(lái)查找:
如果沒(méi)有查到,一般會(huì)發(fā)送reset數(shù)據(jù)包;如果查到了,進(jìn)入TCP數(shù)據(jù)包處理環(huán)節(jié)。
如果是接收到新數(shù)據(jù),TCP就會(huì)把它放入到socket接收緩沖區(qū),然后根據(jù)TCP狀態(tài),必要時(shí)發(fā)送ack確認(rèn)數(shù)據(jù)包。Socket接收緩沖區(qū)的大小就是TCP接收窗口大小。在某種程度上,如果接收窗口很大,TCP吞吐量就會(huì)很大。目前較新的內(nèi)核都能動(dòng)態(tài)調(diào)整窗口的大小,無(wú)需用戶(hù)去修改系統(tǒng)參數(shù)。
用戶(hù)應(yīng)用程序根據(jù)讀事件去執(zhí)行讀操作,用戶(hù)態(tài)空間進(jìn)入到內(nèi)核空間。內(nèi)核把socket buffer里面的內(nèi)容復(fù)制到用戶(hù)指定的內(nèi)存區(qū)域,然后把socket buffer讀取過(guò)的內(nèi)容釋放,TCP增加接收窗口大小,如果有必要,會(huì)傳遞一個(gè)更新窗口的數(shù)據(jù)包給對(duì)端TCP。例如下圖,TCP發(fā)送了一個(gè)ack數(shù)據(jù)包,用于通知對(duì)端TCP,本方TCP接收窗口更新了。
讀取操作完成后,返回應(yīng)用程序,應(yīng)用程序就可以進(jìn)行對(duì)數(shù)據(jù)進(jìn)行處理了。
3、抓包工具工作原理
知道了數(shù)據(jù)如何發(fā)送和接收以后,我們分析一下tcpdump抓包原理。
在數(shù)據(jù)鏈路層和IP層交界的地方(屬于數(shù)據(jù)鏈路層,如下圖),是數(shù)據(jù)包被tcpdump捕獲的場(chǎng)所。
執(zhí)行到這個(gè)交界處時(shí),內(nèi)核會(huì)去查看tcpdump是否在監(jiān)聽(tīng),一旦有監(jiān)聽(tīng),就把數(shù)據(jù)包內(nèi)容放入到tcpdump設(shè)置的緩沖區(qū)。理論上只要tcpdump及時(shí)去提取數(shù)據(jù),在線(xiàn)上壓力不大的情況下,抓包不會(huì)丟包。
tcpdump所抓到的數(shù)據(jù)包,僅僅是代表數(shù)據(jù)包經(jīng)過(guò)了鏈路層和網(wǎng)絡(luò)層之間的交界處。從網(wǎng)卡進(jìn)來(lái)的數(shù)據(jù)包未來(lái)的命運(yùn),可能是繼續(xù)一路往前走到TCP,也有可能在IP層被干掉,還有可能被路由轉(zhuǎn)發(fā)出去;從本機(jī)發(fā)送出去的數(shù)據(jù)包,一旦被tcpdump捕獲到,說(shuō)明已經(jīng)到了數(shù)據(jù)鏈路層,沒(méi)有被IP層過(guò)濾掉,因?yàn)槿绻麛?shù)據(jù)包被IP層過(guò)濾掉,這些數(shù)據(jù)包就不會(huì)到達(dá)tcpdump捕獲點(diǎn),也不會(huì)出現(xiàn)在抓包文件里。
下面我們通過(guò)一些實(shí)驗(yàn)來(lái)驗(yàn)證上述結(jié)論。
實(shí)驗(yàn)之前,我們先介紹一下iptables工具。iptables是被廣泛使用的防火墻工具,它主要跟內(nèi)核netfilter數(shù)據(jù)包過(guò)濾框架進(jìn)行交互。
3.1 實(shí)驗(yàn) LOCAL_IN過(guò)濾
我們?cè)诜?wù)器上面配置如下的iptables命令:
iptables -I INPUT -p tcp --dport 3306 -s 172.17.0.2 -j QUEUE
上述iptables命令設(shè)置了'-I INPUT'參數(shù),意味著在netfilter LOCAL_IN鉤子處執(zhí)行上述iptables規(guī)則,即通往服務(wù)器端TCP之前,如果匹配到上述iptables規(guī)則,則會(huì)被放入目標(biāo)QUEUE(默認(rèn)情況下是直接丟棄數(shù)據(jù)包),不再繼續(xù)前行。
具體命令執(zhí)行見(jiàn)下圖:
設(shè)置上述iptables后,當(dāng)172.17.0.2訪問(wèn)172.17.0.3 3306服務(wù)時(shí),IP數(shù)據(jù)包(如下圖綠色箭頭)會(huì)在服務(wù)器端IP層被丟棄掉,而紅色箭頭所指方向是tcpdump抓包的地方。
我們開(kāi)啟tcpdump抓包:
tcpdump -i any tcp and port 3306 and host 172.17.0.2 -n -v
在172.17.0.2上利用MySQL客戶(hù)端命令訪問(wèn)172.17.0.3上面的3306服務(wù),如下圖:
結(jié)果經(jīng)過(guò)長(zhǎng)時(shí)間等待,最終顯示連接不上。
服務(wù)器端抓包結(jié)果如下:
我們看到第一次握手?jǐn)?shù)據(jù)包反復(fù)重傳。
利用netstat命令,查看有沒(méi)有相應(yīng)的TCP狀態(tài),結(jié)果發(fā)現(xiàn)沒(méi)有,如下圖:
正常情況下,沒(méi)有TCP狀態(tài),說(shuō)明數(shù)據(jù)包沒(méi)有進(jìn)入服務(wù)器端TCP,第一次握手?jǐn)?shù)據(jù)包在服務(wù)器端IP層被干掉了。
利用netstat -s命令,在服務(wù)器端TCP/IP統(tǒng)計(jì)參數(shù)里找線(xiàn)索:
上圖服務(wù)器端IP層接收到20079個(gè)數(shù)據(jù)包,下圖接收到20086個(gè)數(shù)據(jù)包,MySQL客戶(hù)端登入過(guò)程累計(jì)增加了7個(gè)數(shù)據(jù)包,正好符合抓包文件顯示的7個(gè)第一次握手?jǐn)?shù)據(jù)包。
在服務(wù)器端TCP層,對(duì)比上面兩張圖,數(shù)據(jù)沒(méi)有任何變化,說(shuō)明了服務(wù)器端TCP沒(méi)有收到任何數(shù)據(jù)包。
實(shí)驗(yàn)說(shuō)明了在服務(wù)器端IP層進(jìn)來(lái)的方向干掉數(shù)據(jù)包,服務(wù)器端TCP層不會(huì)有任何變化。
3.2 實(shí)驗(yàn) LOCAL_OUT過(guò)濾
我們這次實(shí)驗(yàn)的目的是查看IP層netfilter LOCAL_OUT情況下的抓包情況。
如下圖:
我們?cè)O(shè)置如下iptables命令:
iptables -I OUTPUT -p tcp --sport 3306 -d 172.17.0.2 -j QUEUE
具體操作如下圖:
上述iptables命令設(shè)置了OUTPUT參數(shù),意味著在netfilter LOCAL_OUT鉤子處會(huì)執(zhí)行上述iptables規(guī)則,即IP數(shù)據(jù)包在IP路由之前,如果匹配上述iptables規(guī)則,則會(huì)被放入目標(biāo)QUEUE(默認(rèn)情況下直接丟棄數(shù)據(jù)包),不會(huì)繼續(xù)往下走。
在172.17.0.2上利用MySQL客戶(hù)端命令訪問(wèn)172.17.0.3上面的3306服務(wù),如下圖:
結(jié)果經(jīng)過(guò)長(zhǎng)時(shí)間等待,最終顯示連接不上。
服務(wù)器端抓包結(jié)果如下:
我們看到第一次握手?jǐn)?shù)據(jù)包反復(fù)重傳,跟上一個(gè)抓包結(jié)果幾乎一模一樣
利用netstat命令,查看有沒(méi)有相應(yīng)的TCP狀態(tài),結(jié)果發(fā)現(xiàn)有SYN_RECV狀態(tài),如下圖:
有TCP狀態(tài),說(shuō)明數(shù)據(jù)包進(jìn)入服務(wù)器端TCP,并進(jìn)入SYN_RECV狀態(tài),服務(wù)器端TCP會(huì)發(fā)送第二次握手?jǐn)?shù)據(jù)包,但抓包顯示并沒(méi)有第二次握手?jǐn)?shù)據(jù)包,說(shuō)明被iptables配置干掉了。
查看netstat -s結(jié)果:
上圖顯示了實(shí)驗(yàn)之前的值,下圖顯示了實(shí)驗(yàn)之后的值。
從TCP層面信息來(lái)看,發(fā)送了17個(gè)數(shù)據(jù)分段,說(shuō)明服務(wù)器端TCP發(fā)送了第二次握手?jǐn)?shù)據(jù)包,而且發(fā)送了很多次,但因?yàn)樵O(shè)置了iptables,這些數(shù)據(jù)包被攔截掉了,所以到不了數(shù)據(jù)鏈路層,也就沒(méi)法被tcpdump捕獲到。
從這兩個(gè)實(shí)驗(yàn)來(lái)看,tcpdump抓的數(shù)據(jù)包是一樣的,都是在努力重傳第一次握手?jǐn)?shù)據(jù)包,但iptables設(shè)置的位置不一樣,一個(gè)在入口,在TCP層無(wú)狀態(tài),一個(gè)在出口,在TCP層有狀態(tài)。
進(jìn)一步的分析可以嘗試下面兩個(gè)方向:
- 通過(guò)分析TCP狀態(tài)來(lái)區(qū)分這兩種情況
- 利用netstat -s給出的TCP/IP統(tǒng)計(jì)參數(shù)變化
通過(guò)上面實(shí)驗(yàn),我們看出tcpdump抓包只是從一個(gè)點(diǎn)來(lái)觀察世界,并不能看到全貌,這個(gè)時(shí)候就需要通過(guò)推理來(lái)輔助解決問(wèn)題。
4、潛在協(xié)議層的干擾
4.1 接收數(shù)據(jù)
下圖展示了數(shù)據(jù)包從NIC到協(xié)議棧,再到應(yīng)用程序的過(guò)程。
TCP offload由NIC完成,目的是減輕TCP的工作量,但存在潛在坑;在數(shù)據(jù)鏈路層,存在抓包接口,供tcpdump等抓包工具抓包,同時(shí)也存在著raw socket原始抓包方式接口;在網(wǎng)絡(luò)層,存在raw socket抓包接口,IP Forward轉(zhuǎn)發(fā)功能,還有一整套Netfilter框架(存在大量坑的地方);在TCP層則相對(duì)比較清靜,干擾少;用戶(hù)程序通過(guò)socket接口從TCP取出數(shù)據(jù)或者獲取新建連接。
4.2 發(fā)送數(shù)據(jù)
下圖展示了數(shù)據(jù)包從應(yīng)用發(fā)送數(shù)據(jù)到NIC的過(guò)程。
用戶(hù)程序通過(guò)socket接口來(lái)委托TCP發(fā)送數(shù)據(jù)或者建立連接;在網(wǎng)絡(luò)層,存在raw socket發(fā)包接口,還有一整套Netfilter框架(存在大量坑的地方);在數(shù)據(jù)鏈路層,存在pcap發(fā)包接口,同時(shí)也存在著raw socket原始發(fā)包接口;TCP offload是NIC做的,目的為了提升減輕TCP的工作量(比如分段,checksum),我們也遇到過(guò)由于TCP offload不當(dāng)導(dǎo)致的丟包問(wèn)題。
4.3 案例
下面是一個(gè)從NIC接收數(shù)據(jù)包,并一路到應(yīng)用,再發(fā)送響應(yīng)出去的案例:
我們的應(yīng)用程序是Nginx(Web服務(wù)器軟件),其中Nginx配置監(jiān)聽(tīng)端口為8080,且開(kāi)啟access log。
上圖設(shè)置了nginx keepalive_timeout = 0,即保持客戶(hù)端空閑連接(方便實(shí)驗(yàn))。
啟動(dòng)nginx,通過(guò)netstat查看,nginx已經(jīng)在監(jiān)聽(tīng)8080端口的連接請(qǐng)求。
剛開(kāi)始nginx沒(méi)有任何訪問(wèn),access log都為空,iptables也沒(méi)有設(shè)置。
在172.17.0.2機(jī)器,利用telnet訪問(wèn)172.17.0.3上面的8080端口服務(wù),如下圖:
這樣telnet跟nginx建立連接,下圖可以看出服務(wù)器端相應(yīng)連接已經(jīng)進(jìn)入ESTABLISHED狀態(tài)。
建立連接后,我們?cè)O(shè)置iptables命令,如下圖,對(duì)返回172.17.0.2的nginx響應(yīng)進(jìn)行攔截并丟棄。
我們?cè)诳蛻?hù)端(172.17.0.2)上面繼續(xù)執(zhí)行telnet命令,鍵入'GET hello.html',然后回車(chē)執(zhí)行。
從nginx日志來(lái)看,這個(gè)請(qǐng)求已經(jīng)被處理了,雖然是非法請(qǐng)求,但請(qǐng)求已經(jīng)確認(rèn)到達(dá)nginx了。
大概過(guò)了2分鐘,查看客戶(hù)端抓包情況,累計(jì)捕獲了16個(gè)數(shù)據(jù)包,客戶(hù)端還顯示連接處于ESTABLISHED狀態(tài)。
我們查看服務(wù)器端情況,利用netstat已經(jīng)查不到服務(wù)器端的相應(yīng)連接了,說(shuō)明連接在服務(wù)器端的TCP層已經(jīng)不存在了。
我們分析抓包情況(服務(wù)器抓包和客戶(hù)端抓包效果一樣):
自從發(fā)送了請(qǐng)求數(shù)據(jù)包,客戶(hù)端由于沒(méi)有看到任何服務(wù)器端的數(shù)據(jù)包回來(lái),一直在重傳請(qǐng)求數(shù)據(jù)包。客戶(hù)端以為服務(wù)器還沒(méi)有收到請(qǐng)求,但其實(shí)請(qǐng)求已經(jīng)被nginx處理完畢。
在服務(wù)器端查看netstat -st的統(tǒng)計(jì)情況。
上圖是執(zhí)行telnet請(qǐng)求之前的狀況,下圖是執(zhí)行telnet請(qǐng)求之后的狀況。
從上圖我們可以看出connection aborted due to timeout增加了一個(gè),說(shuō)明在服務(wù)器端TCP看來(lái),請(qǐng)求的響應(yīng)數(shù)據(jù)包(同時(shí)帶有關(guān)閉fin標(biāo)志)由于發(fā)送不出去,連接被aborted,這個(gè)時(shí)候在服務(wù)器端看不到連接相應(yīng)狀態(tài)的存在。
在上層nginx看來(lái),遇到了非法請(qǐng)求,回復(fù)了響應(yīng)并關(guān)閉了連接。在TCP層看來(lái),由于帶有關(guān)閉fin的數(shù)據(jù)包到不了tcpdump抓包接口,服務(wù)器端的TCP狀態(tài)會(huì)處于FIN_WAIT_1狀態(tài)('遇到大量FIN_WAIT1,怎么破?'會(huì)有詳細(xì)介紹),會(huì)維持一段時(shí)間并不斷努力重傳。由于重傳一直得不到響應(yīng),TCP就把FIN_WAIT_1狀態(tài)變?yōu)镃LOSED狀態(tài),在服務(wù)器端查不到該連接了。
這里案例中,我們事先知道我們?cè)O(shè)置了iptables,但如果不知道呢,我們?nèi)绾闻袛喑鰡?wèn)題出在哪一個(gè)環(huán)節(jié)呢?
僅僅靠tcpdump抓包,明顯不夠,因?yàn)橥ㄟ^(guò)抓包分析,我們只能得出服務(wù)器端沒(méi)有接收到請(qǐng)求,我們還需要利用服務(wù)器端的信息,才能繼續(xù)進(jìn)一步判斷。通過(guò)nginx日志,判斷出請(qǐng)求已經(jīng)被應(yīng)用層處理了,說(shuō)明請(qǐng)求數(shù)據(jù)包已經(jīng)到達(dá)應(yīng)用層,nginx已經(jīng)處理請(qǐng)求,并作了響應(yīng)處理,接著委托服務(wù)器端TCP去發(fā)送這些響應(yīng)數(shù)據(jù)包,但顯然服務(wù)器端TCP發(fā)送的響應(yīng)都沒(méi)有到達(dá)抓包接口,說(shuō)明在IP層干掉了,于是可以根據(jù)這些信息去找數(shù)據(jù)包出去方向(outgoing)的netfilter相關(guān)配置,看看有沒(méi)有這樣針對(duì)這些響應(yīng)進(jìn)行過(guò)濾。
從上面案例,可以看出僅僅利用tcpdump是不夠的,還需要綜合利用各種信息,并加以推理,最終得出問(wèn)題出在哪一個(gè)環(huán)節(jié),才能解決問(wèn)題。如果不會(huì)利用這些知識(shí),客戶(hù)端就就會(huì)得出服務(wù)器端沒(méi)有收到請(qǐng)求的錯(cuò)誤判斷。
5、跨機(jī)器判斷
在跨機(jī)器訪問(wèn)過(guò)程中,存在著如下潛在干涉(坑):
- 本機(jī)器自身IP層安全過(guò)濾
- 鏈路層發(fā)送QUEUE丟包
- 鏈路層TCP offload潛在問(wèn)題(這里把NIC歸入數(shù)據(jù)鏈路層)
- 中途設(shè)備各種問(wèn)題(設(shè)備包括路由器/交換機(jī)/防火墻/網(wǎng)關(guān)/負(fù)載均衡器等)
- 對(duì)端機(jī)器鏈路層接收QUEUE丟包
- 對(duì)端鏈路層TCP offload(NIC)潛在問(wèn)題
- 對(duì)端IP層安全過(guò)濾
- 對(duì)端TCP異常狀態(tài)干擾
這些問(wèn)題將在TCPCopy和其它章節(jié)會(huì)有所介紹,這里不再詳細(xì)描述。
6、常用工具工作層次分析
上圖展示了部分流行性工具的工作層次,比如tcpcopy默認(rèn)工作在4層,調(diào)用IP層提供的raw socket接口來(lái)抓包和發(fā)包;netstat或者ss工具可以去**TCP/IP各種統(tǒng)計(jì)值;LVS工作在4層,利用Netfilter來(lái)強(qiáng)行改變路由;tcpdump工作在數(shù)據(jù)鏈路層;HTTP應(yīng)用工作在應(yīng)用層。
懂得了這些工作原理,可以更加深刻的理解問(wèn)題,并解決各種TCP相關(guān)問(wèn)題。
-
互聯(lián)網(wǎng)
+關(guān)注
關(guān)注
55文章
11242瀏覽量
106170 -
Linux
+關(guān)注
關(guān)注
87文章
11506瀏覽量
213382 -
網(wǎng)絡(luò)接口
+關(guān)注
關(guān)注
0文章
90瀏覽量
17742 -
數(shù)據(jù)包
+關(guān)注
關(guān)注
0文章
269瀏覽量
24955
發(fā)布評(píng)論請(qǐng)先 登錄
Linux系統(tǒng)收發(fā)網(wǎng)絡(luò)數(shù)據(jù)包的工作過(guò)程

如何在AIROC GUI上獲取良好數(shù)據(jù)包和總數(shù)據(jù)包?
AXI流數(shù)據(jù)包傳輸問(wèn)題
UART數(shù)據(jù)包設(shè)計(jì)與解析
如何在沒(méi)有收到另一個(gè)udp數(shù)據(jù)包的情況下簡(jiǎn)單地發(fā)送一個(gè)udp數(shù)據(jù)包?
以太網(wǎng)數(shù)據(jù)包捕獲與轉(zhuǎn)發(fā)技術(shù)
基于Linux的數(shù)據(jù)安全傳輸的研究
基于Jpcap的數(shù)據(jù)包捕獲器的設(shè)計(jì)與實(shí)現(xiàn)
Linux網(wǎng)絡(luò)防火墻Netfilter的數(shù)據(jù)包傳輸過(guò)濾原理

Netfilter架構(gòu)下數(shù)據(jù)包信息存儲(chǔ)的應(yīng)用_吳良敏
Linux內(nèi)核網(wǎng)絡(luò)數(shù)據(jù)包發(fā)送在UDP協(xié)議層的處理

數(shù)據(jù)包的發(fā)送流程
wireshark導(dǎo)入數(shù)據(jù)包進(jìn)行分析
簡(jiǎn)述Linux系統(tǒng)收發(fā)網(wǎng)絡(luò)數(shù)據(jù)包的過(guò)程

Linux如何操作將數(shù)據(jù)包發(fā)送出去

評(píng)論