tcpdump抓包命令
tcpdump是一个用于截取网络分组,并输出分组内容的工具。tcpdump凭借强大的功能和灵活的截取策略,使其成为类UNIX系统下用于网络分析和问题排查的首选工具。
tcpdump提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具。tcpdump存在于基本的Linux系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备root权限的用户可以直接执行它来获取网络上的信息。因此系统中存在网络分析工具主要不是对本机安全的威胁,而是对网络上的其他计算机的安全存在威胁。
一、概述
顾名思义,tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。
# tcpdump -vv # -vv表示显示详细的信息
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
11:53:21.444591 IP (tos 0x10, ttl 64, id 19324, offset 0, flags [DF], proto 6, length: 92)
asptest.localdomain.ssh > 192.168.228.244.1858: P 3962132600:3962132652(52) ack 2726525936 win 1266
asptest.localdomain.1077 > 192.168.228.153.domain: [bad udp cksum 166e!] 325+ PTR? 244.228.168.192.in-addr.arpa. (46)
11:53:21.446929 IP (tos 0x0, ttl 64, id 42911, offset 0, flags [DF], proto 17, length: 151) 192.168.228.153.domain > asptest.localdomain.1077: 325 NXDomain q: PTR? 244.228.168.192.in-addr.arpa. 0/1/0 ns: 168.192.in-addr.arpa. (123)
11:53:21.447408 IP (tos 0x10, ttl 64, id 19328, offset 0, flags [DF], proto 6, length: 172) asptest.localdomain.ssh > 192.168.228.244.1858: P 168:300(132) ack 1 win 1266
<==按下[ctrl]-c之后结束
347 packets captured
1474 packets received by filter
745 packets dropped by kernel
不带参数的tcpdump会收集网络中所有的信息包头,数据量巨大,必须过滤。
二、选项介绍
tcpdump采用命令行方式,它的命令大致如下:
tcpdump [ -AbdDefhHIJKlLnNOpqStuUvxX# ] [ -B buffer_size ]
[ -c count ]
[ -C file_size ] [ -G rotate_seconds ] [ -F file ]
[ -i interface ] [ -j tstamp_type ] [ -m module ] [ -M secret ]
[ --number ] [ -Q in|out|inout ]
[ -r file ] [ -V file ] [ -s snaplen ] [ -T type ] [ -w file ]
[ -W filecount ]
[ -y datalinktype ] [ -z postrotate-command ] [ -Z user ]
[ --immediate-mode ]
[ expression ]
参数的含义如下:
参数 | 含义 |
---|---|
-A | 以ASCII格式打印出所有分组,通常用来抓取www的网页数据包数据。 |
-c | 在收到指定的数量的分组后,tcpdump就会停止。 |
-C | 在将一个原始分组写入文件之前,检查文件当前的大小是否超过了参数file_size 中指定的大小。如果超过了指定大小,则关闭当前文件,然后在打开一个新的文件。参数 file_size 的单位是兆字节(是1,000,000字节,而不是1,048,576字节)。 |
-d | 将匹配信息包的代码以人们能够理解的汇编格式给出。 |
-dd | 将匹配信息包的代码以c语言程序段的格式给出。 |
-ddd | 将匹配信息包的代码以十进制的形式给出。 |
-D | 打印出系统中所有可以用tcpdump截包的网络接口。 |
-e | 在输出行打印出数据链路层的头部信息,也就是使用数据链路层的MAC数据包数据来显示. |
-f | 将外部的Internet地址以数字的形式打印出来。 |
-F | 从指定的文件中读取表达式,忽略命令行中给出的表达式。 |
-i | 指定监听的网络接口。 |
-l | 使标准输出变为缓冲行形式,可以把数据导出到文件。 |
-L | 列出网络接口的已知数据链路。 |
-b | 在数据-链路层上选择协议,包括ip、arp、rarp、ipx都是这一层的。 |
-n | 不把网络地址转换成名字。 |
-nn | 不进行端口名称的转换。 |
-N | 不输出主机名中的域名部分。例如,‘nic.ddn.mil‘只输出’nic‘。 |
-t | 在输出的每一行不打印时间戳。 |
-O | 不运行分组分组匹配(packet-matching)代码优化程序。 |
-P | 不将网络接口设置成混杂模式。 |
-q | 快速输出。只输出较少的协议信息。 |
-r | 从指定的文件中读取包(这些包一般通过-w选项产生)。 |
-S | 将tcp的序列号以绝对值形式输出,而不是相对值。 |
-s | 从每个分组中读取最开始的snaplen个字节,而不是默认的68个字节。 |
-T | 将监听到的包直接解释为指定的类型的报文,常见的类型有rpc远程过程调用)和snmp(简单网络管理协议)。 |
-t | 不在每一行中输出时间戳。 |
-tt | 在每一行中输出非格式化的时间戳 |
-ttt | 输出本行和前面一行之间的时间差。 |
-tttt | 在每一行中输出由date处理的默认格式的时间戳。 |
-v | 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息。 |
-vv | 输出详细的报文信息。 |
-w | 直接将分组写入文件中,而不是不分析并打印出来。 |
-X | 可以列出16进制以及ASCII的数据包内容,对于监听数据包内容很有用. |
推荐的一些写法:
tcpdump -ntv -i xxx # -n表示不将网络地址转化为名称,-t不输出时间戳,-v输出一些比较详细的信息(这个很好用)
三、tcpdump的表达式介绍
表达式对应命令参数中最后的可省略的expression.tcpdump利用它作为过滤报文的条件,如果一个报文满足表 达式的条件,则这个报文将会被捕获。如果没有给出任何条件,则网络上所有的信息包 将会被截获。
表达式(expression)实际遵循的是bpf的语法,有关于bpf的相关介绍,可以查看这个页面:
https://biot.com/capstats/bpf.html,下面的部分,基本是此页面的翻译.
在表达式中一般如下几种类型的关键字:
表达式由一个或多个表达元组成(nt: primitive
, 表达元, 可理解为组成表达式的基本元素). 一个表达元通常由一个或多个修饰符(qualifiers
)后跟一个名字或数字表示的id组成(nt: 即, qualifiers id
).
有三种不同类型的修饰符(或者说限定符):type, dir以及 proto.
type 修饰符指定id 所代表的对象类型, id可以是名字也可以是数字. 可选的对象类型有: host, net, port 以及portrange(nt: host 表明id表示主机, net表明id是网络, port 表明id是端口, 而portrange表明id是一个端口范围). 如, host foo
, net 128.3
, port 20
, portrange 6000-6008
(nt: 分别表示主机foo, 网络128.3
, 端口20
, 端口范围 6000-6008
). 如果不指定type修饰符, id默认的修饰符为host.
dir 修饰符描述id 所对应的传输方向, 即发往id 还是从id 接收(nt: 而id到底指什么需要看其前面的type修饰符).可取的方向为: src, dst, src or dst, src and dst.(nt:分别表示, id是传输源, id是传输目的, id是传输源或者传输目的, id是传输源并且是传输目的). 例如, src foo
,dst net 128.3
, src or dst port ftp-data
.(nt: 分别表示符合条件的数据包中, 源主机是foo
, 目的网络是128.3
, 源或目的端口为 ftp-data
).如果不指定dir修饰符, id 默认的修饰符为src or dst.
proto修饰符描述id所属的协议. 常用的协议有: ether, wlan, ip, ip6, arp, rarp, tcp以及 upd.(nt | rt: ether可理解为物理以太网传输协议; wlan, 无线局域网协议; ip,ip6 即通常的TCP/IP协议栈中所使用的ipv4以及ipv6网络层协议;arp, rarp 即地址解析协议, 反向地址解析协议; tcp and udp, 即通常TCP/IP协议栈中的两个传输层协议).
例如, ether src foo
, arp net 128.3
, tcp port 21
, udp portrange 7000-7009
分别表示从以太网地址foo 来的数据包,发往或来自128.3网络的arp协议数据包, 发送或接收端口为21的 tcp协议数据包, 发送或接收端口范围为7000-7009的udp协议数据包.
如果不指定proto 修饰符, 则默认为与相应type匹配的修饰符.
例子:
-
src foo
含义是(ip or arp or rarp) src foo
(nt: 即, 来自主机foo
的ip/arp/rarp
协议数据包, 默认type
为host
). -
net bar
含义是(ip or arp or rarp) net bar
(nt: 即, 来自或发往bar
网络的ip/arp/rarp
协议数据包). -
port 53
含义是(tcp or udp) port 53
(nt: 即, 发送或接收端口为53
的tcp/udp
协议数据包).
对于修饰符后跟id的格式,可理解为, type id是对包最基本的过滤条件: 即对包相关的主机, 网络, 端口的限制; dir 表示对包的传送方向的限制; proto表示对包相关的协议限制)
除以上所描述的表达元('primitive'), 还有其他形式的表达元, 并且与上述表达元格式不同. 比如: gateway, broadcast, less, greater以及算术表达式(nt: 其中每一个都算一种新的表达元). 下面将会对这些表达元进行说明.
表达元之间还可以通过关键字and, or以及 not 进行连接, 从而可组成比较复杂的条件表达式. 比如,
host foo and not port ftp and not port ftp-data
(nt: 其过滤条件可理解为, 数据包的主机为foo
,并且端口不是ftp(端口21) 和ftp-data(端口20, 常用端口和名字的对应可在linux 系统中的/etc/service文件中找到)).
为了表示方便, 同样的修饰符可以被省略, 如tcp dst port ftp or ftp-data or domain
与以下的表达式含义相同tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain
.(nt: 其过滤条件可理解为,包的协议为tcp
, 目的端口为ftp
或 ftp-data
或 domain
(端口53) ).
可用的表达元
==========================================
dst host host
如果IPv4/v6 数据包的目的ip地址是host, 那么捕获该数据包.host 可以是一个ip地址, 也可以是一个主机名.
src host host
如果IPv4/v6 数据包的源ip地址是host, 则捕获该数据包.host 可以是一个ip地址, 也可以是一个主机名.
host host
如果IPv4/v6数据包的源或目的ip地址是host, 则捕获该数据包.以上的几个host 表达式之前可以添加以下关键字:ip, arp, rarp, 以及 ip6.比如:
ip host host
也可以表达为:
ether proto \ip and host host # 这种表达方式在下面有说明, 其中ip之前需要有\来转义,因为ip 对tcpdump 来说已经是一个关键字了.
如果host是一个拥有多个IP的主机, 那么任何一个地址都会用于包的匹配(nt: 即发向host 的数据包的目的地址可以是这几个IP中的任何一个, 从host 接收的数据包的源地址也可以是这几个IP中的任何一个).
==========================================
ether dst ehost
如果数据包(nt: 指tcpdump 可抓取的数据包, 包括ip 数据包, tcp数据包)的以太网目标地址是ehost,则捕获该数据包.
ehost 可以是/etc/ethers 文件中的名字或一个数字地址(nt: 可通过 man ethers 看到对/etc/ethers 文件的描述, 样例中用的是数字地址)
ether src ehost
如果数据包的以太网源地址是ehost(mac地址), 则捕获该数据包.
ether host ehost
如果数据包的以太网源地址或目标地址是ehost, 则捕获该数据包..
==========================================
dst net net
如果数据包的目标地址(IPv4或IPv6格式)的网络号字段为net, 则捕获该数据包.
net可以是从网络数据库文件/etc/networks 中的名字, 也可以用数字形式的来表示.
一个数字IPv4 网络号可以用点分四元组(比如, 192.168.1.0
), 或点分三元组(比如, 192.168.1
), 或点分二元组(比如, 172.16
), 或单一单元组(比如,10
)来表示.
这四种情况对应的网络掩码分别为:四元组:255.255.255.255
(这实际上已经是是一个具体的网络地址了),三元组:255.255.255.0
, 二元组:255.255.0.0
, 一元组:255.0.0.0
.
src net net
如果数据包的源地址(IPv4或IPv6格式)的网络号字段为 net, 则捕获该数据包.
net net
如果数据包的源或目的地址(IPv4或IPv6格式)的网络号字段为 net, 则捕获该数据包.
net net mask netmask
如果数据包的源或目的ip地址的网络掩码与netmask匹配, 则捕获该数据包.
此选项之前还可以配合src和dst来进一步限定数据包的来源,比如.
src net 192.168.1.0 mask 255.255.255.0
net net/len
如果数据包的源或目的地址(IPv4或IPv6格式)的属于该网段(net/len表示的网段), 则捕获该数据包.
此选项之前还可以配合src和dst来进一步限定数据包的来源.
src net 192.168.1.0/24 # 表示需要匹配源地址的网络编号有24位的数据包
dst port port
如果数据包(包括ip/tcp, ip/udp, ip6/tcp or ip6/udp协议)的目的端口为port, 则捕获该数据包.
port 可以是一个数字也可以是一个名字(相应名字可以在/etc/services 中找到该名字, 也可以通过man tcp
和man udp
来得到相关描述信息 ). 推荐使用数字.
dst port 80 # 监听目的端口为80的数据包
src port port
如果数据包的源端口为port, 则捕获该数据包.
port port
如果数据包的源或目的端口为port, 则捕获该数据包.
==========================================
dst portrange port1-port2
监听目的端口在[port1, port2]的数据包,当然,既然存在端口,那么这个数据包必然属于ip/tcp, ip/udp, ip6/tcp 或者ip6/udp这几种中的一种.
src portrange port1-port2
监听源端口在[port1, port2]范围内的数据包.
portrange port1-port2
如果数据包的源端口或目的端口在[port1,port2]这个端口范围, 则捕获该数据包.以上关于port 的选项都可以在其前面添加关键字:tcp 或者udp对数据包加以更严格的限定.
tcp src port 80 # 抓取源端口是80的tcp数据包
==========================================
less length
如果数据包的长度比length 小或等于length, 则捕获该数据包. 这与len <= length
的含义一致.
greater length
如果数据包的长度比length 大或等于length, 则捕获该数据包. 这与len >= length
的含义一致.
==========================================
ip proto protocol
如果数据包为ipv4数据包并且其协议类型为protocol, 则与此对应的条件表达式为真.protocol可以是一个数字也可以是名字, 比如:icmp, pim, udp, tcp等. 由于tcp , udp 以及icmp是tcpdump 的关键字,所以在这些协议名字之前必须要用\来进行转义(如果在C-shell 中需要用\来进行转义). 有时候为了书写方便,我们可以直接用tcp, upd, icmp来替换,这个其实是
ip proto p or ip6 proto p
的缩写,p指代tcp,upd以及icmp.
tcpdump -i eth0 'ip proto \tcp and host 192.168.3.144
则只打印主机192.168.3.144
发出或接收的数据包中tcp 协议头所包含的信息)
==========================================
ether broadcast
如果数据包是以太网广播数据包, 则捕获该数据包. ether 关键字是可选的.
ip broadcast
如果数据包是IPv4广播数据包, 则捕获该数据包.
==========================================
ether multicast
如果数据包是一个以太网多点广播数据包,则捕获该数据包.关键字ether可以省略.
ip multicast
如果数据包是ipv4多点广播数据包, 则捕获该数据包.
==========================================
ether proto protocol
如果数据包属于以下以太协议类型, 则与此对应的条件表达式为真.协议(protocol)字段, 可以是数字或以下所列出的名字: ip, ip6, arp, rarp, stp(Spanning tree protocol, 生成树协议, 可用于防止网络中产生链接循环)等.必须要注意的是如果标识符也是关键字, 从而必须通过\来进行转义.
有时候为了书写方便,我们往往直接使用ip, ip6, arp, rarp, aarp, decnet, stp来代替,它们其实是
ether proto p
的一个省略形式,p表示ip, ip6...
expr relop expr
如果关系为真,就抓取此类数据包. relop可以是>, <, >=, <=, =, !=之一, expr是一个算数表达式,它由整数常量,常规的二进制操作符,如[+, -, *, /, &, |, <<, >>],长度操作符,包数据访问器组成.值得注意的是,所有的组成部分都是无符号的,举个例子, 0x80000000 and 0xffffffff 大于0.可以使用下面的语法,来获取包中的数据:
proto [ expr : size ]
proto字段可以是 ether, fddi, wlan, ip, arp, rarp, tcp, udp, icmp, ip6等协议的名称,expr用于描述比特偏移,size是可选的,表示我们只对从偏移处开始的size字节的数据感兴趣,如果没有的话,默认值为1.
举个例子, ether[0] & 1 != 0
可以抓取所有的多播流量,表达式ip[0] & 0xf != 5
可以抓取到所有的带选项的ipv4包,表达式ip[6:2] & 0x1fff = 0
可以抓取到所有未分片的ipv4包以及第一个ipv4分片包.
一些偏移量以及字段的值可以用名称来直接描述,比如说icmptype (ICMP type字段), icmpcode (ICMP code字段), 以及tcpflags (TCP flags字段).
以下的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 flags字段的值是合法的: tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg.
四、输出结果介绍
下面我们介绍几种典型的tcpdump命令的输出信息
(1) 数据链路层头信息
使用命令:
#tcpdump --e host ICE
ICE是一台装有linux的主机。它的MAC地址是0:90:27:58:AF:1A
, H219是一台装有Solaris的SUN工作站。它的MAC地址是8:0:20:79:5B:46
.
上一条命令的输出结果如下所示:
21:50:12.847509 eth0 < 8:0:20:79:5b:46 0:90:27:58:af:1a ip 60: h219.33357 > ICE. telne t 0:0(0) ack 22535 win 8760 (DF)
21:50:12
是显示的时间, 847509
是ID号,eth0 >
表示从网络接口eth0
接收该分组, 同理eth0 >
表示从网络接口设备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。
(2) ARP包的tcpdump输出信息
使用命令:
#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 reply route is-at 0:90:27:12:10:66 (0:90:27:58:af:1a)
22:32:42是时间戳, 802509是ID号, eth0 >表明从主机发出该分组,arp表明是ARP请求包, who-has route tell ICE表明是主机ICE请求主机route的MAC地址。 0:90:27:58:af:1a 是主机 ICE的MAC地址。
(3) TCP包的输出信息
用tcpdump捕获的TCP包的一般输出信息是:
src > dst: flags data-seqno ack window urgent options
src > dst:表明从源地址到目的地址, flags是TCP报文中的标志信息,具体描述如下:
标识 | 字符缩写 | 描述 |
---|---|---|
S | SYN | 同步标识 |
F | FIN | 终止标识 |
R | RST | 复位标识 |
P | PSH | 推送标识 |
. | 以上四个标识bit全部为0 |
data-seqno是报文中的数据的顺序号, ack是下次期望的顺序号, window是接收缓存的窗口大小, urgent表明 报文中是否有紧急指针。 Options是选项。
(4) UDP包的输出信息
用tcpdump捕获的UDP包的一般输出信息是:
route.port1 > ICE.port2: udp lenth
UDP十分简单,上面的输出行表明从主机route的port1端口发出的一个UDP报文 到主机ICE的port2端口,类型是UDP, 包的长度是lenth。
五、举例
(1) 想要截获所有210.27.48.1 的主机收到的和发出的所有的分组:
#tcpdump host 210.27.48.1
(2) 想要截获主机210.27.48.1 和主机210.27.48.2或210.27.48.3的通信,使用命令(注意:括号前的反斜杠是必须的):
#tcpdump host 210.27.48.1 and \(210.27.48.2 or 210.27.48.3 \)
(3) 如果想要获取主机210.27.48.1除了和主机210.27.48.2之外所有主机通信的ip包,使用命令:
#tcpdump ip host 210.27.48.1 and ! 210.27.48.2
(4) 如果想要获取主机192.168.228.246接收或发出的ssh包,并且不转换主机名使用如下命令:
#tcpdump -nn -n src host 192.168.228.246 and port 22 and tcp
(5) 获取主机192.168.228.246接收或发出的ssh包,并把mac地址也一同显示:
# tcpdump -e src host 192.168.228.246 and port 22 and tcp -n -nn
(6) 过滤的是源主机为192.168.0.1与目的网络为192.168.0.0的报头:
tcpdump src host 192.168.0.1 and dst net 192.168.0.0/24
(7) 过滤源主机物理地址为XXX的报头:
tcpdump ether src 00:50:04:BA:9B and dst……
(为什么ether src后面没有host或者net?物理地址当然不可能有网络喽)。
(8) 过滤源主机192.168.0.1和目的端口不是telnet的报头,并导入到tes.t.txt文件中:
Tcpdump src host 192.168.0.1 and dst port not telnet -l > test.txt
ip icmp arp rarp 和 tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型。
六.man手册中的一些例子
打印所有进入或离开主机sundown的数据包.
tcpdump host sundown
打印主机helios 与主机** hot** 或者与 主机ace 之间通信的数据包
tcpdump host helios and \( hot or ace \)
打印主机ace 与 任何其他主机之间通信的IP 数据包, 但不包括与helios之间的数据包.
tcpdump ip host ace and not helios
打印本地主机与Berkeley网络上的主机之间的所有通信数据包.
tcpdump net ucb-ether
打印所有源地址或目标地址是本地主机的IP数据包(如果本地网络通过网关连到了另一网络, 则另一网络并不能算作本地网络.localnet在 实际使用时要真正替换成本地网络的名字.
tcpdump ip and not net localnet
打印长度超过576字节, 并且网关地址是snup的IP数据包
tcpdump 'gateway snup and ip[2:2] > 576'
以下列出了tcp, ip头的结构, 以方便查看(需要以等宽字体查看).
TCP 头格式(rfc793)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IPV4 头格式(rfc791)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
七.输出格式
tcpdump 的输出格式与协议有关. 以下简要描述了大部分常用的格式及相关例子.
链路层头
ARP/RARP 数据包
tcpdump对arp/rarp包的输出信息中会包含请求类型及该请求对应的参数. 显示格式简洁明了. 以下是从主机rtsg到主机csam的rlogin
(远程登录)过程开始阶段的数据包样例:
arp who-has csam tell rtsg
arp reply csam is-at CSAM
第一行表示:rtsg
发送了一个arp数据包(nt:向全网段发送,arp数据包)以询问csam
的以太网地址,csam以她自己的以太网地址做了回应(在这个例子中, 以太网地址以大写的名字标识, 而internet地址(即ip地址)以全部的小写名字标识).
如果使用tcpdump -n
, 可以清晰看到以太网以及ip地址而不是名字标识:
arp who-has 128.3.254.6 tell 128.3.254.68
arp reply 128.3.254.6 is-at 02:07:01:00:01:c4
如果我们使用tcpdump -e
, 则可以清晰的看到第一个数据包是全网广播的, 而第二个数据包是点对点的:
RTSG Broadcast 0806 64: arp who-has csam tell rtsg
CSAM RTSG 0806 64: arp reply csam is-at CSAM
第一个数据包表明:以arp包的源以太地址是RTSG, 目标地址是全以太网段, type域的值为16进制0806(表示ETHER_ARP即arp包的类型标识).包的总长度为64字节.
TCP 数据包
通常tcpdump对tcp数据包的显示格式如下:
src > dst: flags data-seqno ack window urgent options
src 和 dst 是源和目的IP地址以及相应的端口. flags 标志由S(SYN), F(FIN), P(PUSH, R(RST)等组成,
单独一个.
表示没有flags标识. 数据段顺序号(Data-seqno)描述了此包中数据所对应序列号空间中的一个位置.
ack描述的是同一个连接,同一个方向,下一个本端应该接收的(对方应该发送的)数据片段的顺序号.
window是本端可用的数据接收缓冲区的大小(也是对方发送数据时需根据这个大小来组织数据).
urg(urgent) 表示数据包中有紧急的数据. options 描述了tcp的一些选项, 这些选项都用尖括号来表示(如 <mss 1024>
).
src, dst 和 flags 这三个域总是会被显示. 其他域的显示与否依赖于tcp协议头里的信息.
下面是一个从主机trsg到csam的一个rlogin应用登录的开始阶段.
rtsg.1023 > csam.login: S 768512:768512(0) win 4096 <mss 1024>
csam.login > rtsg.1023: S 947648:947648(0) ack 768513 win 4096 <mss 1024>
rtsg.1023 > csam.login: . ack 1 win 4096
rtsg.1023 > csam.login: P 1:2(1) ack 1 win 4096
csam.login > rtsg.1023: . ack 2 win 4096
rtsg.1023 > csam.login: P 2:21(19) ack 1 win 4096
csam.login > rtsg.1023: P 1:2(1) ack 21 win 4077
csam.login > rtsg.1023: P 2:3(1) ack 21 win 4077 urg 1
csam.login > rtsg.1023: P 3:4(1) ack 21 win 4077 urg 1
第一行表示有一个数据包从rtsg主机的tcp端口1023发送到了csam主机的tcp端口login上. S表示设置了SYN标志. 包的顺序号是768512, 并且没有包含数据.
如果包含有数据,那么数据的表示格式为:first:last(nbytes)
, 其含义是此包中数据的顺序号从first开始直到last结束,不包括last. 并且总共包含nbytes的用户数据.
没有捎带应答即ack, 可用的接受窗口的大小为4096bytes, 并且请求端(rtsg)的最大可接受的数据段大小是1024字节.
主机csam 向主机rtsg 回复了基本相同的SYN数据包, 其区别只是多了一个piggy-backed ack
(nt:捎带回的ack应答, 针对rtsg的SYN数据包).
rtsg 同样针对csam的SYN数据包回复了一ACK数据包作为应答. .
的含义就是此包中没有标志被设置. 由于此应答包中不含有数据, 所以包中也没有数据段序列号.
提醒! 此ACK数据包的顺序号只是一个小整数1. 有如下解释:tcpdump对于一个tcp连接上的会话, 只打印会话两端的初始数据包的序列号,其后相应数据包只打印出与初始包序列号的差异.即初始序列号之后的序列号, 可被看作此会话上当前所传数据片段在整个要传输的数据中的'相对字节'位置(nt:双方的第一个位置都是1, 即'相对字节'的开始编号). -S
将覆盖这个功能,使数据包的原始顺序号被打印出来.
第六行的含义为:主机rtsg 向 主机csam发送了19字节的数据(字节的编号为2到20,传送方向为rtsg到csam). 包中设置了PUSH标志.
在第7行,主机csam回应道, 她已经从主机rtsg中收到了21以下的字节, 但不包括21编号的字节. 这些字节存放在主机csam的socket的接收缓冲中, 相应地,csam的接收缓冲窗口大小会减少19字节(nt:可以从第5行和第7行win属性值的变化看出来). csam在第7行这个包中也向rtsg发送了一个字节. 在第8行和第9行, csam 继续向rtsg 分别发送了两个只包含一个字节的数据包, 并且这个数据包带PUSH标志.
如果头部含有虚假的属性信息(比如其长度属性其实比头部实际长度长或短), tcpdump会为该头部显示[bad opt]
.
如果头部的长度告诉我们某些选项(nt | rt:从下文来看, 指tcp包的头部中针对ip包的一些选项, 回头再翻)会在此包中,而真正的IP(数据包的长度又不够容纳这些选项, tcpdump会显示[bad hdr length]
.
UDP 数据包
UDP 数据包的显示格式,可通过rwho这个具体应用所产生的数据包来说明:
actinide.who > broadcast.who: udp 84
其含义为:actinide主机上的端口who向broadcast主机上的端口who发送了一个udp数据包.这个数据包包含有84个字节的用户数据.
一些UDP服务可通过数据包的源或目的端口来辨别,也可从所显示的更高层协议信息来识别. 比如, Domain Name service requests(DNS 请求).
UDP 名称服务请求
名称服务请求有如下的格式:
src > dst: id op? flags qtype qclass name (len)
比如有一个实际显示为:
h2opolo.1538 > helios.domain: 3+ A? ucbvax.berkeley.edu. (37)
主机h2opolo 向主机helios 上运行的名称服务器查询ucbvax.berkeley.edu
的地址记录(nt: qtype等于A). 此查询本身的id号为3
.
符号+
意味着递归查询标志被设置(nt: dns服务器可向更高层dns服务器查询本服务器不包含的地址记录). 这个最终通过IP包发送的查询请求数据长度为37字节, 其中不包括UDP和IP协议的头数据.
因为此查询操作为默认值(nt | rt: normal one的理解), op字段被省略.如果op字段没被省略, 会被显示在3
和+
之间. 同样, qclass也是默认值, C_IN, 从而也没被显示, 如果没被忽略, 她会被显示在A
之后.
UDP 名称服务应答
对名称服务应答的数据包,tcpdump会有如下的显示格式
src > dst: id op rcode flags a/n/au type class data (len)
比如具体显示如下:
helios.domain > h2opolo.1538: 3 3/3/7 A 128.32.137.3 (273)
helios.domain > h2opolo.1537: 2 NXDomain* 0/1/0 (97)
第一行表示: 主机helios 对主机h2opolo所发送的3号查询请求回应了3条回答记录(nt | rt: answer records), 3条名称服务器记录,以及7条附加的记录. 第一个回答记录(nt: 3个回答记录中的第一个)类型为A(nt: 表示地址), 其数据为internet地址128.32.137.3
.此回应UDP数据包, 包含273字节的数据(不包含UPD和IP的头部数据). op字段和rcode字段被忽略(nt: op的实际值为Query, rcode, 即response code的实际值为NoError), 同样被忽略的字段还有class 字段(nt | rt: 其值为C_IN, 这也是A类型记录默认取值)
第二行表示: helios对h2opolo所发送的2号查询请求做了回应. 回应中, rcode编码为NXDomain(nt: 表示不存在的域)), 没有回答记录,但包含一个名称服务器记录, 不包含权威服务器记录(nt | ck: 从上文来看, 此处的authority records 就是上文中对应的additional records).
*
表示权威服务器回答标志被设置(nt: 从而additional records就表示的是authority records).
由于没有回答记录, type, class, data字段都被忽略.
flag字段还有可能出现其他一些字符, 比如-
(nt: 表示可递归地查询, 即RA 标志没有被设置), |
(nt: 表示被截断的消息, 即TC 标志被置位). 如果应答(nt | ct: 可理解为, 包含名称服务应答的UDP数据包, tcpdump知道这类数据包该怎样解析其数据)的'question'段一个条目(entry)都不包含(nt: 每个条目的含义, 需补充),'[nq]' 会被打印出来.
要注意的是:名称服务器的请求和应答数据量比较大, 而默认的68字节的抓取长度(nt: snaplen, 可理解为tcpdump的一个设置选项)可能不足以抓取数据包的全部内容. 如果你真的需要仔细查看名称服务器的负载, 可以通过tcpdump 的-s 选项来扩大snaplen值.
IP 数据包分片
IP分片数据包(nt: 即一个大的IP数据包切分后生成的小IP数据包)有如下两种显示格式.
(frag id:size@offset+)
(frag id:size@offset)
(第一种格式表示, 此分片之后还有后续分片. 第二种格式表示, 此分片为最后一个碎片.)
id 表示分片的编号( 每个小IP包被分配一个分片编号, 以便区分各个小分片).
size表示此分片的大小 , 不包含分片头部数据.
offset表示此分片所含数据在原始整个IP包中的偏移.
每个分片都会使tcpdump产生相应的输出打印. 第一个分片包含了高层协议的头数据(nt:从下文来看, 被破碎IP数据包中相应tcp头以及IP头都放在了第一个碎片中 ), 从而tcpdump会针对第一个分片显示这些信息, 并接着显示此分片本身的信息. 其后的一些分片并不包含高层协议头信息, 从而只会在显示源和目的之后显示分片本身的信息. 以下有一个例子:
这是一个从arizona.edu
到lbl-rtsg.arpa
途经CSNET网络的ftp应用通信片段:
arizona.ftp-data > rtsg.1170: . 1024:1332(308) ack 1 win 4096 (frag 595a:328@0+)
arizona > rtsg: (frag 595a:204@328)
rtsg.1170 > arizona.ftp-data: . ack 1536 win 2560
有几点值得注意:
第一, 第二行的打印中, 地址后面没有端口号.
这是因为TCP协议信息都放到了第一个分片中, 当显示第二个分片时, 我们无法知道此分片所对应TCP包的顺序号.
第二, 从第一行的信息中, 可以发现主机arizona向rtsg发送308字节的用户数据, 而事实是, 相应IP包经分片后会总共产生512字节数据(第一个分片包含308字节的数据, 第二个分片包含204个字节的数据, 这超过了308字节).
如果你在查找数据包的顺序号空间中的一些空洞(nt: hole,空洞, 指数据包之间的顺序号没有上下衔接上), 512这个数据就足够使你迷茫一阵(nt: 其实只要关注308就行,不必关注分片后的数据总量).
一个IP数据包如果带有非IP分片标志, 则显示时会在最后显示(DF).
时间戳
tcpdump的所有输出打印行中都会默认包含时间戳信息.
时间戳信息的显示格式如下
hh:mm:ss.frac (nt: 小时:分钟:秒.(nt: frac未知, 需补充))
此时间戳的精度与内核时间精度一致, 反映的是内核第一次看到对应数据包的时间(nt: saw, 即可对该数据包进行操作). 而数据包从物理线路传递到内核的时间, 以及内核花费在此包上的中断处理时间都没有算进来.