Fork me on GitHub

#linux包之tcpdump之tcpdump命令

概述

man tcpdump  已阅

yum install tcpdump

Downloading Packages:
(1/2): libpcap-1.4.0-1.20130826git2dbcaa1.el6.x86_64.rpm                                | 130 kB     00:00
(2/2): tcpdump-4.0.0-3.20090921gitdf3cb4.2.el6.x86_64.rpm                               | 336 kB     00:00
[root@localhost ~]# rpm -qa|grep tcpdump
tcpdump-4.0.0-3.20090921gitdf3cb4.2.el6.x86_64

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

Linux作为网络服务器,特别是作为路由器和防火墙时,数据的采集和分析是必不可少的。所以,今天我们就来看看Linux中强大的网络数据采集分析工具——tcpdump。

显然为了安全起见,不用作网络管理用途的计算机上不应该运行这一类的网络分析软件,为了屏蔽它们,可以屏蔽内核中的bpfilter伪设备。一般情况下网络硬件和TCP/IP堆栈不支持接收或发送与本计算机无关的数据包,为了接收这些数据包,就必须使用网卡的混杂模式,并绕过标准的TCP/IP堆栈才行。在FreeBSD下,这就需要内核支持伪设备bpfilter。因此,在内核中取消bpfilter支持,就能屏蔽tcpdump之类的网络分析工具。并且当网卡被设置为混杂模式时,系统会在控制台和日志文件中留下记录,提醒管理员留意这台系统是否被用作攻击同网络的其他计算机的跳板。

vi /var/log/messages 当捕获包时,会启动在混杂模式下,在日志中留下记录。

Sep 12 08:46:57 localhost kernel: device eth0 entered promiscuous mode
Sep 12 08:47:01 localhost kernel: device eth0 left promiscuous mode

May 15 16:27:20 host1 /kernel: fxp0: promiscuous mode enabled

解释

总的的输出格式为:系统时间 来源主机.端口 > 目标主机.端口 数据包参数

tcpdump可以分为三大部分内容,第一是“选项”,第二是“过滤表达式”,第三是“输出信息”。

选项

tcpdump对截获的数据并没有进行彻底解码,数据包内的大部分内容是使用十六进制的形式直接打印输出的。显然这不利于分析网络故障,通常的解决办法是先使用带-w参数的tcpdump截获数据并保存到文件中,然后再使用其他程序(如Wireshark)进行解码分析。当然也应该定义过滤规则,以避免捕获的数据包填满整个硬盘。
-n     不把网络地址转换成名字;
-nn      不进行端口名称的转换。
-t        在输出的每一行不打印时间戳
-vv    输出详细的报文信息;
-c     在收到指定的包的数目后,tcpdump就会停止
-e    在输出行打印出数据链路层的头部信息
-r    从指定的文件中读取包(这些包一般通过-w选项产生)
-w    直接将包写入文件中,并不分析和打印出来

-X  直接解包内容

使用-A选项,则tcpdump只会显示ASCII形式的数据包内容,不会再以十六进制形式显示;
使用-XX选项,则tcpdump会从以太网部分就开始显示网络包内容,而不是仅从网络层协议开始显示。
使用-D选项,则tcpdump会列出所有可以选择的抓包对象。
tcpdump -D
1.eth0
2.nflog (Linux netfilter log (NFLOG) interface)
3.nfqueue (Linux netfilter queue (NFQUEUE) interface)
4.any (Pseudo-device that captures on all interfaces)
5.lo

-e选项的输出中,会发现有oui Unknown的字样,这oui是什么东东呢?在这里顺便科普一下咯:
OUI,即Organizationally unique identifier,是“组织唯一标识符”,在任何一块网卡(NIC)中烧录的6字节MAC地址中,前3个字节体现了OUI,其表明了NIC的制造组织。通常情况下,该标识符是唯一的。
-l选项的作用就是将tcpdump的输出变为“行缓冲”方式,这样可以确保tcpdump遇到的内容一旦是换行符即将缓冲的内容输出到标准输出,以便于利用管道或重定向方式来进行后续处理。
众所周知,Linux/UNIX的标准I/O提供了全缓冲、行缓冲和无缓冲三种缓冲方式。标准错误是不带缓冲的,终端设备常为行缓冲,而其他情况默认都是全缓冲的。
大家在使用tcpdump时,有时会有这样的需求:“对于tcpdump输出的内容,提取每一行的第一个域,即”时间域”,并输出出来,为后续统计所用”,这种场景下,我们就需要使用到-l来将默认的全缓冲变为行缓冲了。
如果不加-l选项,那么只有全缓冲区满,才会输出一次,这样不仅会导致输出是间隔不顺畅的,而且当你ctrl-c时,很可能会断到一行的半截,损坏统计数据的完整性。
做过网络流量分析的同学,或许都有一个共同的需求,那就是“流量保存”和“流量回放”,这就恰好对应了今天要讲解的-w选项和-r选项。
“流量保存”就是把抓到的网络包能存储到磁盘上,保存下来,为后续使用。
“流量回放”就是把历史上的某一时间段的流量,重新模拟回放出来,用于流量分析。

表达式

可以通过手册页来详细阅读 #man  pcap-filter

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

tcpdump  支持正则表达式
tcpdump利用正则作为过滤报文的条件,如果一个报文满足表达式的条件,则这个报文将会被捕获。如果没有给出任何条件,则网络上所有的信息包将会被截获。

或许你会提问“为啥这些协议里没有应用层协议呢?”,其实理由很简单,应用层协议非基础类网络协议,经常会新增或淘汰,tcpdump不会深入到应用层部分去智能解析。所以,你现在看到的tcpdump支持的protocol都是应用层以下的。

ether – 链路层协议
fddi – 链路层协议
tr – 链路层协议
wlan – 链路层协议
ppp – 链路层协议
slip – 链路层协议
link – 链路层协议

tcpdump 'tcp[tcpflags] & tcp-syn != 0 and not dst host qiyi.com'
tcpdump 'ip[2:2] > 576'
tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'

即proto [ expr : size]语法
expr用来指定数据报偏移量,表示从某个协议的数据报的第多少位开始提取内容,默认的起始位置是0;而size表示从偏移量的位置开始提取多少个字节,可以设置为1、2、4。
如果只设置了expr,而没有设置size,则默认提取1个字节。比如ip[2:2],就表示提取出第3、4个字节;而ip[0]则表示提取ip协议头的第一个字节。
在我们提取了特定内容之后,我们就需要设置我们的过滤条件了,我们可用的“比较操作符”包括:>,<,>=,<=,=,!=,总共有6个。

ip[0] & 0xf != 5
IP协议的第0-4位,表示IP版本号,可以是IPv4(值为0100)或者IPv6(0110);第5-8位表示首部长度,单位是“4字节”,如果首部长度为默认的20字节的话,此值应为5,即”0101″。ip[0]则是取这两个域的合体。0xf中的0x表示十六进制,f是十六进制数,转换成8位的二进制数是“0000 1111”。而5是一个十进制数,它转换成8位二进制数为”0000 0101″。
有了上面这些分析,大家应该可以很清楚的知道,这个语句中!=的左侧部分就是提取IP包首部长度域,如果首部长度不等于5,就满足过滤条件。言下之意也就是说,要求IP包的首部中含有可选字段。
大家可能已经有所体会,在写过滤表达式时,你需要把协议格式完全背在脑子里,才能把表达式写对。可这对大多数人来说,可能有些困难。为了让tcpdump工具更人性化一些,有一些常用的偏移量,可以通过一些名称来代替,比如icmptype表示ICMP协议的类型域、icmpcode表示ICMP的code域,tcpflags则表示TCP协议的标志字段域。
更进一步的,对于ICMP的类型域,可以用这些名称具体指代:icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect, icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob, icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq, icmp-maskreply。
而对于TCP协议的标志字段域,则可以细分为tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg。
如果一个过滤表达式有多个过滤条件,那么就需要使用逻辑符了,其中,!或not都可以表示“否定”,&&与and都可以表示“与”,而||与or都可以表示“或”。

有关ETHER的,可以参考《计算机网络协议包头赏析-以太网》;
有关IP的,可以参考《计算机网络协议包头赏析-IP》;
有关TCP的,可以参考《计算机网络协议包头赏析-TCP》;
有关UDP的,可以参考《计算机网络协议包头赏析-UDP》。

表达式中的关键字
第一种是关于类型的关键字,主要包括host(默认),net,port
第二种是确定传输方向的关键字,主要包括src,dst ,dst or src(默认), dst and src 
第三种是协议的关键字,主要包括fddi,ip,arp,rarp,tcp,udp等类型,默认是监听所有协议,Fddi指明是在FDDI(分布式光纤数据接口网络)上的特定的网络协议,实际上它是"ether"的别名,fddi和ether具有类似的源地址和目的地址,所以可以将fddi协议包当作ether的包进行处理和分析。除了这三种类型的关键字之外,其他重要的关键字如下:gateway, broadcast,less,
greater,还有三种逻辑运算,取非运算是 'not ' '! ';与运算是'and','&&';或运算是'or' ,'||';
这些关键字可以组合起来构成强大的组合条件来满足人们的需要
下面举例说明
tcpdump host 192.168.2.101 -c 50 -nn -t
tcpdump host 210.27.48.1 and \(210.27.48.2 or 210.27.48.3 \) 
tcpdump ip host 210.27.48.1 and ! 210.27.48.2
tcpdump tcp port 23 host 210.27.48.1

常见表示方法

host 192.168.2.10或者host com1

tcp port 10000,src host 192.168.2.10,

输出信息

“listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes”
这一句表示我们监听的是通过eth0这个NIC设备的网络包,且它的链路层是基于以太网的,要抓的包大小限制是65535字节。
包大小限制值可以通过-s选项来设置,如果你要追求高性能,建议把这个值调低,这样可以有效避免在大流量情况下的丢包现象。

没有用-s参数指定抓取数据的长度,采用了默认长度为68或96字节;-s0则表示没有长度的限制。

[root@aster5 ~]# tcpdump -nn host 117.136.25.196
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

[root@aster5 ~]# tcpdump -nn -s0 -c 50  host 117.136.25.196 -w 1007
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

加-X的话,接下来便是IP包的内容了,是除去了以太网之后剩下的内容,其中左侧红色字体部分是十六进制内容,右侧天蓝色字体部分是相应的ASCII码内容。

(1) 数据链路层头信息
使用命令#tcpdump -e host ice
ice 是一台装有linux的主机,她的MAC地址是0:90:27:58:AF:1A
H219是一台装有SOLARIC的SUN工作站,它的MAC地址是8:0:20:79:5B:46;上一条
命令的输出结果如下所示:
21:50:12.847509 eth0 ice.telnet 0:0(0) ack 22535 win 8760 (DF)
分析:21:50:12是显示的时间, 847509是ID号,eth0 表示从网络接口设备发送数据包, 8:0:20:79:5b:46是主机H219的MAC地址,它
表明是从源地址H219发来的数据包. 0:90:27:58:af:1a是主机ICE的MAC地址,表示该数据包的
目的地址是ICE . ip 是表明该数据包是IP数据包,60 是数据包的长度, h219.33357 > ice.
telnet 表明该数据包是从主机H219的33357端口发往主机ICE的TELNET(23)端口. ack 22535
表明对序列号是222535的包进行响应. win 8760表明发送窗口的大小是8760.

打印以太头代替默认的ip头
tcpdump -e -nn
16:04:22.481164 e4:1f:13:80:ed:2b > 00:50:56:a1:5a:11, ethertype IPv4 (0x0800), length 322: 192.168.2.2.22 > 192.168.2.84.34559: P 2231088:2231344(256) ack 577 win 121 <nop,nop,timestamp 987621813 4054453550>
tcpdump -nn
16:05:42.390904 IP 192.168.2.2.22 > 192.168.2.84.34559: P 2169680:2169856(176) ack 913 win 121 <nop,nop,timestamp 987701722 4054533458>

(2) ARP包的输出信息

[root@109-com1 asterisk]# tcpdump arp -enX
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:26:16.048727 00:50:56:a1:63:0d > Broadcast, ethertype ARP (0x0806), length 60: Request who-has 192.168.2.85 tell 192.168.2.80, length 46
        0x0000:  0001 0800 0604 0001 0050 56a1 630d c0a8  .........PV.c...
        0x0010:  0250 0000 0000 0000 c0a8 0255 0000 0000  .P.........U....
        0x0020:  0000 0000 0000 0000 0000 0000 0000       ..............

使用命令#tcpdump arp
得到的输出结果是:
22:32:42.802509 eth0 > arp who-has route tell ice (0:90:27:58:af:1a)
22:32:42.802902 eth0 表明从主机发出该数据包, arp表明是
ARP请求包, who-has route tell ice表明是主机ICE请求主机ROUTE的MAC地址。 0:90:27:58:af:1a是主机ICE的MAC地址。

18:56:23.790156 ARP, Request who-has 192.168.2.109 tell 192.168.2.10, length 46
18:56:23.790165 ARP, Reply 192.168.2.109 is-at 00:50:56:a1:04:ea, length 28
18:56:27.279072 ARP, Request who-has 192.168.2.109 tell 192.168.2.210, length 46
18:56:27.279087 ARP, Reply 192.168.2.109 is-at 00:50:56:a1:04:ea, length 28

(3) TCP包的输出信息  tcp包头20字节  ip包头也是20字节
用TCPDUMP捕获的TCP包的一般输出信息是:
src > dst: flags data-seqno ack window urgent options
src > dst:表明从源地址到目的地址, flags是TCP包中的标志信息,S 是SYN标志, F (F
IN), P (PUSH) , R (RST) "." (没有标记); data-seqno是数据包中的数据的顺序号, ack是
下次期望的顺序号, window是接收缓存的窗口大小, urgent表明数据包中是否有紧急指针.
Options是选项.

18:48:22.036100 IP 192.168.2.109.22 > 192.168.2.80.52721: Flags [P.], seq 120736:121008, ack 161, win 1002, length 272
18:48:22.037106 IP 192.168.2.109.22 > 192.168.2.80.52721: Flags [P.], seq 121008:121184, ack 161, win 1002, length 176
18:48:22.037551 IP 192.168.2.80.52721 > 192.168.2.109.22: Flags [.], ack 121184, win 256, length 0

(4) UDP包的输出信息  udp包头8字节
用TCPDUMP捕获的UDP包的一般输出信息是:
route.port1 > ice.port2: udp length
UDP十分简单,上面的输出行表明从主机ROUTE的port1端口发出的一个UDP数据包到主机
ICE的port2端口,类型是UDP, 包的长度是length

18:52:17.486689 IP 192.168.2.109.41608 > 192.168.2.10.40001: UDP, length 180
18:52:17.486712 IP 192.168.2.109.42275 > 172.16.1.16.9012: UDP, length 180

样例

 

-c    计数
-e    链路头

默认    15:30:44.520640
-t    不显示时间戳
-tt    1429687801.082955
-ttt    00:00:00.000688        与上一次时间作比较
-tttt    2015-04-22 15:30:18.980728
-ttttt    00:00:00.000249        与第一行时间作比较

-v
-vv
-vvv

-r file
-w file        Write the raw packets to file rather than parsing and printing them out

in hex
-x    不包括链路层头
-xx    包括链路层头

in hex and ASCII
-X    不包括链路层头
-XX     包括链路层头

 

tcpdump -i eth0 -n
tcpdump -i eth0 -nn -t -vv -c 500
tcpdump -i eth0  tcp -c 20  -t -nn -e

tcpdump -nn -X 'port 1521' -c 1

只捕获100个syn包

tcpdump tcp [13] == 2 -nn -c 10

tcpdump 'tcp[13] & 2 == 2' -nn -c 10

tcpdump 'tcp[tcpflags] & tcp-push != 0'

[root@109-com1 asterisk]# tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0' -nn

[root@109-com1 asterisk]# tcpdump host 117.136.3.33 -nn
[root@109-com1 asterisk]# tcpdump host 192.168.2.215 and \(117.136.25.199 or 117.136.25.141 \) -nn
[root@109-com1 asterisk]# tcpdump host 192.168.2.215 and not 117.136.25.199 -nn

[root@222-comecs ~]# tcpdump 'ip[2:2] > 576' -nn
[root@222-comecs ~]# tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply' -nn 

[root@222-comecs ~]# tcpdump -A -c 10  Handy for capturing web pages.以ascii码显示,捕获web页面非常方便

 

tcpdump -nn  一般一定要加-nn,这样不解析主机名与端口名,并且比较快,如果用tcpdump,不加任何参数,会很慢。

[root@coreserv packet]# date           
Sat Mar 29 15:13:26 CST 2014
[root@coreserv packet]# tcpdump udp >cc
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

1182828 packets captured
3063818 packets received by filter
1880979 packets dropped by kernel
[root@coreserv packet]# date
Sat Mar 29 15:15:29 CST 2014

其中“captured”的计数指的是应用层捕获到的数据,“received by filter”和“dropped by kernel”的计数由内核维护,应用层通过getsockopt来获取。收到一个包,“received by filter”会加1,如果sock的接收buffer被填满时,则把这个数据包丢弃,将“dropped by kernel”加1。
通过调节/proc/sys/net/core/rmem_default和/proc/sys/net/core/rmem_max能够改变sk_rcvbuf的大小。
正常“captured”加上“dropped by kernel”应该等于“received by filter”的大小,有的时候出现不等的情况应该是还有一些数据包在sk_rcvbuf中,还没有被应用层收到的原因。
通过调节发包速率,发包速率调慢,丢包率明显降低。

 

When tcpdump finishes capturing packets, it will report counts of:

    packets ``captured'' (this is the number of packets that tcpdump has received and processed);
    packets ``received by filter'' (the meaning of this depends on the OS on which you're running tcpdump, and possibly on the way the OS was configured -

if a filter was specified on the command line,
on some OSes it counts packets regardless of whether they were matched by the filter expression and, even if they were matched by the filter expression, regardless of whether tcpdump has read and processed them yet,
on other OSes it counts only packets that were matched by the filter expression regardless of whether tcpdump has read and processed them yet,
and on other OSes it counts only packets that were matched by the filter expression and were processed by tcpdump);

    packets ``dropped by kernel'' (this is the number of packets that were dropped, due to a lack of buffer space, by the packet capture mechanism in the OS on which tcpdump is running, if the OS reports that information to applications; if not, it will be reported as 0).

http://blog.sina.com.cn/s/blog_67b48ddf0102v1rm.html  tcpdump捕获包内容不全

在linux下用tcpdump抓取http数据包,之后用wireshark打开,发现数据包的内容是不全的
这时,想分析和获取http包中的内容是不可能的,在图中可以发现,wireshark给出了“Packet size limited during cap”的提示,和:“HTTP truncated”的提示。这是什么呢?
自己在实际中遇到的是这个错误提示:packet size limited during capture: JXTA truncated

对于这个问题,一个“外国朋友的MAIL中”给了非常好的解答,MAIL部分原文如下:
Maynard, Chris wrote:
"Packet Size limited during capture" tells me that the packet was bigger than the snaplen set, so the packet was truncated when captured.  In Wireshark, the snaplen is set in the capture options dialog using the "Limit each packet to ___ bytes" option, and with dumpcap, tshark and tcpdump it is set via the "-s " option.  If not specified, tcpdump uses a default snaplen of 68 (or 96, depending on the platform).

这个问题主要有两方面的原因:
1)在wireshark等包分析软件中,可以设置包的长度,如果不当可能回出现这个问题; wireshark的设置如下图(在[Capture]---[Options]下配置):
关于“Packet size limited during capture”的解释 - karl - 黑昼*无主之地
 

2)用Tcpdump进行抓包时,没有用-s参数指定抓取数据的长度,采用了默认长度为68或96字节;-s0则表示没有长度的限制。

[root@aster5 ~]# tcpdump -nn -s0 -c 50  host 117.136.25.196 -w 1007
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
50 packets captured
50 packets received by filter
0 packets dropped by kernel

eth包头14字节
ip包头20字节
tcp包头20字节
udp包头8字节
 

tcpdump -s0 -c 50 -nn host 222.91.97.126  -w 20001.pcap

tcpdump -s0 -c 50 -nn tcp port 10000 -w 10000.pcap
[root@84-monitor packet]# pwd
/root/packet
[root@84-monitor packet]# scp -P 8164 124.115.106.234:/root/10009.pcap ./
10009.pcap                                                                                                                      100% 2943     2.9KB/s   00:00
[root@84-monitor packet]# scp 192.168.2.221:/root/10001.pcap ./
10001.pcap                                                                                                                 100%   12KB  12.1KB/s   00:00

posted on 2014-03-31 16:37  阳光-源泉  阅读(3261)  评论(0编辑  收藏  举报

导航