tcpdump学习五分钟系列文章(转载)

 

本原创文章属于《Linux大棚》博客。

博客地址为http://roclinux.cn。

文章作者为roc。


其实tcpdump就好像一个神探,它有着夜视的绝技,在毫无光亮的环境中,也可以看到所有的东西。(好像在编美剧hero一般,哈哈)

在介绍tcpdump之前,要和你确认好几个关键前提,否则的话,往后的内容您看起来会非常困难。
1 了解和使用过linux
2 掌握网络七层协议及其作用
3 熟悉各层协议头,重点是以太网/IP/TCP/UDP
4 了解交换机、路由器所对应的协议层,并知道两者的异同点。

如果你有些忘记了,那么强烈建议你翻出《计算机网络》教材,先好好回忆一下,然后再进入到下面的内容…

==

正文:

                                               (一)

通俗的说,tcpdump是一个抓包工具,用于抓取互联网上传输的数据包。
形象的说,tcpdump就好比是国家海关,驻扎在出入境的咽喉要道,凡是要入境和出境的集装箱,海关人员总要打开箱子,看看里面都装了点啥。
学术的说,tcpdump是一种嗅探器(sniffer),利用以太网的特性,通过将网卡适配器(NIC)置于混杂模式(promiscuous)来获取传输在网络中的信息包。

【抓人生中的第一个包】

要用tcpdump抓包,请记住,一定要切换到root账户下,因为只有root才有权限将网卡变更为“混杂模式”。
然后呢,就是用ifconfig的方法查看好你的服务器的网卡名称。(我的叫做eth0,一般都是这个名字)

# tcpdump -i eth0 -nn -X ‘port 53′ -c 1
   
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
23:58:04.688155 IP 116.255.245.206.47172 > 61.139.2.69.53: 15352+ A? www.baidu.com. (31)
0x0000: 4500 003b d596 0000 4011 fa7d 74ff f5ce E..;....@..}t...
0x0010: 3d8b 0245 b844 0035 0027 a48f 3bf8 0100 =..E.D.5.'..;...
0x0020: 0001 0000 0000 0000 0377 7777 0562 6169 .........www.bai
0x0030: 6475 0363 6f6d 0000 0100 01 du.com.....
1 packets captured
1 packets received by filter
0 packets dropped by kernel

在此,我重点解释下这个命令:

-i选项:
是interface的含义,是指我们有义务告诉tcpdump希望他去监听哪一个网卡。这在我们一台服务器有多块网卡时很有必要。

-nn选项:
意思是说当tcpdump遇到协议号或端口号时,不要将这些号码转换成对应的协议名称或端口名称。比如,众所周知21端口是FTP端口,我们希望显示21,而非tcpdump自作聪明的将它显示成FTP。

-X选项:
告诉tcpdump命令,需要把协议头和包内容都原原本本的显示出来(tcpdump会以16进制和ASCII的形式显示),这在进行协议分析时是绝对的利器。

‘port 53′:
这是告诉tcpdump不要看到啥就显示啥。我们只关心源端口或目的端口是53的数据包,其他的数据包别给我显示出来。

-c选项:
是Count的含义,这设置了我们希望tcpdump帮我们抓几个包。我设置的是1,所以tcpdump不会帮我再多抓哪怕一个包回来。

【未完待续】

从混混乱乱的输出中,大家一定隐约的能看到www.baidu.com,是的,我抓到的这个包,其实是DNS解析的第一个包,也就是发出解析请求的包。至于tcpdump输出的内容到底是什么含义,会在后面娓娓道来。敬请期待。
                                                  (二)
tcpdump可以分为三大部分内容,第一是“选项”,第二是“过滤表达式”,第三是“输出信息”。
下面的文章,会分别从这三个方面来重点介绍。
tcpdump的选项,我还真是专门数了一下,总共有50个之多。在这个系列文章中,实在很难全都覆盖,我尽量挑选重要且常用的选项来讲解,
一些不常用的选项,大家抽空可以自己去了解一下。

在《第一招》中讲到了-i选项、-nn选项、-c选项、-X选项。今天,我们继续介绍另外两个重要的选项,即-e选项和-l选项。

【-e选项】- 增加以太网帧头部信息输出

闲言少叙,直接给出例子,大家就能看到区别了:
# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:36:18.490875 IP 116.255.245.206.snapenetio > 61.135.169.73.56503: Flags [P.], seq 990974500:990974696, ack 4001909970, win 270, length 196
# tcpdump -i eth0 -c 1 -e
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:36:09.910296 00:15:5d:f5:4b:37 (oui Unknown) > 00:00:0c:07:ac:15 (oui Cisco), ethertype IPv4 (0x0800), length 250: 116.255.245.206.snapenetio > 61.135.169.73.56503: Flags [P.], seq 990973640:990973836, ack 4001909762, win 270, length 196

如果还是看不懂,说明你忘记了以太网协议的头格式,我再这里补充下,帮大家回忆回忆:
   
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* 目的主机的地址 */
u_char ether_shost[ETHER_ADDR_LEN]; /* 源主机的地址 */
u_short ether_type; /* IP? ARP? RARP? etc */
};

在刚才加-e选项的输出中,会发现有oui Unknown的字样,这oui是什么东东呢?在这里顺便科普一下咯:
OUI,即Organizationally unique identifier,是“组织唯一标识符”,在任何一块网卡(NIC)中烧录的6字节MAC地址中,前3个字节体现了OUI,其表明了NIC的制造组织。通常情况下,该标识符是唯一的。

【-l选项】- 使得输出变为行缓冲

-l选项的作用就是将tcpdump的输出变为“行缓冲”方式,这样可以确保tcpdump遇到的内容一旦是换行符即将缓冲的内容输出到标准输出,以便于利用管道或重定向方式来进行后续处理。

众所周知,Linux/UNIX的标准I/O提供了全缓冲、行缓冲和无缓冲三种缓冲方式。标准错误是不带缓冲的,终端设备常为行缓冲,而其他情况默认都是全缓冲的。

大家在使用tcpdump时,有时会有这样的需求:“对于tcpdump输出的内容,提取每一行的第一个域,即时间域,并输出出来,为后续统计所用”,这种场景下,我们就需要使用到-l来将默认的全缓冲变为行缓冲了。
   
# tcpdump -i eth0 -l |awk '{print $1}'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
22:56:57.571680
22:56:57.572103
22:56:57.599515
22:56:57.706286
22:56:57.888108
22:56:57.888296
22:56:57.973546
22:56:57.973768
22:56:57.975660
22:56:58.019052
22:56:58.019318
^C146 packets captured
161 packets received by filter
0 packets dropped by kernel

如果不加-l选项,那么只有全缓冲区满,才会输出一次,这样不仅会导致输出是间隔不顺畅的,而且当你ctrl-c时,很可能会断到一行的半截,损坏统计数据的完整性。
                                                          (三)
==

上篇文章说过,tcpdump会分成“选项”、“过滤表达式”和“输出信息”三部分讲解。

截止到目前,我们一直在围绕tcpdump的选项部分进行讲解,已经介绍过的选项包括-i选项、-nn选项、-c选项、-X选项、-e选项、-l选项。
今天仍然不例外,我们继续有关选项的内容。

==

【-t选项】- 输出时不打印时间戳

这个选项非常好理解,直接看例子吧:
# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:52:10.433391 ARP, Request who-has 116.255.247.61 tell 116.255.247.125, length 64
# tcpdump -i eth0 -c 1 -t
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
ARP, Request who-has 116.255.245.35 tell 116.255.245.62, length 64

【-v选项】- 输出更详细的信息

加了-v选项之后,在原有输出的基础之上,你还会看到tos值、ttl值、ID值、总长度、校验值等。
至于上述值的含义,需要你专门去研究下IP头、TCP头的具体协议定义咯。

# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:53:09.162644 IP 116.255.245.206.snapenetio > 221.223.255.234.54198: Flags [P.], seq 1443040202:1443040398, ack 3517061690, win 353, length 196
# tcpdump -i eth0 -c 1 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:52:57.902894 IP (tos 0x10, ttl 64, id 18293, offset 0, flags [DF], proto TCP (6), length 172)
116.255.245.206.snapenetio > 221.223.255.234.54198: Flags [P.], cksum 0x4dd9 (correct), seq 1443039302:1443039434, ack 3517061430, win 353, length 132

【-F选项】- 指定过滤表达式所在的文件

还记得我们在第一招中所提到的命令么,我帮助大家回忆一下:

 tcpdump -i eth0 -nn -X ‘port 53′ -c 1

这里面的’port 53′便叫做“过滤表达式”,用于设置我们抓包的条件的,只有满足过滤条件的网络包,才会被抓过来。
当这个过滤条件非常复杂,或者我们需要将一个过滤条件固化下来复用的时候,就会想到把它存到一个文本文件中。
此时,-F选项就会派上用场。请看例子:
   
# cat filter.txt
port 53
# tcpdump -i eth0 -c 1 -t -F filter.txt
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
IP 116.255.245.206.54357 > ns.sc.cninfo.net.domain: 36720+ A? www.baidu.com. (31)
1 packets captured
6 packets received by filter
0 packets dropped by kernel

我们建立了一个filter.txt文本文件来存储过滤表达式,然后通过-F来指定filter.txt,这样tcpdump就会心知肚明地读取filter.txt中的内容作为过滤条件。

                                                 (四)
本文会是“选项内容”的最后一期讲解,主要会讲讲-w和-r两个选项。tcpdump的选项很多,多达50个,其他我没有涉及的选项,还是要大家自己通过man tcpdump的方式来学习了。实在研究不懂的,可以找我探讨:)

==

做过网络流量分析的同学,或许都有一个共同的需求,那就是“流量保存”和“流量回放”,这就恰好对应了今天要讲解的-w选项和-r选项。

“流量保存”就是把抓到的网络包能存储到磁盘上,保存下来,为后续使用。

“流量回放”就是把历史上的某一时间段的流量,重新模拟回放出来,用于流量分析。

【-w选项】- 将流量保存到文件中
# tcpdump -i eth0 -w flowdata
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
^C327 packets captured
327 packets received by filter
0 packets dropped by kernel

通过上面的例子可以看到,通过-w选项将流量都存储在了flowdata文件中了。大家是否有兴趣less下flowdata,看看里面都是什么东东?
# less flowdata
"flowdata" may be a binary file. See it anyway?

悲剧,原来都是二进制格式的,无法直接通过文本方式查看。嗯,买了个关子,把真像告诉大家吧!

tcpdump的-w方式是把raw packets(原始网络包)直接存储到文件中了,也就是存储的都是结构体形式,而非是分析之后的文本格式的信息,因此大家是无法直接通过less命令查看的。

那么,怎么查看呢?大家想必也想到了,就是用-r选项。

【-r选项】- 读取raw packets文件
# tcpdump -r flowdata
reading from file flowdata, link-type EN10MB (Ethernet)
16:43:36.202443 IP 116.255.245.206.snapenetio > 61.135.169.73.52414: Flags [P.], seq 4082702792:4082702924, ack 3248983965, win 291, length 132
16:43:36.222033 IP 61.135.169.73.52414 > 116.255.245.206.snapenetio: Flags [.], ack 132, win 61, length 0
16:43:36.277407 IP 116.255.245.62 > ospf-all.mcast.net: OSPFv2, Hello, length 48
16:43:36.370846 ARP, Request who-has 116.255.245.203 tell 116.255.245.254, length 64
16:43:36.521947 ARP, Request who-has 116.255.245.203 tell 116.255.245.253, length 64
16:43:36.635472 ARP, Request who-has 116.255.245.214 tell 116.255.245.253, length 64

其实上面的命令就是在不知不觉中进行了“流量回放”,你会发现网络包被“抓”的速度都按照历史进行了回放,真像一个“时光机”啊!

由于是按raw packets来存储的,所以你完全可以使用-e、-l和过滤表达式来对输出信息进行控制,十分方便。

==

预告,第五招开始,会讲解过滤表达式了,会比较有意思,敬请期待。

                                           (五)

前四招都是围绕tcpdump的选项来介绍的,从这招起,我们会把目光转向更加常用的“过滤表达式”内容。

通过这几招的学习,你将具备“心无旁骛,潜心专注”的武功。

==

【师傅领进门】

可以给tcpdump传送“过滤表达式”来起到网络包过滤的作用,而且可以支持传入单个或多个过滤表达式,从这一点来说tcpdump还是很大肚能容的。
当你传入的过滤表达式含有shell通配符时,别忘使用单引号把表达式括起来,以防shell自作主张的把含有通配符的表达式先进行了解释和通配。

如果你希望自己研究“过滤表达式”,没问题,我会告诉你如何“进门”,方法就是:

man pcap-filter

你会发现,过滤表达式大体可以分成三种过滤条件,“类型”、“方向”和“协议”,这三种条件的搭配组合就构成了我们的过滤表达式。

【我只想抓UDP的包,不想被TCP的包打扰】
# tcpdump -i eth0 -c 10 'udp'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
11:25:20.801612 IP 116.255.245.48.54808 > 229.111.112.12.csd-mgmt-port: UDP, length 4
11:25:20.802120 IP 116.255.245.206.54313 > ns.sc.cninfo.net.domain: 5256+ PTR? 12.112.111.229.in-addr.arpa. (45)
11:25:21.145126 IP ns.sc.cninfo.net.domain > 116.255.245.206.54313: 5256 NXDomain 0/0/0 (45)
11:25:21.145315 IP 116.255.245.206.46658 > ns.sc.cninfo.net.domain: 15551+ PTR? 48.245.255.116.in-addr.arpa. (45)
11:25:21.153966 IP 116.255.245.43.62220 > 229.111.112.12.csd-mgmt-port: UDP, length 4
11:25:21.180135 IP 116.255.245.61.hsrp > all-routers.mcast.net.hsrp: HSRPv0-hello 20: state=active group=21 addr=116.255.245.33
11:25:21.231151 IP ns.sc.cninfo.net.domain > 116.255.245.206.46658: 15551 NXDomain 0/0/0 (45)
11:25:21.231430 IP 116.255.245.206.46158 > ns.sc.cninfo.net.domain: 31924+ PTR? 69.2.139.61.in-addr.arpa. (42)
11:25:21.277087 IP ns.sc.cninfo.net.domain > 116.255.245.206.46158: 31924 1/0/0 PTR ns.sc.cninfo.net. (72)
11:25:21.277824 IP 116.255.245.206.42656 > ns.sc.cninfo.net.domain: 806+ PTR? 206.245.255.116.in-addr.arpa. (46)
10 packets captured
20 packets received by filter
0 packets dropped by kernel

举这个例子,是为了说明tcpdump具有根据网络包的协议来进行过滤的能力,我们还可以把udp改为ether、ip、ip6、arp、tcp、rarp等。
或许你会提问“为啥这些协议里没有应用层协议呢?”,其实理由很简单,应用层协议非基础类网络协议,经常会新增或淘汰,tcpdump不会深入到应用层部分去智能解析。所以,你现在看到的tcpdump支持的protocol都是应用层以下的。

【我想专门查看这个源机器和那个目的机器之间的网络包,不想被其他无关的机器打扰】

这个其实很简单,也很直观,只要设置src(source)和dst(destination)就好了,而且方便的是,tcpdump还支持使用and和or来进行搭配组合呢!
如果没有设置的话,默认是src or dst。
# tcpdump -i eth0 'dst 8.8.8.8'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:21:23.281978 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 1, length 64
13:21:24.286663 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 2, length 64
13:21:25.288612 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 3, length 64
^C
3 packets captured
5 packets received by filter
0 packets dropped by kernel

【我只想查目标机器端口是53或80的网络包,其他端口的我不关注】
# tcpdump -i eth0 -c 3 'dst port 53 or dst port 80'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:29:04.530130 IP 114.255.192.96.29832 > 116.255.245.206.http: Flags [S], seq 3169042560, win 5840, options [mss 1460,sackOK,TS val 2949111416 ecr 0], length 0
13:29:04.530660 IP 116.255.245.206.43211 > ns.sc.cninfo.net.domain: 40188+ PTR? 206.245.255.116.in-addr.arpa. (46)
13:29:04.548589 IP 114.255.192.96.29832 > 116.255.245.206.http: Flags [.], ack 3709396068, win 5840, options [nop,nop,TS val 2949111475 ecr 1601243970], length 0
3 packets captured
10 packets received by filter
0 packets dropped by kernel

我们可以设置过滤类型,上面例子中我们使用了port这个类型,就是来指定端口。当然,tcpdump还支持如下的类型:
1 host:指定主机名或IP地址,例如’host roclinux’或’host 202.112.18.34′
2 net :指定网络段,例如’arp net 128.3′或’dst net 128.3′
3 portrange:指定端口区域,例如’src or dst portrange 6000-6008′

如果我们没有设置过滤类型,那么默认是host。 

                                              (六)

第六招,仍然会讲解tcpdump的过滤表达式,这次思路很简单,就是直接举例子,其实就是man tcpdump中的例子,很直观,很受用。

==

【例子1】- 我想抓到那些通过eth0网卡的,且来源是roclinux.cn服务器或者目标是roclinux.cn服务器的网络包

tcpdump -i eth0 'host roclinux.cn'

【例子2】- 我想抓通过eth0网卡的,且roclinux.cn和baidu.com之间通讯的网络包,或者,roclinux.cn和qiyi.com之间通讯的网络包

tcpdump -i eth0 'host roclinux.cn and (baidu.com or qiyi.com)'

【例子3】- 我想获取使用ftp端口和ftp数据端口的网络包

tcpdump 'port ftp or ftp-data'

大家是不是会有一个疑问“这个ftp、ftp-data到底对应哪个端口?除了ftp/ftp-data,还有哪些服务名称我可以直接用呢?”

嗯,这是个好问题,答案现在揭晓咯。

在Linux系统中,/etc/services这个文件里面,就存储着所有知名服务和传输层端口的对应关系。这个对应关系是由IANA组织(the Internet Assigned Numbers Authority,互联网数字分配机构)来全权负责的,你可以到这个链接http://www.iana.org/assignments/port-numbers通过Web方式查到。

如果你直接把/etc/services里的ftp对应的端口值从21改为了8888,那么tcpdump就会去抓端口含有8888的网络包了。

【例子4】- 我想获取roclinux.cn和baidu.com之间建立TCP三次握手中第一个网络包,即带有SYN标记位的网络包,另外,目的主机不能是qiyi.com

tcpdump 'tcp[tcpflags] & tcp-syn != 0 and not dst host qiyi.com'

这个语句看着比较复杂,其实如果要把这段解释清楚的确不容易,需要你具备计算机网络专业知识才行。这个我会安排一招来讲。

【例子5】- 打印IP包长超过576字节的网络包

tcpdump 'ip[2:2] > 576'

【例子6】- 打印广播包或多播包,同时数据链路层不是通过以太网媒介进行的。

tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'

最后三个例子,或许你看得有些晕头转向,没关系,先有个感官认识,看完接下来的几篇文章后,相信保证你就明白了:)

你可能感兴趣的:(tcpdump,网络,抓包,协议分析)