Linux tcpdump命令的用法详解

发布时间:2019-09-06编辑:脚本学堂
本文详细介绍下,linux中有关tcpdump命令的用法,一个可以根据使用者的定义对网络上的数据包进行截获的包分析工具,感兴趣的朋友参考下。
现在, 假设我们需要抓取带SYN标志的数据包, 而忽略它是否包含其他标志.(nt:只要带SYN就是我们想要的). 让我们来看看当一个含有
SYN-ACK的数据包(nt:SYN 和 ACK 标志都有), 来到时发生了什么:
|C|E|U|A|P|R|S|F|
|---------------|
|0 0 0 1 0 0 1 0|
|---------------|
|7 6 5 4 3 2 1 0|

13号字节的1号和4号位被置位, 其二进制的值为:
00010010

转换成十进制就是:

0*2^7 + 0*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 0*2^2 + 1*2^1 + 0*2 = 18(nt: 1 * 2^6 表示1乘以2的6次方, 也许这样更
清楚些, 即把原来表达中的指数7 6 ... 0挪到了下面来表达)

现在, 却不能只用'tcp[13] 18'作为tcpdump的过滤表达式, 因为这将导致只选择含有SYN-ACK标志的数据包, 其他的都被丢弃.
提醒一下自己, 我们的目标是: 只要包的SYN标志被设置就行, 其他的标志我们不理会.

为了达到我们的目标, 我们需要把13号字节的二进制值与其他的一个数做AND操作(nt:逻辑与)来得到SYN比特位的值. 目标是:只要SYN 被设置
就行, 于是我们就把她与上13号字节的SYN值(nt: 00000010).

00010010 SYN-ACK 00000010 SYN
AND 00000010 (we want SYN) AND 00000010 (we want SYN)
-------- --------
= 00000010 = 00000010

我们可以发现, 不管包的ACK或其他标志是否被设置, 以上的AND操作都会给我们相同的值, 其10进制表达就是2(2进制表达就是00000010).
从而我们知道, 对于带有SYN标志的数据包, 以下的表达式的结果总是真(true):

( ( value of octet 13 ) AND ( 2 ) ) ( 2 ) (nt: value of octet 13, 即13号字节的值)

灵感随之而来, 我们于是得到了如下的tcpdump 的过滤表达式
tcpdump -i xl0 'tcp[13] & 2 2'

注意, 单引号或反斜杆(nt: 这里用的是单引号)不能省略, 这可以防止shell对&的解释或替换.


UDP 数据包
UDP 数据包的显示格式,可通过rwho这个具体应用所产生的数据包来说明:
actinide.who > broadcast.who: udp 84

其含义为:actinide主机上的端口who向broadcast主机上的端口who发送了一个udp数据包(nt: actinide和broadcast都是指Internet地址).
这个数据包承载的用户数据为84个字节.

一些UDP服务可从数据包的源或目的端口来识别,也可从所显示的更高层协议信息来识别. 比如, Domain Name service requests(DNS 请求,
在RFC-1034/1035中), 和Sun RPC calls to NFS(对NFS服务器所发起的远程调用(nt: 即Sun RPC),在RFC-1050中有对远程调用的描述).

UDP 名称服务请求

(注意:以下的描述假设你对Domain Service protoco(nt:在RFC-103中有所描述), 否则你会发现以下描述就是天书(nt:希腊文天书,
不必理会, 吓吓你的, 接着看就行))

名称服务请求有如下的格式:
src > dst: id op? flags qtype qclass name (len)
(nt: 从下文来看, 格式应该是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'之后.

异常检查会在方括中显示出附加的域: 如果一个查询同时包含一个回应(nt: 可理解为, 对之前其他一个请求的回应), 并且此回应包含权威或附加记录段, 
ancount, nscout, arcount(nt: 具体字段含义需补充) 将被显示为'[na]', '[nn]', '[nau]', 其中n代表合适的计数. 如果包中以下
回应位(比如AA位, RA位, rcode位), 或者字节2或3中任何一个'必须为0'的位被置位(nt: 设置为1), '[b2&3]=x' 将被显示, 其中x表示
头部字节2与字节3进行与操作后的值.

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值.

SMB/CIFS 解码
tcpdump 已可以对SMB/CIFS/NBT相关应用的数据包内容进行解码(nt: 分别为'Server Message Block Common', 'Internet File System'
'在TCP/IP上实现的网络协议NETBIOS的简称'. 这几个服务通常使用UDP的137/138以及TCP的139端口). 原来的对IPX和NetBEUI SMB数据包的
解码能力依然可以被使用(nt: NetBEUI为NETBIOS的增强版本).


tcpdump默认只按照最简约模式对相应数据包进行解码, 如果我们想要详尽的解码信息可以使用其-v 启动选现. 要注意的是, -v 会产生非常详细的信息,
比如对单一的一个SMB数据包, 将产生一屏幕或更多的信息, 所以此选项, 确有需要才使用.

关于SMB数据包格式的信息, 以及每个域的含义可以参看www.cifs.org 或者samba.org 镜像站点的pub/samba/specs/ 目录. linux 上的SMB 补丁
(nt | rt: patch)由 Andrew Tridgell (tridge@samba.org)提供.


NFS 请求和回应

tcpdump对Sun NFS(网络文件系统)请求和回应的UDP数据包有如下格式的打印输出:
src.xid > dst.nfs: len op args
src.nfs > dst.xid: reply stat len op results

以下是一组具体的输出数据
sushi.6709 > wrl.nfs: 112 readlink fh 21,24/10.73165
wrl.nfs > sushi.6709: reply ok 40 readlink "../var"
sushi.201b > wrl.nfs:
144 lookup fh 9,74/4096.6878 "xcolors"
wrl.nfs > sushi.201b:
reply ok 128 lookup fh 9,74/4134.3150

第一行输出表明: 主机sushi向主机wrl发送了一个'交换请求'(nt: transaction), 此请求的id为6709(注意, 主机名字后是交换
请求id号, 而不是源端口号). 此请求数据为112字节, 其中不包括UDP和IP头部的长度. 操作类型为readlink(nt: 即此操作为读符号链接操作),
操作参数为fh 21,24/10.73165(nt: 可按实际运行环境, 解析如下, fd 表示描述的为文件句柄, 21,24 表示此句柄所对应设
备的主/从设备号对, 10表示此句柄所对应的i节点编号(nt:每个文件都会在操作系统中对应一个i节点, 限于unix类系统中),
73165是一个编号(nt: 可理解为标识此请求的一个随机数, 具体含义需补充)).

第二行中, wrl 做了'ok'的回应, 并且在results 字段中返回了sushi想要读的符号连接的真实目录(nt: 即sushi要求读的符号连接其实是一个目录).