你們好,我是肖邦,這是個人第 11 篇原創文章。php
今天要分享的是 tcpdump
,它是 Linux 系統中特別有用的網絡工具,一般用於故障診斷、網絡分析,功能很是的強大。面試
相對於其它 Linux 工具而言,tcpdump
是複雜的。固然我也不推薦你去學習它的所有,學以至用,可以解決工做中的問題纔是關鍵。編程
本文會從應用場景和基礎原理出發,提供豐富的實踐案例,讓你快速的掌握 tcpdump
的核心使用方法,足以應對平常工做的需求。api
在平常工做中遇到的不少網絡問題均可以經過 tcpdump 優雅的解決:ruby
1. 相信大多數同窗都遇到過 SSH 鏈接服務器緩慢,經過 tcpdump 抓包,能夠快速定位到具體緣由,通常都是由於 DNS 解析速度太慢。bash
2. 當咱們工程師與用戶面對網絡問題爭執不下時,經過 tcpdump 抓包,能夠快速定位故障緣由,輕鬆甩鍋,毫無壓力。服務器
3. 當咱們新開發的網絡程序,沒有按照預期工做時,經過 tcpdump 收集相關數據包,從包層面分析具體緣由,讓問題迎刃而解。微信
4. 當咱們的網絡程序性能比較低時,經過 tcpdump 分析數據流特徵,結合相關協議來進行網絡參數優化,提升系統網絡性能。網絡
5. 當咱們學習網絡協議時,經過 tcpdump 抓包,分析協議格式,幫助咱們更直觀、有效、快速的學習網絡協議。app
上述只是簡單羅列幾種常見的應用場景,而 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 的話,默認是 host dir
:表示傳輸的方向,可取的方式爲: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 經常使用方法,就足以應付工做中大部分網絡相關的疑難雜症了。
推薦閱讀:
本次分享就到這裏了,謝謝你們的閱讀,我是肖邦。關注個人公衆號「編程修養」,大量的乾貨文章等你來!
公衆號後臺回覆「1024」有驚喜!
歡迎各位老鐵,加肖邦的我的微信,技術交流!!