1. Wireshark与tcpdump介绍
Wireshark是一个网络协议检测工具,支持Windows平台和Unix平台,我一般只在Windows平台下使用Wireshark,如果是Linux的话,我直接用tcpdump了,因为我工作环境中的Linux一般只有字符界面,且一般而言Linux都自带的tcpdump,或者用tcpdump抓包以后用Wireshark打开分析。
在Windows平台下,Wireshark通过WinPcap进行抓包,封装的很好,使用起来很方便,可以很容易的制定抓包过滤器或者显示过滤器,具体在下面介绍。Wireshark是一个免费的工具,只要google一下就能很容易找到下载的地方。
tcpdump是基于Unix系统的命令行式的数据包嗅探工具。如果要使用tcpdump抓取其他主机MAC地址的数据包,必须开启网卡混杂模式,所谓混杂模式,用最简单的语言就是让网卡抓取任何经过它的数据包,不管这个数据包是不是发给它或者是它发出的,点击【http://en.wikipedia.org/wiki/Promiscuous_mode】获取更多有关混杂模式的资料。一般而言,Unix不会让普通用户设置混杂模式,因为这样可以看到别人的信息,比如telnet的用户名和密码,这样会引起一些安全上的问题,所以只有root用户可以开启混杂模式,开启混杂模式的命令是:ifconfig eth0 promisc, eth0是你要打开混杂模式的网卡。肯定有人要问如果在windows下要不要打开混杂模式,windows下网卡没有什么混杂模式不混杂模式,在于应用程序本身,如使用Wireshark抓包的时候可以通过设置为在混杂模式下抓包(这就是为什么该死的ARP欺骗病毒可以猖狂的原因)。tcpdump当然也可以指定抓包过滤器,而且其过滤器语言非常著名,叫做Berkeley包过滤,简称BPF语言。
2. 简单的例子
我们通过访问www.google.com.hk这个网址来看看抓包结果。
2.1 tcpdump
前面说过一般情况下Linux都自带了tcpdump,但是如果发生了小概率事件,发现没有tcpdump的话,可以到http://www.tcpdump.org下载源代码,编译安装。
使用root用户登录,运行tcpdump命令就可以开始抓包。这里说明一下,如果使用SSH登录到远程Linux,然后直接运行tcpdump,会发现抓到大量的数据包,速度快的都看不清楚,这是因为tcpdump抓到的包发送给远程的终端显示,同时又抓了这个包,再显示,再抓取,造成了循环抓取。当然,这样抓包没有任何意义,除了证明你的网络是通的。
因为没有打开网卡的混杂模式,所以如果本机没有任何进程访问网络,是抓不到包的,如果在字符界面下,用wgethttp://www.google.com.hk 访问网址,如果有GUI,可以打开firefox浏览器访问http://www.google.com.hk。
默认情况下,tcpdump会选择第一块网卡,也就是eth0,进行抓包,每行显示一个抓取的数据包,如:
0.003183 192.168.21.137 72.14.203.147 TCP 38039 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=36941509 TSER=0 WS=6
0.011707 72.14.203.147 192.168.21.137 TCP http > 38039 [SYN, ACK] Seq=0 Ack=1 Win=64240 Len=0 MSS=1460
0.011770 192.168.21.137 72.14.203.147 TCP 38039 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
以上三个数据包就是著名的TCP三次握手的数据包,其中38039是客户端的TCP端口,http的默认端口是80,如果tcpdump在/etc/services中发现端口对应的服务名称,那么会自动的转为名字,所以这里会显示为http。表示客户端的38039端口和服务器端的http端口进行TCP三次握手。
前面提到tcpdump默认选择第一块网卡进行抓包,我们可以使用-i参数指定通过哪一个网卡抓包,如(#表示我输入的命令,Linux下root用户的提示符就是#):
# tcpdump –i eth1
或者
#tcpdump –i any
如果想知道我们可以通过哪几个网卡抓包,可以使用-D参数,如:
# tcpdump –D
1.eth0
2.any
3.lo
因为我的机器上只有一个网卡,因此只有eth0,如果有多块网卡活动的话,会有eth1,eth2依次下去。any的意思是通过任意一块网卡进行抓包,lo是回环接口。(关于TCP三次握手和回环接口等网络问题,请参考《TCP/IP协议详解》)。
默认情况下,tcpdump抓包结果显示在屏幕(严格点,专业点应该说是标准输出)上,显然这不利于进一步的数据分析,因此我们需要将抓包结果存放在文件中。可是使用-w命令将结果保存在文件中,如:
#tcpdump –w google.cap
这句命令将抓包结果存放在google.cap文件中,结束以后可以用Wireshark打开查看。同事,tcpdump出了抓包,还可以使用-r参数制定抓包数据文件,结合过滤器对抓包数据分析,如:
#tcpdump –r google.cap http
这句命令的意思是让tcpdump读取google.cap文件,把其中http协议的数据包都给过滤出来。关于过滤器在下面详细介绍。
2.2 Wireshark
我在windows系统中使用Wireshark的,首先熟悉一下界面,图1是使用Wireshark打开google.cap文件的界面,
图1 Wireshark界面
图1中标注出三快区域,R1区域用来显示简单的数据包信息,我们用tcpdump抓包的时候,默认情况下也是显示成这样的;R2区域用来显示选中的数据包的详细信息,细心一点会发现他是按照TCP/IP四层结构显示的,第一行是数据链路层的信息,第二行是网络层信息(IP协议),第三行是传输层信息(TCP协议),第四行是应用层信息(HTTP协议),可以展开每一行用来观察具体的内容;R3区域是用来显示此数据包的真实面目。我们在R1和R2区域看到的信息都是Wireshark整理以后给我们看的,抓包的真实数据实际上是一堆二进制序列,用ultraedit打开google.cap文件可以看到就是一些数字,如图2所示。
图2 抓包文件长的样子
使用Wireshark抓包非常容易,直接点击按钮(工具栏第三个按钮)(工具栏第一个按钮)就开始抓包了,会发现只要一点击这个按钮,立刻就显示抓到包了,这是因为Wireshark默认在混杂模式下抓包,只要经过网卡的数据包都抓取下来(当然这台机器要连在网络中,如果没有数据流过当然没有包可抓),点击按钮停止此次抓包。
如果机器上安装了多块网卡,Wireshark默认选择第一张网卡抓包,如果等抓包完成了,这是发现选错了网卡是一件极度郁闷的事情。点击按钮可以在抓包之前选择抓哪张网卡。
图3 选择网卡
我机器上只有一张网卡,另外两个是安装Vmware时的虚拟网卡,可以看到虽然Packets上面已经有数据了,实际上需要点击Start才开始抓包。
解决了选择网卡的问题以后,考虑如果过滤抓包内容,点击菜单栏上的” Capture” > “Options”可以看到制定抓包规则的界面,如图4所示。
图4 制定抓包规则
图4可以看到Caputre packets in promiscuous mode,默认是选中的,表示Wireshark默认在混杂模式下抓包。同样可以选择通过哪张网卡抓包,不过这些都不是重点,最重要的是Caupture Fileter这里,点击该按钮,可以看到弹出一些预定义好的过滤器。比如选择“HTTP TCP port(80)”,下面Filter string: tcp port http就是过滤器的表示。表示抓tcp协议的,端口为80的数据包(http协议的默认端口是80)。
3. 过滤器(BPF语言)的使用
主要介绍一下在tcpdump中的过滤器使用,因为懂了这个就可以得心应手的使用wireshark了。
从最简单的开始,BPF语言主要有一个标志或者数字和限定词组成,限定词有三种:
第一种:指定类型
host, 定义抓取哪个IP地址(也可以给它mac地址,格式是00:00:00:00:00:00)的数据包,比如我想抓有关192.168.0.148这个IP地址的数据包,那么就写成tcpdump host 192.168.0.148, host是限定词,192.168.0.148就是标志。这条命令会抓取从发出或者向192.168.0.148发送的数据包。
net, 定义抓取某个网络的数据包,给出网络号就行了,它根据给的网络号字节数是1,2,3来判断A类地址,B类地址或者C类地址,比如tcpdump net 10.1.1 ,它就认为这是一个C类地址。
port,指定端口,比如tcpdump host and port 22, 这是抓端口为22的数据包,不管是TCP还是UDP的,这里我稍微早一点的给出了逻辑操作,and J,如果只想抓TCP的,那么可以写tcpdump host 192.168.0.148 and tcp port 22。
portrange,顾名思义,这个是指定端口范围的,用连字符”-”指定范围,比如tcpdump port 1025-8080
第二种:指定方向
我们之前的命令都是说“这条命令会抓取从192.168.0.148发出或者向192.168.0.148发送”,所以,如果指向抓从发出的数据包可以使用限定词src, 命令:tcpdump src host 192.168.0.148,反过来,想抓发向192.168.0.148的数据包,使用限定词dst,命令:tcpdump dst host 192.168.0.148。
第三种:指定协议
我们知道网络协议有N种。。。我列一下常用的几种,其他的可以去google一下J
ether和fddi, 以太网协议
tr, TR协议
ip, IP协议
ip6, IPv6协议
arp, ARP协议
好了,最后还需要注意的是逻辑运算,and, or, not(与,或,非),上面已经有一个例子了, 这里就不再罗嗦了,和普通的编程语言没有什么不同。
除此之外,还有更加牛X的功能,比如指定TCP中的某个标识位是什么,这种应用我一般很少用,不再罗嗦了。
--------------------------------------------------------------------------------------------------------------------------------------------------------
[root@linux ~]# tcpdump [-nn] [-i 介面] [-w 儲存檔名] [-c 次數] [-Ae] [-qX] [-r 檔案] [所欲擷取的資料內容] 參數: -nn:直接以 IP 及 port number 顯示,而非主機名與服務名稱 -i :後面接要『監聽』的網路介面,例如 eth0, lo, ppp0 等等的介面; -w :如果你要將監聽所得的封包資料儲存下來,用這個參數就對了!後面接檔名 -c :監聽的封包數,如果沒有這個參數, tcpdump 會持續不斷的監聽, 直到使用者輸入 [ctrl]-c 為止。 -A :封包的內容以 ASCII 顯示,通常用來捉取 WWW 的網頁封包資料。 -e :使用資料連接層 (OSI 第二層) 的 MAC 封包資料來顯示; -q :僅列出較為簡短的封包資訊,每一行的內容比較精簡 -X :可以列出十六進位 (hex) 以及 ASCII 的封包內容,對於監聽封包內容很有用 -r :從後面接的檔案將封包資料讀出來。那個『檔案』是已經存在的檔案, 並且這個『檔案』是由 -w 所製作出來的。 所欲擷取的資料內容:我們可以專門針對某些通訊協定或者是 IP 來源進行封包擷取, 那就可以簡化輸出的結果,並取得最有用的資訊。常見的表示方法有: 'host foo', 'host 127.0.0.1' :針對單部主機來進行封包擷取 'net 192.168' :針對某個網域來進行封包的擷取; 'src host 127.0.0.1' 'dst net 192.168':同時加上來源(src)或目標(dst)限制 'tcp port 21':還可以針對通訊協定偵測,如 tcp, udp, arp, ether 等 還可以利用 and 與 or 來進行封包資料的整合顯示呢! 範例一:以 IP 與 port number 捉下 eth0 這個網路卡上的封包,持續 3 秒 [root@linux ~]# tcpdump -i eth0 -nn tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes 01:33:40.41 IP 192.168.1.100.22 > 192.168.1.11.1190: P 116:232(116) ack 1 win 9648 01:33:40.41 IP 192.168.1.100.22 > 192.168.1.11.1190: P 232:364(132) ack 1 win 9648 <==按下 [ctrl]-c 之後結束 6680 packets captured <==捉下來的封包數量 14250 packets received by filter <==由過濾所得的總封包數量 7512 packets dropped by kernel <==被核心所丟棄的封包 |
- 01:33:40.41:這個是此封包被擷取的時間,『時:分:秒』的單位;
- IP:透過的通訊協定是 IP ;
- 192.168.1.100.22 > :傳送端是 192.168.1.100 這個 IP,而傳送的 port number 為 22,您必須要瞭解的是,那個大於 (>) 的符號指的是封包的傳輸方向喔!
- 192.168.1.11.1190:接收端的 IP 是 192.168.1.11, 且該主機開啟 port 1190 來接收;
- P 116:232(116):這個封包帶有 PUSH 的資料傳輸標誌, 且傳輸的資料為整體資料的 116~232 byte,所以這個封包帶有 116 bytes 的資料量;
- ack 1 win 9648:ACK與 Window size 的相關資料。
再來,一個網路狀態很忙的主機上面,你想要取得某部主機對你連線的封包資料而已時, 使用 tcpdump 配合管線命令與正規表示法也可以,不過,畢竟不好捉取! 我們可以透過 tcpdump 的表示法功能,就能夠輕易的將所需要的資料獨立的取出來。 在上面的範例一當中,我們僅針對 eth0 做監聽,所以整個 eth0 介面上面的資料都會被顯示到螢幕上, 不好分析啊!那麼我們可以簡化嗎?例如只取出 port 21 的連線封包,可以這樣做:
[root@linux ~]# tcpdump -i eth0 -nn port 21
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
01:54:37.96 IP 192.168.1.11.1240 > 192.168.1.100.21: . ack 1 win 65535
01:54:37.96 IP 192.168.1.100.21 > 192.168.1.11.1240: P 1:21(20) ack 1 win 5840
01:54:38.12 IP 192.168.1.11.1240 > 192.168.1.100.21: . ack 21 win 65515
01:54:42.79 IP 192.168.1.11.1240 > 192.168.1.100.21: P 1:17(16) ack 21 win 65515
01:54:42.79 IP 192.168.1.100.21 > 192.168.1.11.1240: . ack 17 win 5840
01:54:42.79 IP 192.168.1.100.21 > 192.168.1.11.1240: P 21:55(34) ack 17 win 5840
|
- 我們先在一個終端機視窗輸入『 tcpdump -i lo -nn 』 的監聽,
- 再另開一個終端機視窗來對本機 (127.0.0.1) 登入『ssh localhost』
[root@linux ~]# tcpdump -i lo -nn 1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode 2 listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes 3 11:02:54.253777 IP 127.0.0.1.32936 > 127.0.0.1.22: S 933696132:933696132(0) win 32767 <mss 16396,sackOK,timestamp 236681316 0,nop,wscale 2> 4 11:02:54.253831 IP 127.0.0.1.22 > 127.0.0.1.32936: S 920046702:920046702(0) ack 933696133 win 32767 <mss 16396,sackOK,timestamp 236681316 236681316,nop, wscale 2> 5 11:02:54.253871 IP 127.0.0.1.32936 > 127.0.0.1.22: . ack 1 win 8192 <nop, nop,timestamp 236681316 236681316> 6 11:02:54.272124 IP 127.0.0.1.22 > 127.0.0.1.32936: P 1:23(22) ack 1 win 8192 <nop,nop,timestamp 236681334 236681316> 7 11:02:54.272375 IP 127.0.0.1.32936 > 127.0.0.1.22: . ack 23 win 8192 <nop, nop,timestamp 236681334 236681334> |
- 第 3 行顯示的是『來自 client 端,帶有 SYN 主動連線的封包』,
- 第 4 行顯示的是『來自 server 端,除了回應 client 端之外(ACK),還帶有 SYN 主動連線的標誌;
- 第 5 行則顯示 client 端回應 server 確定連線建立 (ACK)
- 第 6 行以後則開始進入資料傳輸的步驟。
更神奇的使用要來啦!如果我們使用 tcpdump 在 router 上面監聽『明碼』的傳輸資料時, 例如 FTP 傳輸協定,你覺得會發生什麼問題呢? 我們先在主機端下達『 tcpdump -i lo port 21 -nn -X 』然後再以 ftp 登入本機,並輸入帳號與密碼, 結果你就可以發現如下的狀況:
[root@linux ~]# tcpdump -i lo -nn -X 'port 21' 0x0000: 4500 0048 2a28 4000 4006 1286 7f00 0001 E..H*(@.@....... 0x0010: 7f00 0001 0015 80ab 8355 2149 835c d825 .........U!I./.% 0x0020: 8018 2000 fe3c 0000 0101 080a 0e2e 0b67 .....<.........g 0x0030: 0e2e 0b61 3232 3020 2876 7346 5450 6420 ...a220.(vsFTPd. 0x0040: 322e 302e 3129 0d0a 2.0.1).. 0x0000: 4510 0041 d34b 4000 4006 6959 7f00 0001 E..A.K@.@.iY.... 0x0010: 7f00 0001 80ab 0015 835c d825 8355 215d ........./.%.U!] 0x0020: 8018 2000 fe35 0000 0101 080a 0e2e 1b37 .....5.........7 0x0030: 0e2e 0b67 5553 4552 2064 6d74 7361 690d ...gUSER.dmtsai. 0x0040: 0a . 0x0000: 4510 004a d34f 4000 4006 694c 7f00 0001 E..J.O@.@.iL.... 0x0010: 7f00 0001 80ab 0015 835c d832 8355 217f ........./.2.U!. 0x0020: 8018 2000 fe3e 0000 0101 080a 0e2e 3227 .....>........2' 0x0030: 0e2e 1b38 5041 5353 206d 7970 6173 7377 ...8PASS.mypassw 0x0040: 6f72 6469 7379 6f75 0d0a ordisyou.. |
另外你得瞭解,為了讓網路介面可以讓 tcpdump 監聽,所以執行 tcpdump 時網路介面會啟動在 『錯亂模式 (promiscuous)』,所以你會在 /var/log/messages 裡面看到很多的警告訊息, 通知你說你的網路卡被設定成為錯亂模式!別擔心,那是正常的。 至於更多的應用,請參考 man tcpdump 囉!
例題:如何使用 tcpdump 監聽 (1)來自 eth0 介面卡且 (2)通訊協定為 port 22 ,(3)目標來源為 192.168.1.100 的封包資料? 答:
|
ethereal
啟動的方法很簡單,你必須要在 X Window 底下,先開啟一個終端機,然後直接輸入 ethereal 後, 就會出現如下的畫面了:
圖五、ethereal 使用範例圖
簡單的作法,你可以點選如上圖顯示的那個按鈕,會出現挑選監聽的介面視窗,如下所示:
圖六、ethereal 使用範例圖
你應該選擇要監聽的介面,在這裡因為是測試用的,所以鳥哥使用的是 lo 這個內部介面, 你當然應該要選擇你自己的網路介面才是。然後按下 start 後,就會出現開始偵測的畫面了:
圖七、ethereal 使用範例圖
在這個畫面當中你可以看到很多類型的封包協定,在等你處理完畢後,就可以按下『stop』結束監聽, 而開始進入如下的封包分析畫面。
圖八、ethereal 使用範例圖
封包分析畫面共分為三大區塊,如上圖所示,第一區塊主要顯示的是封包的標頭資料, 內容就有點類似 tcpdump 的顯示結果,第二區塊則是詳細的表頭資料, 包括訊框的內容、通訊協定的內容以及 socket pair 等等資訊。 第三區塊則是 16 進位與 ASCII 碼的顯示結果。透過這個 ethereal 您就可以一口氣得到所需要的所有封包內容啦! 而且還是圖形介面的,很方便吧!透過在第一區塊選擇不同的封包,就能夠查閱每個封包的資料內容囉!
nc, netcat
[root@linux ~]# nc [IP|host] [port] [root@linux ~]# nc -l -p [port] 參數: -l :作為監聽之用,亦即開啟一個 port 來監聽用戶的連線; -p :開啟的這個 port number 範例一:連接本地端的 port 25 查閱相關訊息 [root@linux ~]# nc localhost 25 localhost.localdomain [127.0.0.1] 25 (smtp) open 220 pc.dm.tsai ESMTP Postfix ehlo localhost 250-pc.dm.tsai 250-PIPELINING 250-SIZE 40000000 250-ETRN quit 221 Bye |
範例二:啟動一個 port 來監聽使用者的連線要求 [root@linux ~]# nc -l -p 20000 # 啟動一個 port 20000 在主機上,如果此時使用 netstat -tlnp # 就可以看到系統上多出來一個 port 20000 在傾聽使用者的連線喔! |
[root@linux ~]# nc localhost 20000 <==這裡可以開始輸入字串了! |