虽然常用tcpdump这个工具,可是却对某个参数一知半解,
google到的中文资料常常人云亦云,一错皆错,反而不知所云,
闲来无事,参考
tcpdumpman格式,并根据自己的理解和测试,弄了下面这份文档。
有些不常见的内容,本人忽略了!?

因为个人水平有限,谬误之处在所难免,

希望有水的灌水,有砖的拍砖!!
语法

描述
Tcpdump程序用来捕获通过某网络接口的匹配某布尔表达式的数据报文信息。

操作系统 使用Tcpdump程序必须具备的条件
SunOS with nit or bpf 必须具备访问设备/dev/nit/dev/bpf*的权限
Solaris with dlpi 必须具备访问/dev/le等网络仿真设备的权限
HP-UX with dlpi 必须是root,或者必须被setuid为root权限
IRIX with snoop 必须是root,或者it must be installed setuid to root
Linux 必须是root,或者必须被setuid为root权限
Ultrix and Digital UNIX 一旦超级用户使用pfconfig(8)启用混杂模式,任何用户都可使用
BSD 必须具备访问设备/dev/bpf*的权限,或者说内核支持/dev/bpfilter之类的伪设备
选项
选项 描述
-a ASCII模式显示所捕获的数据(很多说法是“试着把网络和广播地址转换成名称”,也许是版本差异)
-d 将已经编译好的packet-matching code以某种可读形式输出到标准输出,然后退出
-dd 将packet-matching code以 C程序片断形式输出
-ddd 将packet-matching code以十进制形式输出 (前面加上总数)??? (可参考后面示例17)
-e 显示所捕获包的链路层MAC地址
-f 按数字形式输出外部internet地址 (倒不是很清楚和-n的区别)
-l 使标准输出变成缓冲行形式,Useful if you want to see the data while capturing it (倒类似于linux下的tee命令)
-n 输出时将域名或主机名称转换成IP地址
-nn 输出时将端口名称转换成数字
-N 输出时不显示域名后缀部分,而只显示主机名称,如使用site代替site.test.com
-O 禁止运行packet-matching codeoptimizer,除非您认为optimizerbug
-p 将接口设置成默认的promiscuous模式,注意可能其他的原因而使接口处于非promiscuous模式
-q Quick (quiet?)输出,显示出较少的协议信息,从而输出行会短一些
-R 使用RAW socket接口,如果您需要同时使用多个接口,就需要启用默认的packet socket模式
-S 显示绝对的TCP序列号,而不是相对的
-t 禁止显示每输出行首的默认的timestamp标志,依赖于timestamp标志,我们可以确定某连接建立时的耗时
-tt 显示未格式化的timestamp,类似于一串十进制的数字而非时间格式的timestamp
-v 详细输出,相对于q,譬如可显示出IP数据报中的“生存周期”和“服务类型”、显示出网络接口信息等
-vv 更详细输出,譬如可显示出NFS应答报文的附加域
-x 16进制显示出报文信息(不包括链路层头信息),从而可获得较小的完整报文,否则以slaplen标准输出
-X 默认使用的packet socket interface
-b 只捕获特定的数据链路层协议,可以使用的包括ip/802.2/802.3/arp/rarp/dec/lat/atalk/aarp/x25/ipx(RFC1340)
-c 只捕获指定行数的数据报文
-F 从外部文件中读取表达式,从而忽略后面所输命令行中输入的表达式
-i 指定待监听的接口,如果不指定,tcpdump会搜寻已经配置好的num最小的接口,一般是eth0(localhost除外)
-r 从外部文件读入数据报,一般用来读取-w参数保存下来的文件,如果文件是“-”,则代表标准输入
-s 按指定slaplen长度捕获数据报文,具体请见如下原文
Snarf snaplen bytes of data from each packet rather than the default of 68 (with SunOS's NIT, the minimum is actually 96).? 68 bytes is adequate for IP, ICMP, TCP and UDP but may truncate protocol information from name server and NFS packets (see below).? Packets truncated because of a limited snapshot are indicated in the output with ``[|proto]'', where proto is the name of the protocol level at which the truncation has occurred.? Note that taking larger snapshots both increases the amount of time it takes to process packets and, effectively, decreases the amount of packet buffering.? This may cause packets to be lost. You should limit snaplen to the smallest number that will capture the protocol information you're interested in
-T 目前已知的类型有:rpcrtp(Real-Time Applications protocol)rtcp (Real-Time Applications control protocol), vat(Visual Audio Tool), wb (distributed White Board)
-w 将所捕获的报文输出到文件,以后可用-r参数读取,如果文件是“-”,则代表标准输出
  •  
    •  
      •  
        •  
          •  
            •  
              •  
                •  
                  •  
                    •  
                         

表达式
定义待捕获数据报文的条件表达式,如果匹配所指定的表达式,则tcpdump将数据报文捕获下来。如果没有指定表达式,则tcpdump捕获所有的数据报文,否则,只捕获和表达式想匹配的数据报文。
 
表达式可以由一个或多个primitive组成,primitive通常由一个标识符(ID)及其前面的界定符(qualifier)组成,常见的界定符(qualifier)有下面三种类型:
 
¨  type qualifiers
类型界定符,指出标识符
(ID)所代表的类型,可以使用的类型有hostnetport三种,譬如“host dandy”、“net 10.0.0.0”和“port 80”等,默认的类型为host
¨ dir qualifiers
方向界定符,指定数据报文是传入还是传出,可以使用的方向有“
src”、“dst”、“src or dst”和“src and dst”,如果没指定,则默认为“src or dst”。譬如“src dandy”、“dst net 128.3”、“src or dst port ftp-data”等。对于“NULL”链路层协议(譬如SLIP之类的点对点协议),则可以使用inboundoutbound界定符指定所需的传输方向。
¨ proto qualifiers
协议界定符,指定待匹配的协议,可以使用的协议有
ether/fddi/ip/arp/rarp/decent/lat/sca/moprc/mopdl/tcp/udp等,譬如“ether src dandy”、“arp net 128.3”、“tcp port 21”等。如果没有指定协议,则默认为匹配所有协议。
[注意:FDDI实际等价于ether]
 
除上述之外,还有一些特殊的primitive关键字,如gateway, broadcast, less, greater 和数学表达式,稍后详述。
 
更为复杂的过滤表达式通常由多个primitive组成,多个primitive之间由andornot等连接符连接,譬如“host foo and not port ftp and not port ftp-data”,为了减少输入,可以省略相同的界定符,譬如表达式“tcp dst port ftp or ftp-data or domain”等价于“tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain”。
 
下面列举一些常见的primitive
¨ dst host host
¨ src host host
¨  host host
¨ ether dst ehost
¨  ether src ehost
¨ ether host ehost
¨  gateway host
¨ dst net net
¨ src net net
¨  net net
¨ net net mask mask
¨ net net/len
¨ dst port port
¨ src port port
¨ port port
¨ less length
¨ greater length
¨ ip proto protocol
¨ ether broadcast
¨ ip broadcast
¨ ether multicast
¨ ip multicast
¨ ether proto protocol
¨ decnet src host
¨ decnet dst host
¨ decnet host host
¨ ip, arp, rarp, decent
¨ lat, moprc, mopdl
¨ tcp, udp, icmp
¨ expr relop expr
 
需要重点说明的是 expr relop expr这种primitiverelop >, <, >=, <=, =, !=中的任一种,expr可以看做数学表达式,通常由常整数(integer? constants,标准的C语法形式)、普通的二进制运算符(binary operators,如+, -, *, /, &, |)、一个长度运算符(length operator)和特定的packet data? accessors组成。
如果要访问报文内的数据,可以使用如下的语法:
 proto [ expr : size ]
protoether, fddi, ip, arp, rarp, tcp, udpicmp中的任一种,同时指出了后续[expr:size]操作的协议层;expr给出了相对协议层的偏移量,以字节为单位; Size是可选的,指出了感兴趣proto协议域内连续的字节数,如ip[6:2]指的是IP首部第7、第8两字节,Size的大小可以是124,默认为1length operator,由关键字len指明报文的长度。
例如,“ip[0] & 0x0f !=5”捕获所有带选项的IP报文,“ip[6:2]? &? 0x1fff? =? 0”仅仅捕获未分片且片偏移为0的数据报文,“tcp[13] & 2 != 0”捕获所有SYN置为1的TCP报文。
这些检查含蓄地应用在TCPUDP的下标操作中,例如,tcp[0]总是指TCP报头的首字节,而不会是某分片的首字节。
 
也许初学者对此类表达式不是很理解,需要说明的是,必须熟悉各类协议首部的格式,下面分别对上述几个例子做如下解释:
 
如在expr“ip[0] & 0x0f !=5”中,“ip[0]”可以看做从0位开始的IP首部(1字节),和8位的“0x0f”做与运算,也就是说IP首部前8位的部分(第1字节)和8位的“0x0f”做与运算。由于IP首部前4位是版本号,后4位是首部长度,所以与运算的结果就是首部长度的取值。大家都知道,在没有选项的情况下,IP首部长度为20个字节,而首部长度是32位的数目,所以此种情况下首部长度域的取值为5。其实expr“ip[0] & 0x0f !=5”和expr“ip[0] & 0x0f ?> 5”等价,表示的是IP首部长度不小于5,也就是说IP首部不小于20字节,扣除正常的IP首部长度20字节,多余的就是选项长度。
 
如在expr“ip[6:2] & 0x1fff = 0”中,“ip[6:2]”代表的含义是IP首部从第6字节结尾处(第49bit)开始的2字节,如果熟悉IP首部的话,就知道其指3位的flags和13位的offset所在的2字节,0x1fff就表示二进制0001111111111111,如果需要满足“ip[6:2]”和“0x1fff”进行与运算后其结果为假,则3位的flags必须为“000”,则13位的offset必须为“0000000000000”,也就是说,该IP没有分片,位偏移值亦为0。
 
如在expr“tcp[13] & 2 != 0”中,“tcp[13]”表示的是从tcp首部第13字节结束点开始,“2”用二进制表示就是“00000010”,等价于“0x02”,进行与运算后的值不等于0,也就是说SYN置为1了。
 
多个primitive之间可以由连接符连接(可以使用圆括弧,但必须转义或者用引号括住),下面列举一些常见的连接符:
¨ 取反操作(`!' or `not')
¨ 连接操作(`&&' or `and')
¨ 或操作(`||' or `or')
 
注意,取反操作具备最高优先级,连接操作和或操作优先级别相同,运算时从左至右结合,连接操作必须显式指定,如果没有显式指定关键字,则隐含指定最近的使用的关键字,譬如“not host vs and ace”等价于“not host vs and host ace”,而不应该和“not ( host vs or ace )”相混淆。
 
表达式参数可以作为单个参数或复合参数传递给tcpdump, 后者更方便一些。一般说来,如果表达式包含Shell元字符(metacharacter),传递括起来的参数要容易一些。Multiple arguments are concatenated with spaces before being parsed
示例
为了方便演示,所有的示例只取有限个数据报文,数据报文的个数控制可通过-c参数来实现。
 
示例1:捕获所有进出主机172.16.3.99的数据报文;

 
示例2:捕获主机172.16.3.99和主机172.16.3.251172.16.3.22之间的数据报文;

注意:为了避免使用\符号,可以使用符号来转义。
 
示例3:捕获主机172.16.3.99和除主机172.16.3.253之外的所有主机之间的数据报文;

 
示例4:显示来自主机172.16.3.99ftp数据报文;

 
示例5:捕获每个TCP会话中的起始和结束报文(SYNACK报文),并且报文来自本地网络的其他主机;

 
示例6:捕获来自主机172.16.3.99的数据报文,并且其大小不小于576字节;
]
 
示例7To print IP broadcast or multicast packets that were not sent via ethernet broadcast or multicast

 
示例8:捕获所有非echo requests/repliesICMP报文 (也就是说, 不是 ping 报文)

 
示例9:以ASCII方式显示捕获的数据报文;

 
示例10:以16进制显示捕获的数据报文;

 
示例11:输出时显示所捕获数据报文的链路层地址;

 
示例12:输出时以数字方式显示端口名称;

 
示例13:简洁输出所捕获的数据报文;

 
示例14:详细输出所捕获的数据报文;

 
示例15:输出时不显示时间戳标志;

 
示例16:输出时以非标准方式显示时间戳标志;

 
示例17:关于参数-d的例子;

输出格式
tcpdump的输出格式取决于所指定的协议,下面给出大多数协议的输出格式的简洁描述和示例。
 
A)链路层报文
如果使用了-e选项,输出行将显示链路层相关信息。
 
在以太网环境中,将显示源/目的MAC地址、协议、数据报文长度等信息,如示例11所示。

FDDI网络环境中,将显示帧控制(frame control)域、源/目的地址和报文长度,帧控制域负责解释报文的其他部分。普通报文(譬如包含IP数据包的报文)是优先级基于07之间的异步报文。
譬如类似于“async4”的被认为是包含802.2 Logical Link Control (LLC)的数据包,如果不是ISO数据包或所谓的SNAP包,LLC头信息将会显示。
 
(注意:接下来的描述假设您熟悉RFC1144中所讨论的SLIP压缩算法)
SLIP链路中,tcpdump程序将显示方向指示 (“I”代表inbound“O”代表outbound)、报文类型、压缩信息。首先显示的是报文类型,常见的报文类型有三种:iputcpctcp
对于IP报文来说,不会显示更多的链路信息。对TCP报文来说,紧跟报文类型显示的是连接标识符(connection identifier)
If the packet is compressed, its encoded header is printed out.? The special cases are printed out as *S+n and *SA+n, where n is the amount by which the sequence number (or sequence number and ack) has changed.? If it is not a special case, zero or more changes are printed.? A change is indicated by U (urgent pointer), W (window), A (ack), S (sequence number), and I (packet ID), followed by a delta (+n or -n), or a new value (=n). Finally, the amount of data in the packet and compressed header length are printed.
For example, the following line shows an outbound compressed TCP packet, with an implicit connection identifier; the ack has changed by 6, the sequence number by 49, and the packet ID by 6; there are 3 bytes of data and 6 bytes of compressed header:
O ctcp * A+6 S+49 I+6 3 (6)
 
BARP/RARP 报文
 
ARP/RARP报文输出时显示了请求类型及其相关参数,信息可读性强,信息格式类似于:

 
第一行表明了rtsg发出了一个ARP包来请求主机csamMAC地址,第二行表明了csam回复其MAC地址给rtsg
如果使用tcpdump –n查看的话将清晰一些:

 
如果使用tcpdump –e,则实际上看到第一个广播报文,第二个是点到点的报文:

上面第一个报文指出以太网源地址是RTSG,目的地址是以太网广播地址,类型为16进制数0806(类型 ETHER_ARP),报文全
64字节。
 
下面给出一个实际例子,注意rarp协议号是16进制的0835

 
CTCP报文
注意:以下描述设您比较熟悉RFC793中讨论的TCP协议,否则,本文对您毫无意义。
 
一般说来,TCP协议的输出格式类似于:

Srcdst分别指源IP地址和目标IP地址,包括端口号;
FlagsS (SYN)F (FIN)P (PUSH) R (RST)或单独的表示没有置任何标志位的“.”,TCP首部中的其他两个标志ACKURGTcpdump将做特殊显示;
Data-seqno描述了IP数据报文分组的起始序号和隐含的终止序号,其格式是起始序号、冒号、终止序号、圆括弧内的数据字节数;
Ack表示确认序号,并且确定了希望接收的下个数据包的SYN号,只在首部ACK标志被置为1时才显示;
Window指定了连接建立后能够接收数据包的缓存大小,默认为4096
Urg只有在TCP首部中Urg标志被置为1时才显示,表明有紧急数据需要发送;
OptionsTCP首部后的选项,用尖括号括住(e.g., )
 
SrcDstFlags总是存在,其他字段依赖于数据报文的TCP头内容,只输出必要的部分。下面的例子表明了在浏览器中输入了“http://www.39.net/check.htm 后所捕获到的数据:

 
忽略前面三行,第一行表示主机172.16.3.99主动打开到主机219.235.232.171:80SYN连接,数据字节数为 0,窗口大小为65535,另外包含若干选项,(DF)表示没有IP分片;
第二行主机219.235.232.171:80被动打开到主机172.16.3.99SYN连接,并置ACK位,窗口大小为8760,包含若干选项,没有IP分片;
 
DUDP报文
一般地讲,UDP报文的输出格式通常使用rwho报文来演示:

这就是说将某UDP数据报文从主机actinidewho端口发送到主机broadcastwho端口,该数据报文包含84字节的数据。
根据其源/目的端口号,某些UDP服务能够识别并提供更多的高层协议信息,特别是Domain Name service requests (RFC-1034/1035) NFS RPC调用 (RFC-1050)
 
EUDP名字服务请求
注意:以下描述设您比较熟悉RFC1035中讨论的DNS,否则,本文对您毫无意义。
 
一般地讲,UDP名字服务请求的输出格式类似于:

 
下面给出一个实际的例子:

忽略前三行,第三行(红色行)代表的含义是这样的:
主机172.16.3.99向域名服务器219.235.232.140提交了域名查询服务,请求的查询类型是A,也就是说查询www.39.netIP地址,查询ID2,“+”表明设置了递归请求(recursion desired)标志。查询报文长度是28个字节,不包括UDPIP协议的头长度。
该查询操作是普通的Query查询,所以忽略了op域,如果op域有其他设置的话,则应该位于“2”和“+”之间,类似地,普通的C_IN类型qclass查询,也被忽略了,其他类型的qclass查询应该显示在“A”后面。
 
Tcpdump也会检查一些不规则的情况,相应的结果作额外的域放在方括号内(square brackets):如果某查询包含回答(answer)、名字服务(name server)或授权机构(authority),输出时会将ancountnscountarcount显示成“[na]”、“[nn]”或“[nau]”,其中n代表相应的数量。
如果在第二和第三字节中,如果任何应答位(response bits)被设置,如AA, RA rcode,或者任何“must be zero”位被设置,输出时就会显示“[b2&3=x]”,这里的x16进制数,表示报文头第二、第三字节的值。
 
FUDP名字服务回答
 
名字服务回答的格式类似于:

 
下面给出一个实际的例子:

 
第四行(红色行)代表的含义是这样的:
 
域名服务器219.235.232.140向主机172.16.3.99提交了有关查询号为2的域名查询应答,“1/0/0”表示1个应答(answer records)0个域名服务记录(name server records)0个授权机构记录(authority records)
第一个应答记录的类型是A类型的地址记录,其Internet地址是219.235.232.171,应答包长度是44字节,不包括UDPIP头长度。因为是A记录的class(C_IN),所以忽略了op(query)和应答代码(NoError)
 
第四行(红色行)代表的含义是这样的:
域名服务器所提供的对1号查询的应答是:域名不存在(NXDomain),只有1个域名服务记录,应答包长度为105字节。
其中“*”表示已经设置了权威应答(authoritative answer),由于没有应答记录,这里就不显示typeclassdata了。
另外,也可能输出其他的标志符号,如“-(recursion available, RA,没有设置)和“| (truncated message, TC,设置),如果“question”部分没有包含任何有效的内容,在显示出“[nq]”。
注意到名字服务查询和应答包一般都比较大,68字节长的snaplen可能无法捕捉到足够的报文内容,您可以使用-s选项增大捕捉缓冲区,如“-s 128”,效果应该就不错了。
 
综合UDP名字服务的查询和应答,下面给出本次测试的一个实际例子。
 
下面是在dos状态下提出的域名查询:

 
下面是用tcpdump捕获到的数据报文:

 
GIP分片
如果存在IP分片,则数据报文的输出格式类似于:

(前一行表示存在更多的分片,后一行表示这是最后的一片)
id是分片的的标识号,size是分片大小,单位是字节,不包括IP头长度,offset是该分片在原始数据报文中的位移,单位也是字节。
输出的时候,每一分片的信息都将显示出来,第一个分片包含了高层协议的头信息,以后的分片不再包含高层协议信息,所以后续分片格式在显示了源/目的地址后,紧跟显示的就是分片信息。
下面给出一个例子,rtsgarizona下载576字节的FTP数据:

  •  
    •  
      •  
        •  
          •  
            •  
              •  
                •  
                  •  
                    •  

  •  
    •  
      •  
        •  
          •  
            •  
              •  
                •  
                  •  
                    •  

需要注意的是:
首先,第二行地址信息中不再包括端口信息,这是因为相关端口信息只存在于第一个分片内,后续分片无从知道相关信息,譬如端口信息和SYN号;
其次,从第一行可以看出用户有308字节的数据,加上20字节的头信息,所以第二行分片偏移从328开始,实际传输的用户数据是512字节(308+204)
最后,如果没有分片,则输出时在尾部显示“(DF)”信息。
 
H)时间戳
默认地,所有输出行都包括时间戳,表明了当前的时钟时间,格式类似于:

其精度和内核时钟相同,反映了内核收到数据报文的时间,从以太接口收到报文到内核响应“报文就绪” 中断有一个滞后, 该滞后不被考虑。有很多文档将frac说成什么ID标识,这肯定是不对的。
 
I)参考文档
后来发现1)、2)也还可以,就顺便将地址贴上来了。
1)Tcpdump Manual
2)  http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V51B_HTML/MAN/MAN8/0230____.HTM
3)  http://publib16.boulder.ibm.com/pseries/zh_CN/cmds/aixcmds5/tcpdump.htm