使用tshark監(jiān)視和檢查網(wǎng)絡(luò)流量
譯文大多數(shù)人恐怕已經(jīng)聽說過Wireshark,這是一款人氣非常旺、功能非常強(qiáng)的網(wǎng)絡(luò)協(xié)議分析工具。但是大家可能不知道的是,還有一個(gè)控制臺版本的Wireshark,名叫tshark。tshark的兩個(gè)主要優(yōu)點(diǎn)就是,它可以用在腳本中,也可以通過SSH連接用在遠(yuǎn)程計(jì)算機(jī)上。主要缺點(diǎn)就是,它沒有圖形用戶界面(GUI),如果你要搜索大量的網(wǎng)絡(luò)數(shù)據(jù),要是有GUI,確實(shí)方便得很。
你可以從官方網(wǎng)站獲得tshark、自行編譯,也可以從你的Linux發(fā)行版獲得它(它作為預(yù)先編譯的程序包)。第二種方法更快捷、更簡單。想把tshark安裝到Debian 7系統(tǒng)上,你就要以根用戶身份,運(yùn)行下列命令:
# apt-get install tshark Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: libc-ares2 libcap2-bin libpam-cap libsmi2ldbl libwireshark-data libwireshark2 libwiretap2 libwsutil2 wireshark-common Suggested packages: libcap-dev snmp-mibs-downloader wireshark-doc The following NEW packages will be installed: libc-ares2 libcap2-bin libpam-cap libsmi2ldbl libwireshark-data libwireshark2 libwiretap2 libwsutil2 tshark wireshark-common 0 upgraded, 10 newly installed, 0 to remove and 0 not upgraded. Need to get 15.6 MB of archives. After this operation, 65.7 MB of additional disk space will be used. Do you want to continue [Y/n]? Y ...
想查明tshark是否已正確安裝,并查明其版本,請執(zhí)行這個(gè)命令:
$ tshark -v TShark 1.8.2 ...
注意:本文假設(shè)你已經(jīng)很熟悉網(wǎng)絡(luò)數(shù)據(jù)、TCP/IP和數(shù)據(jù)包捕獲,還可能熟悉Wireshark,并假設(shè)你想了解關(guān)于tshark的更多信息。
tshark簡介
凡是Wireshark具有的功能,tshark都有,前提條件是它不需要GUI。它還可以用來替代tcpdump,tcpdump過去是網(wǎng)絡(luò)數(shù)據(jù)捕獲方面的行業(yè)標(biāo)準(zhǔn)。除了捕獲方面外(兩種工具在這方面功能相當(dāng)),tshark的功能比tcpdump來得強(qiáng)大;因此,如果你只想學(xué)用一種工具,tshark應(yīng)該是你的選擇。
正如你設(shè)想的那樣,tshark有好多命令行選項(xiàng)。請參閱其參考手冊頁,即可了解完整列表。
使用tshark捕獲網(wǎng)絡(luò)流量
你應(yīng)該運(yùn)行的頭一個(gè)命令是sudo tshark –D,即可列出可用網(wǎng)絡(luò)接口:
$ sudo tshark -D 1. eth0 2. nflog (Linux netfilter log (NFLOG) interface) 3. any (Pseudo-device that captures on all interfaces) 4. lo
如果你以普通用戶的身份運(yùn)行tshark,極有可能會得到下列輸出結(jié)果,因?yàn)槠胀ㄓ脩魺o權(quán)直接訪問網(wǎng)絡(luò)接口設(shè)備:
$ tshark -D tshark: There are no interfaces on which a capture can be done
想捕獲數(shù)據(jù),最簡單的辦法就是運(yùn)行不帶任何參數(shù)的tshark,這會在屏幕上顯示所有數(shù)據(jù)。只要按Ctrl-C組合鍵,就可以停止數(shù)據(jù)捕獲。
在忙碌的網(wǎng)絡(luò)上,輸出結(jié)果會飛快地滾動顯示,所以一點(diǎn)也沒有幫助。比較舊的計(jì)算機(jī)可能跟不上忙碌的網(wǎng)絡(luò),所以tshark和tcpdump之類的程序過去常常丟失網(wǎng)絡(luò)數(shù)據(jù)包。由于現(xiàn)代計(jì)算機(jī)功能相當(dāng)強(qiáng)大,這不再是個(gè)問題。
使用文件,保存和閱讀網(wǎng)絡(luò)數(shù)據(jù)
最有用的一個(gè)命令行參數(shù)是-w,后面跟以文件名。這個(gè)參數(shù)讓你可以將網(wǎng)絡(luò)數(shù)據(jù)保存到文件中,以便以后處理它。下面這個(gè)tshark命令可捕獲500個(gè)網(wǎng)絡(luò)數(shù)據(jù)包(-c 500),并將它們保存到名為LJ.pcap的文件(-w LJ.pcap)。
$ tshark -c 500 -w LJ.pcap
第二有用的參數(shù)是-r。后面跟以有效的文件名時(shí),它讓你可以閱讀和處理之前捕獲的含有網(wǎng)絡(luò)數(shù)據(jù)的文件。
捕獲過濾器
捕獲過濾器是數(shù)據(jù)捕獲過程中所應(yīng)用的過濾器;因此,它們讓tshark丟棄不符合過濾器標(biāo)準(zhǔn)的網(wǎng)絡(luò)流量,避免生成龐大的捕獲文件。這可以使用-f命令行參數(shù)(后面跟以雙引號里面的過濾器)來實(shí)現(xiàn)。
捕獲過濾器中使用的最重要的與TCP相關(guān)的字段名有:tcp.port(用于過濾源頭或目的地TCP端口)、tcp.srcport(用于檢查TCP源頭端口)以及tcp.dstport(用于檢查目的地端口)。
通常來說,數(shù)據(jù)捕獲后應(yīng)用過濾器被認(rèn)為比在捕獲過程中進(jìn)行過濾來得更實(shí)用、功能更廣泛,因?yàn)榇蠖鄶?shù)時(shí)候,你并不事先知道想要檢查什么。然而,如果你確實(shí)知道要做什么,使用捕獲過濾器就能為你節(jié)省時(shí)間和磁盤空間,這也是使用捕獲過濾器的主要原因。
切記:過濾器字符串始終應(yīng)該使用小寫字母。
顯示過濾器
顯示過濾器是數(shù)據(jù)包捕獲后所應(yīng)用的過濾器;因此,它們只是“隱藏”網(wǎng)絡(luò)流量,而不實(shí)際刪除。你總是可以去除顯示過濾器的影響,找回你的所有數(shù)據(jù)。
顯示過濾器支持比較運(yùn)算符和邏輯運(yùn)算符。http.response.code == 404 && ip.addr == 192.168.10.1顯示過濾器顯示了來自192.168.10.1 IP地址或前往192.168.10.1 IP地址的流量,該流量里面還有404 (Not Found) HTTP響應(yīng)代碼。!bootp && !ip過濾器將BOOTP和IP流量排除在輸出結(jié)果之外。eth.addr == 01:23:45:67:89:ab && tcp.port == 25過濾器顯示了前往或來自擁有01:23:45:67:89:ab MAC地址的網(wǎng)絡(luò)設(shè)備的流量,使用TCP端口25用于入站或出站連接。
定義規(guī)則時(shí),要切記:ip.addr != 192.168.1.5表達(dá)式并不意味著沒有一個(gè)ip.addr字段含有192.168.1.5 IP地址。它意味著,其中一個(gè)ip.addr字段不應(yīng)該含有192.168.1.5 IP地址!因此,另一個(gè)ip.addr字段值可能相當(dāng)于192.168.1.5!你可以看成是“有一個(gè)不是192.168.1.5的ip.addr字段”。正確的表達(dá)方式是,鍵入!(ip.addr == 192.168.1.5)。這是顯示過濾器方面的一個(gè)常見誤解。
還要牢記:如果你想跟蹤局域網(wǎng)上的某一個(gè)機(jī)器,MAC地址確實(shí)很有用,因?yàn)槿绻摍C(jī)器使用DHCP,其IP地址就會變化,但是MAC地址變化的話比較困難。
如果使用得當(dāng),顯示過濾器是極其有用的工具,不過你仍得自行解讀結(jié)果,找到問題,并考慮可能的解決辦法。建議訪問顯示過濾器參考網(wǎng)站:http://www.wireshark.org/docs/dfref/t/tcp.html,即可關(guān)注與TCP有關(guān)的流量。想查看與UDP流量有關(guān)的所有可用字段名,請?jiān)L問http://www.wireshark.org/docs/dfref/u/udp.html。
導(dǎo)出數(shù)據(jù)
設(shè)想一下:你想提取幀數(shù)、幀相對時(shí)間、源頭IP地址、目的地IP地址、數(shù)據(jù)包協(xié)議,以及來自之前捕獲的網(wǎng)絡(luò)流量的網(wǎng)絡(luò)數(shù)據(jù)包的長度。下面這個(gè)tshark命令就能為你做到這一切:
$ tshark -r login.tcpdump -T fields -e frame.number -e ↪frame.time_relative -e ip.src -e ip.dst -e ↪frame.protocols -e frame.len -E header=y -E ↪quote=n -E occurrence=f
-E header=y選項(xiàng)指令tshark先輸出報(bào)頭行。-E quote=n規(guī)定tshark不包括引號里面的數(shù)據(jù),而-E occurrence=f指令tshark使用有多個(gè)occurrence的字段的頭一個(gè)occurrence。
以明文格式輸出意味著,你很容易以UNIX方式來處理它。下面這個(gè)命令使用來自ip.src字段的輸出,顯示了十個(gè)最常見的IP地址:
$ tshark -r ~/netData.pcap -T fields -e ip.src | sort ↪| sed '/^\s*$/d' | uniq -c | sort -rn ↪| awk {'print $2 " " $1'} | head
#p#
使用tshark的兩個(gè)Python腳本
現(xiàn)在,我們不妨看一下讀取tshark文本輸出并處理它的兩個(gè)Python腳本。我無法想象用Wireshark之類的GUI應(yīng)用程序來處理同一項(xiàng)任務(wù)!
代碼片段1列出了檢查IP地址有效性的***個(gè)腳本的完整Python代碼。
代碼片段1. checkIP.py
# 編程員:Mihalis Tsoukalos # 日 期:Tuesday 28 October 2014 import socket import sys import re def valid_ip(address): try: socket.inet_aton(address) return True except: return False # IP地址計(jì)數(shù)器 total = 0 valid = 0 invalid = 0 # 逐行讀取來自stdin的文件 for line in sys.stdin: line = line.rstrip('\n') if valid_ip(line): valid = valid + 1 # 輸出"The IP is valid!" else: # 輸出"The IP is not valid!" invalid = invalid + 1 total = total + 1 # 顯示已檢查的IP地址總數(shù) print "Total number of IPs checked:", total print "Valid IPs found:", valid print "Invalid IPs found:", invalid checkIP.py Python腳本的目的僅僅是找到無效的IP地址,它表明網(wǎng)絡(luò)數(shù)據(jù)已經(jīng)是用tshark捕獲的。你可以按如下方式使用它: $ tshark -r ~/networkData.pcap -T fields -e ip.src ↪| python checkIP.py Total number of IPs checked: 1000 Valid IPs found: 896 Invalid IPs found: 104
代碼片段2顯示了第二個(gè)Python腳本(storeMongo.py)的完整代碼。
代碼片段2. store Mongo.py
# 編程員:Mihalis Tsoukalos # 日 期:Tuesday 28 October 2014 # # 描述:該P(yáng)ython腳本讀取來自tshark的輸入,對其解析后,存儲到MongoDB數(shù)據(jù)庫 import sys import pymongo import re # 編寫的BSON文檔的數(shù)量 total = 0 # 打開MongoDB連接 connMongo = pymongo.Connection('mongodb://localhost:27017') # 連接至名為LJ(Linux日志)的數(shù)據(jù)庫 db = connMongo.LJ # 選擇保存網(wǎng)絡(luò)數(shù)據(jù)包的組合 traffic = db.netdata # 逐行讀取來自stdin的文件 for line in sys.stdin: line = line.rstrip('\n') parsed = line.split("\t") total = total + 1 # 構(gòu)建“待插入的文檔” netpacket = { 'framenumber': parsed[0], 'sourceIP': parsed[1], 'destIP': parsed[2], 'framelength': parsed[3], 'IPlength': parsed[4] } # 保存它! net_id = traffic.insert(netpacket) connMongo.close() # 顯示編寫的BSON文檔的總數(shù) print "Total number of documents stored: ", total
代碼片段2中顯示的Python腳本將網(wǎng)絡(luò)數(shù)據(jù)插入到MongoDB數(shù)據(jù)庫中,以便進(jìn)一步處理和查詢。你想使用什么數(shù)據(jù)庫,隨你喜歡。我使用MongoDB的主要原因是,因?yàn)槲蚁矚g它在存儲可能含有一些不規(guī)則記錄(字段丟失的記錄)的結(jié)構(gòu)化數(shù)據(jù)時(shí)具有的那種靈活性。
Python腳本的名稱是storeMongo.py,它假設(shè)網(wǎng)絡(luò)數(shù)據(jù)已經(jīng)使用tshark或tcpdump捕獲。下一個(gè)外殼命令運(yùn)行Python腳本,其輸入來自tshark:
$ tshark -r ~/var/test.pcap -T fields -e frame.number ↪-e ip.src -e ip.dst -e frame.len -e ↪ip.len -E header=n -E quote=n -E occurrence=f ↪| python storeMongo.py Total number of documents stored: 500
tshark命令的文本輸出類似如下:
5 yy.xx.zz.189 yyy.74.xxx.253 66 52 6 197.224.xxx.145 yyy.74.xxx.253 86 72 7 109.xxx.yyy.253 zzz.224.xxx.145 114 100 8 197.xxx.zzz.145 zzz.xxx.xxx.253 86 72 9 109.zzz.193.yyy 197.224.zzz.145 114 100
目前,所有數(shù)值都以字符串的形式存儲起來,不過你很容易將它們轉(zhuǎn)換成數(shù)字,如果你想這么做的話。下面這個(gè)命令將來自IPlength列的所有字符串值轉(zhuǎn)換成相應(yīng)的整數(shù)值:
> db.netdata.find({IPlength : {$exists : true}}).forEach( ↪function(obj) { obj.IPlength = new NumberInt( ↪obj.IPlength ); db.netdata.save(obj); } );
現(xiàn)在,你可以開始查詢MongoDB數(shù)據(jù)庫了。下列命令找到含有某個(gè)目的地IP地址的所有“記錄”(用NoSQL術(shù)語來說就是文檔):
> use LJ switched to db LJ > db.netdata.find({ "destIP": "192.168.1.12" }) ... >
下一個(gè)命令找到frame.len值小于70的所有項(xiàng):
> use LJ switched to db LJ > db.netdata.find({ "framelength": {"$lt" : "70" }}) ... >
下一個(gè)命令找到IPlength值大于100、小于200的所有項(xiàng):
> use LJ switched to db LJ > db.netdata.find({ "IPlength": {"$lt" : "200", "$gt": "100" }}) ... >
你應(yīng)該記住的不是實(shí)際命令,而是這一點(diǎn):你可以使用自己喜歡的查詢語言查詢所選擇的數(shù)據(jù)庫,并找到有用的信息,不需要重新運(yùn)行tshark、再次解析網(wǎng)絡(luò)數(shù)據(jù)。
你在測試查詢后,可以將它們作為計(jì)劃任務(wù)(cron job)來運(yùn)行。就是這么簡單!
#p#
使用tshark分析Nmap ping掃描
下一步,不妨分析由Nmap在執(zhí)行ping掃描后生成的網(wǎng)絡(luò)流量。ping掃描的目的只是查明IP地址是否正常(up)而已。簡而言之,對ping掃描中的Nmap來說重要的不是已收到數(shù)據(jù)包的實(shí)際數(shù)據(jù),而是響應(yīng)數(shù)據(jù)包確實(shí)存在。局域網(wǎng)里面的Nmap ping掃描使用ARP協(xié)議,而局域網(wǎng)外面的主機(jī)使用ICMP協(xié)議來掃描。已執(zhí)行的掃描ping的是局域網(wǎng)外面的IP地址。
下面這個(gè)Nmap命令掃描64個(gè)IP地址,從2.x.yy.1到2.x.yy.64:
# nmap -sP 2.x.yy.1-64 Starting Nmap 6.00 ( http://nmap.org ) at 2014-10-29 11:55 EET Nmap scan report for ppp-4.home.SOMEisp.gr (2.x.yy.4) Host is up (0.067s latency). Nmap scan report for ppp-6.home.SOMEisp.gr (2.x.yy.6) Host is up (0.084s latency). ... Nmap scan report for ppp-64.home.SOMEisp.gr (2.x.yy.64) Host is up (0.059s latency). Nmap done: 64 IP addresses (35 hosts up) scanned in 3.10 seconds
結(jié)果顯示,在執(zhí)行時(shí)段,只有35個(gè)主機(jī)正常,或者確切地說,只有35個(gè)主機(jī)回應(yīng)了Nmap掃描。Nmap還計(jì)算了往返程時(shí)延(延遲)。這相當(dāng)準(zhǔn)確地估計(jì)了由Nmap發(fā)送的初始數(shù)據(jù)包傳輸?shù)侥繕?biāo)設(shè)備所需要的時(shí)間,加上響應(yīng)數(shù)據(jù)包返回到Nmap所需要的時(shí)間。
下面這個(gè)tshark命令用于捕獲,可以按組合鍵Ctrl-C來終止:
# tshark -w nmap.pcap Running as user "root" and group "root". This could be dangerous. Capturing on eth0 2587 ^C 18 packets dropped # ls -l nmap.pcap -rw------- 1 root root 349036 Oct 29 11:55 nmap.pcap
現(xiàn)在,不妨使用tshark,分析已生成的流量。下面這個(gè)命令搜索前往或來自2.x.yy.6 IP地址的流量:
$ tshark -r nmap.pcap -R "ip.src == 2.x.yy.6 || ip.dst == 2.x.yy.6" 712 3.237125000 109.zz.yyy.253 -> 2.x.yy.6 ↪ICMP 42 Echo (ping) request id=0xa690, seq=0/0, ttl=54 1420 5.239804000 109.zz.yyy.253 -> 2.x.yy.6 ↪ICMP 42 Echo (ping) request id=0x699a, seq=0/0, ttl=49 1432 5.240111000 109.zz.yyy.253 -> 2.x.yy.6 ↪TCP 58 41242 > https [SYN] Seq=0 Win=1024 Len=0 MSS=1460 1441 5.296861000 2.x.yy.6 -> 109.zz.yyy.253 ICMP 60 ↪Timestamp reply id=0x0549, seq=0/0, ttl=57
正如你所見,只要存在來自2.x.yy.6的響應(yīng)數(shù)據(jù)包(1441),就足以讓Nmap認(rèn)為該主機(jī)是正常的;因此,不需要對該IP進(jìn)行任何的額外測試了。
現(xiàn)在,不妨看一下被認(rèn)為宕機(jī)(down)的IP地址的流量:
$ tshark -r nmap.pcap -R "ip.src == 2.x.yy.2 || ip.dst == 2.x.yy.2" 708 3.236922000 109.zz.yyy.253 -> 2.x.yy.2 ↪ICMP 42 Echo (ping) request id=0xb194, seq=0/0, ttl=59 1407 5.237255000 109.zz.yyy.253 -> 2.x.yy.2 ↪ICMP 42 Echo (ping) request id=0x24ed, seq=0/0, ttl=47 1410 5.237358000 109.zz.yyy.253 -> 2.x.yy.2 ↪TCP 58 41242 > https [SYN] Seq=0 Win=1024 Len=0 MSS=1460 1413 5.237448000 109.zz.yyy.253 -> 2.x.yy.2 ↪TCP 54 41242 > http [ACK] Seq=1 Ack=1 Win=1024 Len=0 1416 5.237533000 109.zz.yyy.253 -> 2.x.yy.2 ↪ICMP 54 Timestamp request id=0xf7af, seq=0/0, ttl=51 1463 5.348871000 109.zz.yyy.253 -> 2.x.yy.2 ↪ICMP 54 Timestamp request id=0x9d7e, seq=0/0, ttl=39 1465 5.349006000 109.zz.yyy.253 -> 2.x.yy.2 ↪TCP 54 41243 > http [ACK] Seq=1 Ack=1 Win=1024 Len=0 1467 5.349106000 109.zz.yyy.253 -> 2.x.yy.2 ↪TCP 58 41243 > https [SYN] Seq=0 Win=1024 Len=0 MSS=1460
由于ICMP數(shù)據(jù)包沒有收到回應(yīng),Nmap發(fā)送HTTP數(shù)據(jù)包和HTTPS數(shù)據(jù)包,對2.x.yy.2 IP地址進(jìn)行更多次嘗試,可是依然沒有一次成功。之所以出現(xiàn)這種情況,是因?yàn)镹map給標(biāo)準(zhǔn)的ping(ICMP協(xié)議)增添了智能:萬一ICMP請求由于某種原因而被阻擋,試一試幾個(gè)常見的TCP端口。
借助下面這個(gè)命令,就能找到已發(fā)送ICMP數(shù)據(jù)包的總數(shù):
$ tshark -r nmap.pcap -R "icmp" | grep "2.x" | wc -l 233
顯示特定協(xié)議的統(tǒng)計(jì)數(shù)字
tshark讓你可以顯示關(guān)于某個(gè)特定協(xié)議的有用的統(tǒng)計(jì)數(shù)字。下面這個(gè)命令顯示了關(guān)于HTTP協(xié)議的統(tǒng)計(jì)數(shù)字,使用含有網(wǎng)絡(luò)數(shù)據(jù)的現(xiàn)有文件:
$ tshark -q -r http.pcap -R http -z http,tree ===================================================== HTTP/Packet Counter value rate percent ----------------------------------------------------- Total HTTP Packets 118 0.017749 HTTP Request Packets 66 0.009928 55.93% GET 66 0.009928 100.00% HTTP Response Packets 52 0.007822 44.07% ???: broken 0 0.000000 0.00% 1xx: Informational 0 0.000000 0.00% 2xx: Success 51 0.007671 98.08% 200 OK 51 0.007671 100.00% 3xx: Redirection 0 0.000000 0.00% 4xx: Client Error 1 0.000150 1.92% 404 Not Found 1 0.000150 100.00% 5xx: Server Error 0 0.000000 0.00% Other HTTP Packets 0 0.000000 0.00% =====================================================
所有工作由-z選項(xiàng)和-q選項(xiàng)來完成,前者用于計(jì)算統(tǒng)計(jì)數(shù)字,后者用于禁止根據(jù)每個(gè)數(shù)據(jù)包輸出信息。-R選項(xiàng)在進(jìn)行其他任何處理之前丟棄了不匹配指定過濾器的所有數(shù)據(jù)包。
下面是另一個(gè)有用的命令,顯示了協(xié)議層次結(jié)構(gòu)方面的統(tǒng)計(jì)數(shù)字:
$ tshark -nr ~/var/http.pcap -qz "io,phs"
你本人可以試一試,看看輸出結(jié)果!
總結(jié)
如果你深入了解了顯示過濾器,并且通曉TCP/IP和網(wǎng)絡(luò),那么借助tshark或Wireshark,與網(wǎng)絡(luò)有關(guān)的問題將不再是問題。
掌握tshark需要花點(diǎn)時(shí)間,不過我認(rèn)為這個(gè)時(shí)間值得一花。
參考資源
tshark:http://www.wireshark.org/docs/man-pages/tshark.html
Wireshark:http://www.wireshark.org
顯示過濾器參考網(wǎng)站:http://www.wireshark.org/docs/dfref