雖然知道wireshark是抓包神器,只會大概大概用一下,還用一下下tcpdump,略懂一點BPF過濾器,也知道一點怎么用wirkshark過濾相關的報文,但是對於詳細的字段的含義,如何查看TCP的交互情況還不是非常的了解。現在,簡單分析一下。PS:這次抓包的對象是傳說中通過公安局多少多少級認證的本公司開發的交易系統,本來看到他的驗證碼傾斜的很有規律,叫的斑斑點點也不是很密集。就想寫個小程序練習一下驗證碼識別,可是我失望了,在wireshark里面居然沒有抓到任何報文,這個東西的驗證碼居然是客戶端生成的,無語。於是,抓下登錄過程的報文,看看能否破解,相關的TCP報文:crack.pcapng。關於報文分析,有一個很好的E文網站:packetlife。
廢話少說,簡單在看看TCP的協議頭:TCP協議頭
這張圖片有點過期,保留位是6位,實際的情況是,保留位的后2位已經被使用了。保留位的第5位是Congestion Window Reduced(CWR),第6位是ECN-Echo(ECN)。TCP協議的其他部分不說,先看看TCP協議的幾個不是很了解標志是什么意思。
-
CWR(Congestion Window Reduced)
簡單來說就是網絡不是很暢通了,通知對方減少阻塞窗口,發包速度發慢一點。 -
ECN(ECN-Echo)
ECN兩個作用,在TCP三次握手時表明TCP端是否支持ECN;在傳輸數據時,發送方是無法知道網絡是否暢通的,但是經過重重的路由后,路由根據網絡的情況可以知道是否阻塞,路由會設置在IP層會設置的相應的標志,即接收端發現了擁塞。CWR為發送端縮小擁塞窗口標志,用來通知發送端它已經收到了設置ECN標志,應該減慢發包速度。關於ECN的詳細描述請參考:ECN -
URG(Urgent)
這就是傳說中的帶外數據。因為TCP是沒有消息邊界的,假如有一種情況,你已經發送了一些數據,但是此時,你要發送一些數據優先處理,就可以設置這些標志,同時如果設置了這個標志,緊急指針也會設置為相應的偏移。當接受方收到URG數據時,不緩存在接收窗口,直接往上傳給上層。具體的使用可以參考TCP帶外數據。大體來說,就是,調用send
和recv
是要加上MSG_OOB
參數。同時接收方要處理SIGURG
信號。不過據說這個帶外數據在實際上,用得很少。 -
PSH(Push)
簡單來說,就是告訴對方,我發這么多數據了,你可以處理了,不用緩沖在接收窗口了,直接交數據給上層吧。如果設置了SO_NODELAY
選項,可以強制設置這個標志,如果設置了這個標志,數據就不緩沖在發送窗口那里,直接發送。
TCP報文SYN ACK的計算如下:
A -> B SYN J ACK K LEN L B -> A SYN K ACK J+L LEN M A -> B SYN J+L ACK K+M
具體看下wireshark抓到的報文:
-
- 第1幀,發送SYN J:
A -> B seq = 0, win = 8192, len = 0, MSS = 1440, WS = 4, SACK_PERM = 1
WS(Window Scale), 4表示左移動4位,原來窗口大小是16為,現在是20為,現代擴大了4倍,關於WS,這里有比較詳細的描述tcp-windows-and-window-scaling。這里比較疑惑的就是SACK_PERM這個TCP選項。SACK(Select ACKnowledgement)的目的就是當出現大量的報文丟失時增加恢復時間來用的,類似於累計ACK,就是說N多個ACK合成一個SACK。關於SACK,有兩個地方描述的比較詳細SelectiveAcknowledgements,TCP Selective Acknowledgment。 - 第2幀,發送SYN K, ACK J+1:
B -> A seq = 0, ACK = 1, Win = 14600, Len = 0, MSS = 1448, SACK_PERM = 1 WS = 128
這些含義看第1幀,win = 14600, WS = 128,可以看到這台服務器的窗口非常大,WS也很多,網絡性能應該不錯的(事實也如此)。 - 第3幀,發送SYN J+1, ACK K+1:
A -> B seq = 1, ACK = 1, win = 66608, Len = 0
這是建立TCP連接的第3次握手,這時win = 66608了,轉換為2進制有17位比16位長,因為再第1幀第2幀的交互中已經交互了各種的TCP選項,所以這次的確認不帶有TCP選項。
當這3次交互完成后,連接真正建立,只要服務端accept后,就可以接收和發送數據了。
- 第1幀,發送SYN J:
-
TCP數據傳輸
普通數據傳輸
截圖的是報文的第7幀,這個幀報文在這次抓的報文中相對有代表性點的。這個幀的報文設置了PSH
標志,而且是TCP分片傳輸的報文,因為此幀的報文是第6幀報文分片傳輸的,從ACK = 125
可以看出。傳輸數據的報文沒有什么特別可以說的:~ -
TCP終止連接的4次交換的部分是幀19到幀21(可以發現,這里的交互是有問題的)。
終止連接
- 第19幀,發送FIN J, ACK K:
A -> B seq = 2559, ack = 2361, win = 65812, len = 0
客戶端發起FIN主動關閉連接和上個報文的ACK(應該是接收完了數據,關閉SOCKET),客戶端最后應該會變成TIME_WAIT狀態。這是第一次交換。 - 第20幀,發送FIN K, ACK J+1:
B -> A seq = 2361, ack = 2560, Win = 26240, Len = 37
這次交換中,除了對客戶端的ACK外,同時發送FIN,但同時帶有37字節的數據,這37個數據不是我們期待有的。可以猜測一下,可能是服務端里面有37個字節還沒有發送,在收到FIN后,把緩存里面的數據全部發送過去。服務端如果忘記的關閉連接,會變成CLOSE_WAIT狀態。這里兩次的交換合並在一起了。 - 第21幀,發送RST, ACK K+Len:
A -> B seq = 2560, ACK = 2398, win = 0, Len = 0
主動關閉一方收到FIN,回應ACK。但是這里卻有一個不是我們期待的RST
標志。RST
標志表明往已經關閉連接發送數據,這是個錯誤。這是第四次交換。
這里的客戶端與服務端的交換是有問題的,在第20幀,收到FIN時,不應該再發送數據,這樣發送的數據很有可能收到的就是
RST
。但是這並不一定是發送數據一方的問題,很有可能是客戶端還沒有接受完數據就關閉連接了。但可以肯定的是,在客戶端或服務端某個地方肯定存在BUG。 - 第19幀,發送FIN J, ACK K:
這個就是某交易系統登錄的報文,報文涉及5次數據交互(請求-應答)。這有5次交換,第1,2次交換,很可能是交換RSA公鑰(猜的,因為報文數據有OpenSSL標志:~)。然而后面的還有3次數據交互,並不是我期待的一次交互。難道還要同步其他密鑰之類的?有空問下相關開發人員。如果是單純破解報文的話,存在比較大的難度,但是如果是DOS
攻擊的話,這應該是非常簡單的……
http://luoguochun.cn/2014/07/23/wireshark-tcp/