前發了一篇網絡排查問題的文章,反響不錯,今天就常用的網絡排查命令tcpdump 抓取tcp通信過程給大家展示一下
https://www.tcpdump.org/manpages/tcpdump.1.html
tcpdump官網的一段描述:
The general format of a TCP protocol line is:
src > dst: Flags [tcpflags], seq data-seqno, ack ackno, win window, urg urgent, options [opts], length len
Src and dst are the source and destination IP addresses and ports.
Tcpflags are some combination of S (SYN), F (FIN), P (PUSH), R (RST), U (URG), W (ECN CWR), E (ECN-Echo) or '.' (ACK), or 'none' if no flags are set.
Data-seqno describes the portion of sequence space covered by the data in this packet (see example below).
Ackno is sequence number of the next data expected the other direction on this connection.
Window is the number of bytes of receive buffer space available the other direction on this connection.
Urg indicates there is 'urgent' data in the packet.
Opts are TCP options (e.g., mss 1024).
Len is the length of payload data.
簡單翻譯一下:
tcpdump命令的使用方法
src > dst: Flags [tcpflags], seq data-seqno, ack ackno, win window, urg urgent, options [opts], length len
Src and dst are the source and destination IP addresses and ports.
src 和 dst 用來指定源IP 端口 和 目的地地址和端口
tcp標志S (SYN), F (FIN), P (PUSH), R (RST), U (URG), W (ECN CWR), E (ECN-Echo) or '.' (ACK)
注意"." 這個點符號代表的是ACK,那么"S." 就表示 SYN,ACK
// 上述標志是TCP常用的標志,如果有不熟悉的同學,后面我會補充一篇關于TCP協議的文章
1
下面我在我的linux虛擬機里面進行實踐操作,首先通過shell每隔5秒訪問一次百度
打開一個新的窗口,開始使用tcpdump命令抓包,因為我虛擬機很純凈,這里抓80端口就可以了
for((i=1;i>0;i++)) { curl www.baidu.com; sleep 5; } // sleep 5 防止后面tcpdump刷屏太快
tcpdump -nn tcp and port 80 -c 50 -w baidu.cap // 抓取 端口為80的 tcp包 50條 記錄到 baidu.cap
tcpdump -r baidu.cap -nn // 讀取 baidu.cap -nn 表示端口 直接使用數字顯示
// 三次握手
00:01:27.495986 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [S], seq 3269637489, win 14600, options [mss 1460,sackOK,TS val 36161220 ecr 0,nop,wscale 7], length 0
00:01:27.499790 IP 61.135.169.121.80 > 10.0.2.15.39629: Flags [S.], seq 1731784705, ack 3269637490, win 65535, options [mss 1460], length 0
00:01:27.499839 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [.], ack 1, win 14600, length 0
// Flags [S] SYC
// Flags [S.] SYC ACK
// Flags [.] ACK
// 數據
00:01:27.500578 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [P.], seq 1:177, ack 1, win 14600, length 176
00:01:27.500884 IP 61.135.169.121.80 > 10.0.2.15.39629: Flags [.], ack 177, win 65535, length 0
00:01:27.505774 IP 61.135.169.121.80 > 10.0.2.15.39629: Flags [.], seq 1:1421, ack 177, win 65535, length 1420
00:01:27.505790 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [.], ack 1421, win 17040, length 0
00:01:27.505947 IP 61.135.169.121.80 > 10.0.2.15.39629: Flags [P.], seq 1421:1441, ack 177, win 65535, length 20
00:01:27.505961 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [.], ack 1441, win 17040, length 0
00:01:27.506046 IP 61.135.169.121.80 > 10.0.2.15.39629: Flags [P.], seq 1441:2782, ack 177, win 65535, length 1341
00:01:27.506059 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [.], ack 2782, win 19880, length 0
// Flags [P.] PSH ACK
// 四次揮手
00:01:27.506605 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [F.], seq 177, ack 2782, win 19880, length 0
00:01:27.506806 IP 61.135.169.121.80 > 10.0.2.15.39629: Flags [.], ack 178, win 65535, length 0
00:01:27.510914 IP 61.135.169.121.80 > 10.0.2.15.39629: Flags [F.], seq 2782, ack 178, win 65535, length 0
00:01:27.510932 IP 10.0.2.15.39629 > 61.135.169.121.80: Flags [.], ack 2783, win 19880, length 0
// Flags [F.] FIN ACK
2 用wireshark查看net文件
wireshark打開net文件
統計>流量圖
統計>流量圖
3 總結一下
可以發現通過 tcpdump 工具 可以 清晰看到完整的TCP 三次握手和四次揮手的過程
在排查網絡,抓包的時候該命令十分常用,是一個需要掌握的進階命令,當然前提是要熟悉tcp協議
LISTEN – 偵聽來自遠方TCP端口的連接請求;
SYN-SENT -在發送連接請求后等待匹配的連接請求;
SYN-RECEIVED – 在收到和發送一個連接請求后等待對連接請求的確認;
ESTABLISHED- 代表一個打開的連接,數據可以傳送給用戶;
FIN-WAIT-1 – 等待遠程TCP的連接中斷請求,或先前的連接中斷請求的確認;
FIN-WAIT-2 – 從遠程TCP等待連接中斷請求;
CLOSE-WAIT – 等待從本地用戶發來的連接中斷請求;
CLOSING -等待遠程TCP對連接中斷的確認;
LAST-ACK – 等待原來發向遠程TCP的連接中斷請求的確認;
TIME-WAIT -等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認;
CLOSED – 沒有任何連接狀態;
路由器僅根據網絡號net-id來轉發分組,當分組到達目的網絡的路由器之后,再按照主機號host-id將分組交付給主機;同一網絡上的所有主機的網絡號相同。
從主機號host-id借用若干個比特作為子網號subnet-id;子網掩碼:網絡號和子網號都為1,主機號為0;數據報仍然先按照網絡號找到目的網絡,發送到路由器,路由器再按照網絡號和子網號找到目的子網:將子網掩碼與目標地址逐比特與操作,若結果為某個子網的網絡地址,則送到該子網。
每臺主機或路由器在其內存中具有一個ARP表(ARP table),這張表包含IP地址到MAC地址的映射關系。將IP地址通過廣播,根據目標IP地址解析到MAC地址。
1. Ping
Ping 是 ICMP 的一個重要應用,主要用來測試兩臺主機之間的連通性。
Ping 的原理是通過向目的主機發送 ICMP Echo 請求報文,目的主機收到之后會發送 Echo 回答報文。Ping 會根據時間和成功響應的次數估算出數據包往返時間以及丟包率。
2. Traceroute
Traceroute 是 ICMP 的另一個應用,用來跟蹤一個分組從源點到終點的路徑。
Traceroute 發送的 IP 數據報封裝的是無法交付的 UDP 用戶數據報,并由目的主機發送終點不可達差錯報告報文。
用于解決內網中的主機要和因特網上的主機通信。由NAT路由器將主機的本地IP地址轉換為全球IP地址,分為靜態轉換(轉換得到的全球IP地址固定不變)和動態NAT轉換。
每個路由器維護一張表,記錄該路由器到其它網絡的”跳數“,路由器到與其直接連接的網絡的跳數是1,每多經過一個路由器跳數就加1;更新該表時和相鄰路由器交換路由信息;路由器允許一個路徑最多包含15個路由器,如果跳數為16,則不可達。交付數據報時優先選取距離最短的路徑。
1、 客戶端發送自己支持的加密規則給服務器,代表告訴服務器要進行連接了;
2、 服務器從中選出一套加密算法和 hash 算法以及自己的身份信息(地址等)以證書的形式發送給瀏覽器,證書中包含服務器信息,加密公鑰,證書的頒發機構;
3、客戶端收到網站的證書之后要做下面的事情:
4、服務器接收到客戶端傳送來的信息,要做下面的事情:
5、如果計算法 hash 值一致,握手成功。
把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。
作者:雨點的名字 來源:https://www.cnblogs.com/qdhxhz/p/8470997.html
CP有6種標示:SYN(建立聯機) ACK(確認) PSH(傳送) FIN(結束) RST(重置) URG(緊急)
一、TCP三次握手
第一次握手
客戶端向服務器發出連接請求報文,這時報文首部中的同部位SYN=1,同時隨機生成初始序列號 seq=x,此時,TCP客戶端進程進入了 SYN-SENT(同步已發送狀態)狀態。TCP規定,SYN報文段(SYN=1的報文段)不能攜帶數據,但需要消耗掉一個序號。這個三次握手中的開始。表示客戶端想要和服務端建立連接。
第二次握手
TCP服務器收到請求報文后,如果同意連接,則發出確認報文。確認報文中應該 ACK=1,SYN=1,確認號是ack=x+1,同時也要為自己隨機初始化一個序列號 seq=y,此時,TCP服務器進程進入了SYN-RCVD(同步收到)狀態。這個報文也不能攜帶數據,但是同樣要消耗一個序號。這個報文帶有SYN(建立連接)和ACK(確認)標志,詢問客戶端是否準備好。
第三次握手
TCP客戶進程收到確認后,還要向服務器給出確認。確認報文的ACK=1,ack=y+1,此時,TCP連接建立,客戶端進入ESTABLISHED(已建立連接)狀態。
TCP規定,ACK報文段可以攜帶數據,但是如果不攜帶數據則不消耗序號。這里客戶端表示我已經準備好。
思考:為什么要三次握手呢,有人說兩次握手就好了
舉例:已失效的連接請求報文段。
client發送了第一個連接的請求報文,但是由于網絡不好,這個請求沒有立即到達服務端,而是在某個網絡節點中滯留了,直到某個時間才到達server,本來這已經是一個失效的報文,但是server端接收到這個請求報文后,還是會想client發出確認的報文,表示同意連接。
假如不采用三次握手,那么只要server發出確認,新的建立就連接了,但其實這個請求是失效的請求,client是不會理睬server的確認信息,也不會向服務端發送確認的請求,但是server認為新的連接已經建立起來了,并一直等待client發來數據,這樣,server的很多資源就沒白白浪費掉了,采用三次握手就是為了防止這種情況的發生,server會因為收不到確認的報文,就知道client并沒有建立連接。這就是三次握手的作用。
二、TCP數據的傳輸過程
建立連接后,兩臺主機就可以相互傳輸數據了。如下圖所示:
1)主機A初始seq為1200,滑動窗體為100,向主機B傳遞數據的過程。
2)假設主機B在完全成功接收數據的基礎上,那么主機B為了確認這一點,向主機A發送 ACK 包,并將 Ack 號設置為 1301。因此按如下的公式確認 Ack 號:
Ack號=Seq號 + 傳遞的字節數 + 1(這是在完全接受成功的情況下)
3)主機A獲得B傳來的ack(1301)后,開始發送seq為1301,滑動窗體為100的數據。
……
與三次握手協議相同,最后加 1 是為了告訴對方要傳遞的 Seq 號。上面說了,主機B完全成功接收A發來的數據才是這樣的,如果存在丟包該如何。
下面分析傳輸過程中數據包丟失的情況,如下圖所示:
上圖表示通過 Seq 1301 數據包向主機B傳遞100字節的數據,但中間發生了錯誤,主機B未收到。經過一段時間后,主機A仍未收到對于 Seq 1301 的ACK確認,因此嘗試
重傳數據。為了完成數據包的重傳,TCP套接字每次發送數據包時都會啟動定時器,如果在一定時間內沒有收到目標機器傳回的 ACK 包,那么定時器超時,數據包會重傳。
上面也只是一種可能,比如數據1250丟失,那么Ack返回的就是1250,具體的可以詳細看下博客:
https://www.cnblogs.com/qdhxhz/p/10267932.html
三、TCP的四次揮手
第一次揮手
TCP發送一個FIN(結束),用來關閉客戶到服務端的連接??蛻舳诉M程發出連接釋放報文,并且停止發送數據。
釋放數據報文首部,FIN=1,其序列號為seq=u(等于前面已經傳送過來的數據的最后一個字節的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。TCP規定,FIN報文段即使不攜帶數據,也要消耗一個序號。
第二次揮手
服務端收到這個FIN,他發回一個ACK(確認),確認收到序號為收到序號+1,和SYN一樣,一個FIN將占用一個序號。
服務器收到連接釋放報文,發出確認報文,ACK=1,ack=u+1,并且帶上自己的序列號seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態。
TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處于半關閉狀態,即客戶端已經沒有數據要發送了,但是服務器若發送數據,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。
客戶端收到服務器的確認請求后,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文(在這之前還需要接受服務器發送的最后的數據)。
第三次揮手
服務端發送一個FIN(結束)到客戶端,服務端關閉客戶端的連接。
服務器將最后的數據發送完畢后,就向客戶端發送連接釋放報文,FIN=1,ack=u+1,由于在半關閉狀態,服務器很可能又發送了一些數據,假定此時的序列號為seq=w,此時,服務器就進入了LAST-ACK(最后確認)狀態,等待客戶端的確認。
第四次揮手
客戶端發送ACK(確認)報文確認,并將確認的序號+1,這樣關閉完成。
客戶端收到服務器的連接釋放報文后,必須發出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP連接還沒有釋放,必須經過2??MSL(最長報文段壽命)的時間后,當客戶端撤銷相應的TCB后,才進入CLOSED狀態。
服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB后,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早一些。
思考:那么為什么是4次揮手呢?
為了確保數據能夠完成傳輸。
關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之后,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這里的ACK報文和FIN報文多數情況下都是分開發送的。
可能有人會有疑問,tcp我握手的時候為何ACK(確認)和SYN(建立連接)是一起發送。揮手的時候為什么是分開的時候發送呢?
因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉 SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步揮手。
思考:客戶端突然掛掉了怎么辦?
正常連接時,客戶端突然掛掉了,如果沒有措施處理這種情況,那么就會出現客戶端和服務器端出現長時期的空閑。解決辦法是在服務器端設置保活計時器,每當服務器收到客戶端的消息,就將計時器復位。超時時間通常設置為2小時。
若服務器超過2小時沒收到客戶的信息,他就發送探測報文段。若發送了10個探測報文段,每一個相隔75秒,還沒有響應就認為客戶端出了故障,因而終止該連接。
四、SYN(洪水)攻擊
背景
初始化連接的 SYN 超時問題Client發送SYN包給Server后掛了,Server回給Client的SYN-ACK一直沒收到Client的ACK確認,這個時候這個連接既沒建立起來,也不能算失敗。
這就需要一個超時時間讓Server將這個連接斷開,否則這個連接就會一直占用Server的SYN連接隊列中的一個位置,大量這樣的連接就會將Server的SYN連接隊列耗盡,讓正常的連接無法得到處理。
目前,Linux下默認會進行5次重發SYN-ACK包,重試的間隔時間從1s開始,下次的重試間隔時間是前一次的雙倍,5次的重試時間間隔為1s, 2s, 4s, 8s, 16s,總共31s,第5次發出后還要等32s都知道第5次也超時了,所以,總共需要 1s + 2s + 4s+ 8s+ 16s + 32s=63s,TCP才會把斷開這個連接。
由于,SYN超時需要63秒,那么就給攻擊者一個攻擊服務器的機會,攻擊者在短時間內發送大量的SYN包給Server(俗稱SYN flood攻擊),用于耗盡Server的SYN隊列。
什么是 SYN 攻擊
SYN 攻擊指的是,攻擊客戶端在短時間內偽造大量不存在的IP地址,向服務器不斷地發送SYN包,服務器回復確認包,并等待客戶的確認。由于源地址是不存在的,服務器需要不斷的重發直至超時,這些偽造的SYN包將長時間占用未連接隊列,正常的SYN請求被丟棄,導致目標系統運行緩慢,嚴重者會引起網絡堵塞甚至系統癱瘓。SYN 攻擊是一種典型的 DoS攻擊。
如何檢測 SYN 攻擊?
檢測 SYN 攻擊非常的方便,當你在服務器上看到大量的半連接狀態時,特別是源IP地址是隨機的,基本上可以斷定這是一次SYN攻擊。在 Linux/Unix 上可以使用系統自帶的netstats 命令來檢測 SYN 攻擊。
如何防御 SYN 攻擊?
SYN攻擊不能完全被阻止,除非將TCP協議重新設計。我們所做的是盡可能的減輕SYN攻擊的危害,常見的防御 SYN 攻擊的方法有如下幾種:
四、TCP和UDP的區別
我這里簡單列舉幾個,因為我還沒有研究UDP這個協議。
1、基于連接與無連接;UDP是無連接的,即發送數據之前不需要建立連接
2、TCP保證數據正確性,UDP可能丟包,TCP保證數據順序,UDP不保證。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重復,且按序到達;UDP盡最大努力交付,即不保證可靠交付Tcp通過校驗和,重傳控制,序號標識,滑動窗口、確認應答實現可靠傳輸。如丟包時的重發控制,還可以對次序亂掉的分包進行順序控制。
3、UDP具有較好的實時性,工作效率比TCP高,適用于對高速傳輸和實時性有較高的通信或廣播通信。
4、每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信。
5、TCP對系統資源要求較多,UDP對系統資源要求較少。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。