大家好,我是肖邦,這是我的第 11 篇原創文章。
今天要分享的是 tcpdump
,它是 Linux 系統中特別有用的網路工具,通常用於故障診斷、網路分析,功能非常的強大。
相對於其它 Linux 工具而言,tcpdump
是複雜的。當然我也不推薦你去學習它的全部,學以致用,能夠解決工作中的問題才是關鍵。
本文會從應用場景和基礎原理出發,提供豐富的實踐案例,讓你快速的掌握 tcpdump
的核心使用方法,足以應對日常工作的需求。
應用場景
在日常工作中遇到的很多網路問題都可以通過 tcpdump 優雅的解決:
1. 相信大多數同學都遇到過 SSH 連線伺服器緩慢,通過 tcpdump 抓包,可以快速定位到具體原因,一般都是因為 DNS 解析速度太慢。
2. 當我們工程師與使用者面對網路問題爭執不下時,通過 tcpdump 抓包,可以快速定位故障原因,輕鬆甩鍋,毫無壓力。
3. 當我們新開發的網路程式,沒有按照預期工作時,通過 tcpdump 收集相關資料包,從包層面分析具體原因,讓問題迎刃而解。
4. 當我們的網路程式效能比較低時,通過 tcpdump 分析資料流特徵,結合相關協議來進行網路引數優化,提高系統網路效能。
5. 當我們學習網路協議時,通過 tcpdump 抓包,分析協議格式,幫助我們更直觀、有效、快速的學習網路協議。
上述只是簡單羅列幾種常見的應用場景,而 tcpdump 在網路診斷、網路優化、協議學習方面,確實是一款非常強大的網路工具,只要存在網路問題的地方,總能看到它的身影。
熟練的運用 tcpdump
,可以幫助我們解決工作中各種網路問題,下邊我們先簡單學習下它的工作原理。
工作原理
tcpdump 是 Linux 系統中非常有用的網路工具,執行在使用者態,本質上是通過呼叫 libpcap
庫的各種 api
來實現資料包的抓取功能。
通過上圖,我們可以很直觀的看到,資料包到達網路卡後,經過資料包過濾器(BPF)篩選後,拷貝至使用者態的 tcpdump 程式,以供 tcpdump 工具進行後續的處理工作,輸出或儲存到 pcap 檔案。
資料包過濾器(BPF)主要作用,就是根據使用者輸入的過濾規則,只將使用者關心的資料包拷貝至 tcpdump,這樣能夠減少不必要的資料包拷貝,降低抓包帶來的效能損耗。
思考:這裡分享一個真實的面試題
面試官:如果某些資料包被 iptables 封禁,是否可以通過 tcpdump 抓到包?
通過上圖,我們可以很輕易的回答此問題。
因為 Linux 系統中 netfilter
是工作在協議棧階段的,tcpdump 的過濾器(BPF)工作位置在協議棧之前,所以當然是可以抓到包了!
我們理解了 tcpdump 基本原理之後,下邊直接進入實戰!
實戰:基礎用法
我們先通過幾個簡單的示例來介紹 tcpdump 基本用法。
1. 不加任何引數,預設情況下將抓取第一個非 lo 網路卡上所有的資料包
$ tcpdump
2. 抓取 eth0 網路卡上的所有資料包
$ tcpdump -i eth0
3. 抓包時指定 -n
選項,不解析主機和埠名。這個引數很關鍵,會影響抓包的效能,一般抓包時都需要指定該選項。
$ tcpdump -n -i eth0
4. 抓取指定主機 192.168.1.100
的所有資料包
$ tcpdump -ni eth0 host 192.168.1.100
5. 抓取指定主機 10.1.1.2
傳送的資料包
$ tcpdump -ni eth0 src host 10.1.1.2
6. 抓取傳送給 10.1.1.2
的所有資料包
$ tcpdump -ni eth0 dst host 10.1.1.2
7. 抓取 eth0 網路卡上發往指定主機的資料包,抓到 10 個包就停止,這個引數也比較常用
$ tcpdump -ni eth0 -c 10 dst host 192.168.1.200
8. 抓取 eth0 網路卡上所有 SSH 請求資料包,SSH 預設埠是 22
$ tcpdump -ni eth0 dst port 22
9. 抓取 eth0 網路卡上 5 個 ping 資料包
$ tcpdump -ni eth0 -c 5 icmp
10. 抓取 eth0 網路卡上所有的 arp 資料包
$ tcpdump -ni eth0 arp
11. 使用十六進位制輸出,當你想檢查資料包內容是否有問題時,十六進位制輸出會很有幫助。
$ tcpdump -ni eth0 -c 1 arp -X
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:13:31.602995 ARP, Request who-has 172.17.92.133 tell 172.17.95.253, length 28
0x0000: 0001 0800 0604 0001 eeff ffff ffff ac11 ................
0x0010: 5ffd 0000 0000 0000 ac11 5c85 _.........\.
12. 只抓取 eth0 網路卡上 IPv6 的流量
$ tcpdump -ni eth0 ip6
13. 抓取指定埠範圍的流量
$ tcpdump -ni eth0 portrange 80-9000
14. 抓取指定網段的流量
$ tcpdump -ni eth0 net 192.168.1.0/24
實戰:高階進階
tcpdump 強大的功能和靈活的策略,主要體現在過濾器(BPF)強大的表示式組合能力。
本節主要分享一些常見的所謂高階用法,希望讀者能夠舉一反三,根據自己實際需求,來靈活使用它。
1. 抓取指定客戶端訪問 ssh 的資料包
$ tcpdump -ni eth0 src 192.168.1.100 and dst port 22
2. 抓取從某個網段來,到某個網段去的流量
$ tcpdump -ni eth0 src net 192.168.1.0/16 and dst net 10.0.0.0/8 or 172.16.0.0/16
3. 抓取來自某個主機,發往非 ssh 埠的流量
$ tcpdump -ni eth0 src 10.0.2.4 and not dst port 22
4. 當構建複雜查詢的時候,你可能需要使用引號,單引號告訴 tcpdump 忽略特定的特殊字元,這裡的 ()
就是特殊符號,如果不用引號的話,就需要使用轉義字元
$ tcpdump -ni eth0 'src 10.0.2.4 and (dst port 3389 or 22)'
5. 基於包大小進行篩選,如果你正在檢視特定的包大小,可以使用這個引數
小於等於 64 位元組:
$ tcpdump -ni less 64
大於等於 64 位元組:
$ tcpdump -ni eth0 greater 64
等於 64 位元組:
$ tcpdump -ni eth0 length == 64
6. 過濾 TCP 特殊標記的資料包
抓取某主機傳送的 RST
資料包:
$ tcpdump -ni eth0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-rst) != 0'
抓取某主機傳送的 SYN
資料包:
$ tcpdump -ni eth0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-syn) != 0'
抓取某主機傳送的 FIN
資料包:
$ tcpdump -ni eth0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-fin) != 0'
抓取 TCP 連線中的 SYN
或 FIN
包
$ tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0'
7. 抓取所有非 ping 型別的 ICMP
包
$ tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply'
8. 抓取埠是 80,網路層協議為 IPv4, 並且含有資料,而不是 SYN、FIN 以及 ACK 等不含資料的資料包
$ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
解釋一下這個複雜的表示式,具體含義就是,整個 IP 資料包長度減去 IP 頭長度,再減去 TCP 頭的長度,結果不為 0,就表示資料包有 data
,如果還不是很理解,需要自行補一下 tcp/ip
協議
9. 抓取 HTTP 報文,0x4754
是 GET
前兩字元的值,0x4854
是 HTTP
前兩個字元的值
$ tcpdump -ni eth0 'tcp[20:2]=0x4745 or tcp[20:2]=0x4854'
常用選項
通過上述的實戰案例,相信大家已經掌握的 tcpdump
基本用法,在這裡來詳細總結一下常用的選項引數。
(一)基礎選項
-i
:指定介面-D
:列出可用於抓包的介面-s
:指定資料包抓取的長度-c
:指定要抓取的資料包的數量-w
:將抓包資料儲存在檔案中-r
:從檔案中讀取資料-C
:指定檔案大小,與-w
配合使用-F
:從檔案中讀取抓包的表示式-n
:不解析主機和埠號,這個引數很重要,一般都需要加上-P
:指定要抓取的包是流入還是流出的包,可以指定的值in
、out
、inout
(二)輸出選項
-e
:輸出資訊中包含資料鏈路層頭部資訊-t
:顯示時間戳,tttt
顯示更詳細的時間-X
:顯示十六進位制格式-v
:顯示詳細的報文資訊,嘗試-vvv
,v
越多顯示越詳細
過濾表示式
tcpdump 強大的功能和靈活的策略,主要體現在過濾器(BPF)強大的表示式組合能力。
(一)操作物件
表示式中可以操作的物件有如下幾種:
type
,表示物件的型別,比如:host
、net
、port
、portrange
,如果不指定 type 的話,預設是 hostdir
:表示傳輸的方向,可取的方式為:src
、dst
。proto
:表示協議,可選的協議有:ether
、ip
、ip6
、arp
、icmp
、tcp
、udp
。
(二)條件組合
表達物件之間還可以通過關鍵字 and
、or
、not
進行連線,組成功能更強大的表示式。
or
:表示或操作and
:表示與操作not
:表示非操作
建議看到這裡後,再回頭去看實戰篇章的示例,相信必定會有更深的理解。如果是這樣,那就達到了我預期的效果了!
經驗
到這裡就不再加新知識點了,分享一些工作中總結的經驗:
1. 我們要知道 tcpdump
不是萬能藥,並不能解決所有的網路問題。
2. 在高流量場景下,抓包可能會影響系統效能,如果是在生產環境,請謹慎使用!
3. 在高流量場景下,tcpdump
並不適合做流量統計,如果需要,可以使用交換機映象的方式去分析統計。
4. 在 Linux 上使用 tcpdump
抓包,結合 wireshark
工具進行資料分析,能事半功倍。
5. 抓包時,儘可能不要使用 any
介面來抓包。
6. 抓包時,儘可能指定詳細的資料包過濾表示式,減少無用資料包的拷貝。
7. 抓包時,儘量指定 -n
選項,減少解析主機和埠帶來的效能開銷。
最後
通過上述內容,我們知道 tcpdump 是一款功能強大的故障診斷、網路分析工具。在我們的日常工作中,遇到的網路問題總是能夠通過 tcpdump 來解決。
不過 tcpdump 相對於其它 Linux 命令來說,會複雜很多,但鑑於它強大功能的誘惑力,我們多花一些時間是值得的。要想很好地掌握 tcpdump,需要對網路報文(TCP/IP
協議)有一定的瞭解。
當然,對於簡單的使用來說,只要有網路基礎概念就行,掌握了 tcpdump 常用方法,就足以應付工作中大部分網路相關的疑難雜症了。
推薦閱讀
推薦閱讀:
- 寫給 Linux 初學者的一封信
- 全網最詳盡的負載均衡原理圖解
- 上古神器 sed 教程詳解,小白也能看的懂
- Linux 三劍客之 grep 教程詳解
- Linux 檔案搜尋神器 find 實戰詳解,建議收藏!
本次分享就到這裡了,謝謝大家的閱讀,我是肖邦。關注我的公眾號「程式設計修養」,大量的乾貨文章等你來!
公眾號後臺回覆「1024」有驚喜!
歡迎各位老鐵,加肖邦的個人微信,技術交流!!