tcpdump抓包命令
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利用它作为过滤报文的条件,如果一个报文满足表 达式的条件,则这个报文将会被捕获。如果没有给出任何条件,则网络上所有的信息包 将会被截获。
在表达式中一般如下几种类型的关键字:
表达式由一个或多个表达元组成(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, 则捕获该数据包.
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 net mask 255.255.255.0
==========================================
net net/len
如果数据包的源或目的地址(IPv4或IPv6格式)的属于该网段(net/len表示的网段), 则捕获该数据包.
此选项之前还可以配合src和dst来进一步限定数据包的来源.
src net net/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 port # 抓取源端口是port的tcp数据包
==========================================
less length
如果数据包的长度比length 小或等于length, 则捕获该数据包. 这与len <= length
的含义一致.
greater length
如果数据包的长度比length 大或等于length, 则捕获该数据包. 这与len >= length
的含义一致.
==========================================
ip proto protocol
如果数据包为ipv4数据包并且其协议类型为protocol, 则与此对应的条件表达式为真.protocol可以是一个数字也可以是名字, 比如:icmp6, pim, udp, ** tcp等. 由于tcp** , udp 以及icmp是tcpdump 的关键字,所以在这些协议名字之前必须要用\来进行转义(如果在C-shell 中需要用\来进行转义). 注意此表达元不会把数据包中协议头链中所有协议头内容全部打印出来(nt: 实际上只会打印指定协议的一些头部信息, 比如可以用
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, 生成树协议, 可用于防止网络中产生链接循环)等.必须要注意的是如果标识符也是关键字, 从而必须通过\来进行转义.
四、输出结果介绍
下面我们介绍几种典型的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, 即可对该数据包进行操作). 而数据包从物理线路传递到内核的时间, 以及内核花费在此包上的中断处理时间都没有算进来.