拿来即用的网络数据采集分析工具 -- Tcpdump过滤组合

    技术2022-07-11  132

    理解 tcpdump 的输出

    tcpdump 输出的内容虽然多,却很规律。

    这里以我随便抓取的一个 tcp 包为例来看一下

    21:26:49.013621 IP 172.20.20.1.15605 > 172.20.20.2.5920: Flags [P.] , seq 49:97, ack 106048, win 4723, length 4

    从上面的输出来看,可以总结出:

    第一列:时分秒毫秒 21:26:49.013621 第二列:网络协议 IP 第三列:发送方的ip地址+端口号,其中172.20.20.1是 ip,而15605 是端口号 第四列:箭头 >, 表示数据流向 第五列:接收方的ip地址+端口号,其中 172.20.20.2 是 ip,而5920 是端口号 第六列:冒号 第七列:数据包内容,包括Flags 标识符,seq 号,ack 号,win 窗口,数据长度 length,其中 [P.] 表示 PUSH 标志位为 1,更多标识符见下面

    Flags 标识符 使用 tcpdump 抓包后,会遇到的 TCP 报文 Flags,有以下几种:

    [S] : SYN(开始连接) [P] : PSH(推送数据) [F] : FIN (结束连接) [R] : RST(重置连接) [.] : 没有 Flag,由于除了 SYN 包外所有的数据包都有ACK,所以一般这个标志也可表示 ACK

    常规过滤规则

    使用 host 就可以指定 host ip 进行过滤

    $ tcpdump host 192.168.10.100

    数据包的 ip 可以再细分为源ip和目标ip两种

    根据源ip进行过滤

    $ tcpdump -i eth2 src 192.168.10.100

    根据目标ip进行过滤

    $ tcpdump -i eth2 dst 192.168.10.200

    基于网段进行过滤:net 若你的ip范围是一个网段,可以直接这样指定

    $ tcpdump net 192.168.10.0/24

    网段同样可以再细分为源网段和目标网段

    根据源网段进行过滤

    $ tcpdump src net 192.168

    根据目标网段进行过滤

    $ tcpdump dst net 192.168

    基于端口进行过滤:port 使用 port 就可以指定特定端口进行过滤

    $ tcpdump port 8088

    端口同样可以再细分为源端口,目标端口

    根据源端口进行过滤

    $ tcpdump src port 8088

    根据目标端口进行过滤

    $ tcpdump dst port 8088

    如果你想要同时**指定两个端口你可以这样写**

    $ tcpdump port 80 or port 8088 但也可以简写成这样 $ tcpdump port 80 or 8088

    如果你的想抓取的不再是一两个端口,而是一个范围,一个一个指定就非常麻烦了,此时你可以这样指定一个端口段。

    $ tcpdump portrange 8000-8080 $ tcpdump src portrange 8000-8080 $ tcpdump dst portrange 8000-8080

    对于一些常见协议的默认端口,我们还可以直接使用协议名,而不用具体的端口号

    比如 http == 80,https == 443 等 $ tcpdump tcp port http

    **基于协议进行过滤**:proto 常见的网络协议有:tcp, udp, icmp, http, ip,ipv6 等

    若你只想查看 icmp 的包,可以直接这样写

    $ tcpdump icmp protocol 可选值:ip, ip6, arp, rarp, atalk, aarp, decnet, sca, lat, mopdl, moprc, iso, stp, ipx, or netbeui

    可选参数解析

    设置不解析域名提升速度

    -n:不把ip转化成域名,直接显示 ip,避免执行 DNS lookups 的过程,速度会快很多 -nn:不把协议和端口号转化成名字,速度也会快很多。 -N:不打印出host 的域名部分.。比如,,如果设置了此选现,tcpdump 将会打印'nic' 而不是 'nic.ddn.mil'.

    过滤结果输出到文件 使用 tcpdump 工具抓到包后,往往需要再借助其他的工具进行分析,比如常见的 wireshark 。 而要使用wireshark ,我们得将 tcpdump 抓到的包数据生成到文件中,最后再使用 wireshark 打开它即可。 使用 -w 参数后接一个以 .pcap 后缀命令的文件名,就可以将 tcpdump 抓到的数据保存到文件中。

    tcpdump icmp -w icmp.pcap

    控制详细内容的输出

    -v:产生详细的输出. 比如包的TTL,id标识,数据包长度,以及IP包的一些选项。同时它还会打开一些附加的包完整性检测,比如对IP或ICMP包头部的校验和。 -vv:产生比-v更详细的输出. 比如NFS回应包中的附加域将会被打印, SMB数据包也会被完全解码。(摘自网络,目前我还未使用过) -vvv:产生比-vv更详细的输出。比如 telent 时所使用的SB, SE 选项将会被打印, 如果telnet同时使用的是图形界面,其相应的图形选项将会以16进制的方式打印出来(摘自网络,目前我还未使用过)

    控制时间的显示

    -t:在每行的输出中不输出时间 -tt:在每行的输出中会输出时间戳 -ttt:输出每两行打印的时间间隔(以毫秒为单位) -tttt:在每行打印的时间戳之前添加日期的打印(此种选项,输出的时间最直观)

    显示数据包的头部

    -x:以16进制的形式打印每个包的头部数据(但不包括数据链路层的头部) -xx:以16进制的形式打印每个包的头部数据(包括数据链路层的头部) -X:以16进制和 ASCII码形式打印出每个包的数据(但不包括连接层的头部),这在分析一些新协议的数据包很方便。 -XX:以16进制和 ASCII码形式打印出每个包的数据(包括连接层的头部),这在分析一些新协议的数据包很方便。

    过滤指定网卡的数据包

    -i:指定要过滤的网卡接口,如果要查看所有网卡,可以 -i any

    过滤特定流向的数据包

    -Q:选择是入方向还是出方向的数据包,可选项有:in, out, inout,也可以使用 --direction=[direction] 这种写法

    其他常用的一些参数

    -A:以ASCII码方式显示每一个数据包(不显示链路层头部信息). 在抓取包含网页数据的数据包时, 可方便查看数据 -l : 基于行的输出,便于你保存查看,或者交给其它工具分析 -q : 简洁地打印输出。即打印很少的协议相关信息, 从而输出行都比较简短. -c : 捕获 count 个包 tcpdump 就退出 -s : tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s number, number 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。 -S : 使用绝对序列号,而不是相对序列号 -C:file-size,tcpdump 在把原始数据包直接保存到文件中之前, 检查此文件大小是否超过file-size. 如果超过了, 将关闭此文件,另创一个文件继续用于原始数据包的记录. 新创建的文件名与-w 选项指定的文件名一致, 但文件名后多了一个数字.该数字会从1开始随着新创建文件的增多而增加. file-size的单位是百万字节(nt: 这里指1,000,000个字节,并非1,048,576个字节, 后者是以1024字节为1k, 1024k字节为1M计算所得, 即1M=1024 * 1024 = 1,048,576) -F:使用file 文件作为过滤条件表达式的输入, 此时命令行上的输入将被忽略.

    对输出内容进行控制的参数

    -D : 显示所有可用网络接口的列表 -e : 每行的打印输出中将包括数据包的数据链路层头部信息 -E : 揭秘IPSEC数据 -L :列出指定网络接口所支持的数据链路层的类型后退出 -Z:后接用户名,在抓包时会受到权限的限制。如果以root用户启动tcpdump,tcpdump将会有超级用户权限。 -d:打印出易读的包匹配码 -dd:以C语言的形式打印出包匹配码. -ddd:以十进制数的形式打印出包匹配码

    过滤规则组合 有编程基础的同学,对于下面三个逻辑运算符应该不陌生了吧

    and:所有的条件都需要满足,也可以表示为 && or:只要有一个条件满足就可以,也可以表示为 || not:取反,也可以使用 !

    举个例子,我想需要抓一个来自**10.5.2.3**发往任意主机的3389端口的包

    $ tcpdump src 10.5.2.3 and dst port 3389

    当你在使用多个过滤器进行组合时,有可能需要用到括号,而括号在 shell 中是特殊符号,因为你需要使用引号将其包含。例子如下:

    $ tcpdump 'src 10.0.2.4 and (dst port 3389 or 22)'

    而在单个过滤器里,常常会判断一条件是否成立,这时候,就要使用下面两个符号

    =:判断二者相等 ==:判断二者相等 !=:判断二者不相等

    当你使用这两个符号时,tcpdump 还提供了一些关键字的接口来方便我们进行判断,比如

    if:表示网卡接口名、 proc:表示进程名 pid:表示进程 id svc:表示 service class dir:表示方向,in 和 out eproc:表示 effective process name epid:表示 effective process ID

    比如我现在要过滤来自进程名为 nc 发出的流经 en0 网卡的数据包,或者不流经 en0 的入方向数据包,可以这样子写

    $ tcpdump "( if=en0 and proc =nc ) || (if != en0 and dir=in)"

    包大小进行过滤 若你想查看指定大小的数据包,也是可以的

    $ tcpdump less 32 $ tcpdump greater 64 $ tcpdump <= 128

    根据 mac 地址进行过滤 例子如下,其中 ehost 是记录在 /etc/ethers 里的 name

    $ tcpdump ether host [ehost] $ tcpdump ether dst [ehost] $ tcpdump ether src [ehost]

    **过滤通过指定网关的数据包**

    tcpdump gateway [host]

    **过滤广播/多播数据包**

    $ tcpdump ether broadcast $ tcpdump ether multicast $ tcpdump ip broadcast $ tcpdump ip multicast $ tcpdump ip6 multicast

    **提取 HTTP 的 User-Agent** 从 HTTP 请求头中提取 HTTP 用户代理:

    $ tcpdump -nn -A -s1500 -l | grep "User-Agent:"

    **通过 egrep 可以同时提取用户代理和主机名(或其他头文件):**

    $ tcpdump -nn -A -s1500 -l | egrep -i 'User-Agent:|Host:'

    **抓取 HTTP GET 和 POST 请求** 抓取 HTTP GET 请求包:

    $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420' #or $ tcpdump -vvAls0 | grep 'GET'

    可以抓取 HTTP POST 请求包:

    $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354' #or $ tcpdump -vvAls0 | grep 'POST'

    找出发包数最多的 IP 找出一段时间内发包最多的 IP,或者从一堆报文中找出发包最多的 IP,可以使用下面的命令:

    $ tcpdump -nnn -t -c 200 | cut -f 1,2,3,4 -d '.' | sort | uniq -c | sort -nr | head -n 20 cut -f 1,2,3,4 -d '.' :. 为分隔符,打印出每行的前四列。即 IP 地址。 sort | uniq -c : 排序并计数 sort -nr : 按照数值大小逆向排序

    抓取 DNS 请求和响应 DNS 的默认端口是 53,因此可以通过端口进行过滤

    $ tcpdump -i any -s0 port 53

    提取 HTTP 请求的 URL 提取 HTTP 请求的主机名和路径:

    $ tcpdump -s 0 -v -n -l | egrep -i "POST /|GET /|Host:"

    抓取 HTTP 有效数据包 抓取 80 端口的 HTTP 有效数据包,排除 TCP 连接建立过程的数据包(SYN / FIN / ACK):

    $ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
    Processed: 0.013, SQL: 9