1. 程式人生 > >一次抓包定位問題的經歷

一次抓包定位問題的經歷

作為一個android開發,經常要抓包定位問題,主要用到的工具有fiddles,charles,wireshark,像http、https的抓包用前2者比較方便,但是底層的包就必須用tcpdump+wireshark了,今天學習了wireshark抓包,在此小記。

準備工作

tcpdump的主要功能就是把網路日誌記錄在一個pcap檔案內,在android上要用tcpdump,首先必須是root的手機,然後得把tcpdump安裝好,具體方法可以參考這裡。由於我的手機是aosp版本,所以自帶root和tcpdump,一個字,爽。
另外我的電腦是mac,在mac上需要裝一個wireshark來檢視抓包日誌。

抓包

連上手機之後,敲入以下三行命令就可以開始抓包,非常簡單。

adb shell   #登入手機
su          #切換Root使用者
tcpdump -p -vv -s 0 -w /sdcard/capture.pcap   #執行抓包命令,結果儲存到capture.pcap檔案中

之後我們要停止抓包,只要按下ctrl+c強行中止就可以了。此時我們可以找到capture.pcap檔案,用adb把他pull出來就好了,然後在mac上我們用wireshark開啟pcap檔案檢視日誌。我遇到的問題是websocket連不上的問題,希望能通過抓包來定位問題。

wireshark 看日誌

用wireshark開啟pcap檔案可以看到下圖,裡面用TCP、ARP、ICMP包。

enter description here

如果不過濾的話,日誌會非常多,要學會用各種方法過濾。我抓包的是一個websocket的連線,我知道web伺服器的埠是8092,所以我在過濾視窗輸入tcp.port == 8092,如下所示

enter description here

一下子只剩下十幾條日誌了,如下所示

enter description here

可以看到非常清楚的看到了websocket的連線過程。
我們知道websocket是基於http的,在http的基礎上upgrade,然後開始websocket層的資料傳輸。

三次握手(19,23,24)

從上圖可以看到,一上來就是一個熟悉的tcp三次握手(19,23,24三個包)。可以看出我們的本地埠是36498,websocket伺服器那邊的埠是8092.
首先本地向伺服器發一個SYN包(Seq=0),然後伺服器回了SYN+ACK(seq=0,ack=1),接著本地回ACK(ack=1,seq=1),成功建立了一個TCP連線。

如下包是什麼意思呢? [SYN,ACK]表示的是TCP包的flag裡,SYN,ACK為1.後面的seq=0,ack=1表示的是seq和ack的序號。

enter description here

可以看到響應包的ack=請求包的seq+1,這個沒錯。但是seq不應該是隨機的嗎?為什麼都是0開始的啊?這裡的seq都是相對值而不是絕對值。

http upgrade(25)

在TCP連線之上,我們發了一個http請求(25號包),這個請求是用來協商升級即upgrade的,包體如下

enter description here
可以看出我們發的是一個get請求,Upgrade欄位是websocket,Connection型別是Upgrade,還有host,user-agent,accept-encoding等熟悉的http頭資訊。

http回包(27)

客戶端傳送請求升級websocket的http包給伺服器,伺服器表示沒問題,回了個http包(27號),內容為 HTTP/1.1 101 Switching Protocols.此時客戶端和服務端之間的協議就升級為websocket了,之後都用websocket來交流

websocket包(29)

剛才協議升級完了,就可以用websocket通訊了,客戶端向伺服器發了個29號包。主要內容為,這是我們的auth包,向伺服器認證,是個json包。後面的內容就不能展示出來了。
{"gameId":2,"accid":25340,"rpcMethod":"/user/auth",。。。。}

這個包裡有個FIN要注意了,這是websocket層的FIN,而不是TCP層請求斷開的FIN,這個FIN的意思是伺服器,你別等了,我這個包已經完整了(因為如果包太大了就會拆分成幾個包)。

enter description here

其實我們可以看這個websocket對應的TCP包裡面的flag就清楚了,如下所示flag只有PSH和ACK並沒有FIN。

enter description here

這是websocket的FIN

enter description here

結束包(48號)

然後服務端忽然給客戶端發了個48號包,這是個FIN包。

enter description here
好了。現在回頭看看,我抓包的初衷,我以為websocket連不上,但是實際上是websocket已經連上了,然後客戶端向服務端發了個AUTH包,服務端直接把tcp連線給斷了。所以這個鍋必須是伺服器的!(真正原因,是伺服器收到客戶端的auth請求,認為客戶端版本過低,沒有給客戶端回包,而是直接斷開了tcp連線,實際上應該給客戶端發一個auth失敗的通知)。

總結

事實證明抓包還是很有用的,對定位問題很有幫助。

ref