一、前言tshark作为Wireshark的配套子命令,在CLI场景下能胜任Wireshark绝大部分功能,对于需要批量处理、筛选过滤、导出、统计分析、定制化输出等能力。
当然,tshark同时具备抓包和分析包的能力,简单理解为tshark是wireshark的CLI版本,但Linux端抓包基本上业界都会使用tcpdump,并且它基本能覆盖抓包的所有场景,如果想要了解tcpdump的用法,可以参照笔者总结的这篇文章。
因此本文将不再讲述tshark的抓包用法,而着重讲述tshark配合诸如grep、sed、awk等文本处理工具如何分析过滤报文、批量处理报文等,拿到我们想要的任何报文内容,这些都是图形化wireshark所做不到的,也是CLI与生俱来的优势。
二、各个发行版安装方式tshark是wireshark的子命令,默认情况下会携带,gentoo是另外,需要使用USE标记,以下是各发行版的安装命令:
发行版
安装命令
CentOS
yum install wireshark -y
Debian/Ubuntu
apt install wireshark -y
Archlinux
pacman -Syu wireshark
Gentoo
USE="tshark" emerge --ask wireshark
如果是Windows客户端,安装wireshark即可,tshark默认会被安装到wireshark所在路径。
三、用法案例及参数说明1.读取报文文件不做任何过滤(-r|--read-file)使用-r|--read-file参数读取抓包文件:
代码语言:shell复制tshark -r
2.禁止反向解析(-n/-N)1)禁止一切反向解析(-n)为了防止IP地址、端口等被反向解析为主机名、端口名时,-n参数较为常用,可以更直观看到交互的五元组信息,而不是别名形态:
代码语言:shell复制tshark -n -r
flag取值
含义
d
对于DNS包启用解析
m
启用MAC地址解析
n
启用网络地址解析
N
使用外部解析器(例如DNS)进行网络地址解析,n需要被同时启用才有效果
t
启用传输层端口解析
v
启用VLAN ID的名称解析
代码语言:shell复制tshark -N t -r
如果要同时启用多个解析,比如同时启用网络地址解析、传输层端口解析,可以是:
代码语言:shell复制tshark -N n -N t -r
也就是wireshark里的“解码为(Decode As)”功能,将特定协议层级,按照手动指定的协议解码输出。
简单理解为,匹配符合条件的包,并将这些包按照指定协议来解析输出一遍。
tshark在默认情况下会根据协议特征和端口标准来自动解码数据包,比如443端口会自动解析为SSL,无需额外指定-d参数,但在某些情况下,特定协议可能有多种变体或扩展,或者端口自定义后并且从协议特征分析有多种协议符合特征,而tshark的自动解码可能只是选择了其中一种,那么手动指定协议解析就派上用场。
执行tshark -d --help可以列出支持解码的过滤条件及协议:
代码语言:shell复制tshark -d --help|&grep tcp # 过滤TCP相关的过滤器因为tshark对于协议的自动解析能力基本上都能覆盖,手上目前还没有这种需要被手动指定协议来解码的场景,但还是可以做一些功能上的演示。
比如将TCP 80端口解码输出为ssh协议:
代码语言:shell复制tshark -r
但解码前它实际就是一条正常的HTTP stream:
又或者我们将DNS报文分别解码为rtp、quic协议:
代码语言:shell复制tshark -r dns.pcap -d 'udp.port==53,rtp'
tshark -r dns.pcap -d 'udp.port==53,quic'tshark会将符合特征的报文解码到我们指定的协议,当然这里不能跨协议解析,比如udp.port==80,http将udp端口80的包解码成HTTP协议这是不存在的,http是基于TCP的实现,不在一个协议栈里,无法解码。
上面的解码仅作为用法示例演示,没有任何意义,请注意辨别。
原始报文为DNS,tshark已经自动帮我们解码适配到正确的协议:
4.输出为特定格式(-T)指定输出格式可以是:ek|fields|json|jsonraw|pdml|ps|psml|tabs|text
比如输出为json格式可以是:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
其中fields格式需要配合-e来使用,不能单独使用,具体用法看下面的-e说明。
5.输出报文指定字段(-e)-e用来指定报文的某个协议字段,给-T选项处理输出为最终格式。
比如,只需要报文帧数、ip地址、端口、tcp或ip协议的字段并最终输出为fields,可以是:
代码语言:shell复制tshark -n -r
tshark -n -r
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
-E能接的参数有:
参数选项
默认
含义
bom=y|n
n
在输出前加上UTF-8字节顺序标记(十六进制ef、bb、bf);
header=y|n
n
打印一个使用-e作为输出第一行的字段名称头部;
separator=/t|/s|\
/t
设置字段分隔符;
occurrence=f|l|a
a
打印每个字段的第一次、最后一次或所有出现的内容;
aggregator=,|/s|\
,
设置用于每个字段内的分割字符。
quote=d|s|n
n
设置用于环绕字段的引号字符。
下面一一举例。
1)bom=y|nbom(byte-order mark)即字节顺序标记,它是插入到以UTF-8、UTF16或UTF-32编码Unicode文件开头的特殊标记,用来识别Unicode文件的编码类型。对于UTF-8来说,BOM并不是必须的,此选项也不常用,除非有这类需求格式场景。
通过-E bom=y 来启用BOM即可,tshark会在控制字段中插入BOM标记。
比如这条命令,我们指定打印输出某些字段,并且通过bom=y参数插入bom格式:
代码语言:shell复制tshark -n -r
2)header=y打印一个使用-e作为输出第一行的字段名称头部,前面已有演示,-e指定的字段,将会在第一行也打印出来这些字段名。
比如指定打印tcp绝对序列号以及五元组信息,可以是:
代码语言:shell复制tshark -n -r
设置分隔符为两个/t:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
比如下面这个包,通过IPIP封装,因此ip有内层和外层:
此时我们通过tshark来处理IP字段,occurrence的默认行为是a,即输出字段内所有的内容,会将两个IP都输出出来:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
比如将IP层的多个IP字段,用分号分割可以是:
代码语言:shell复制tshark -n -r
将每个输出字段用双引号引起来,通过quote=d来实现:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
1)端口复用场景(Tcp Port numbers reused)比如下面这个示例,在wireshark中打开,会显示前后文的依赖关系,比如第2帧提示的端口复用(tcp port numbers reused):
而如果直接使用tshark来看,是没有这个提示信息的:
加上-2参数,让它进行一次完整的前后文分析并将这些字段计算出来,则能正常显示:
代码语言:shell复制tshark -2 -n -r
3)分片重组场景(Reassembled in #frame)又或者分片场景,ping一个icmp大包,超过mtu后会分片传输,在wireshark打开后显示如下:
收到的request大包会分成两帧传输,而reply并不需要响应大包,字节数没有超过mtu,因此无需分片。
在tshark中打开则为:
提示有分段,但并没有明确提示哪个段对应哪个request的补充,进行二次分析后则可以明确提示:
代码语言:shell复制tshark -n -r
以上只是列举最常见的三个场景,其它场景不一一举例,进行二次分析往往可以更人性化提示前后报文的依赖相关性。
8.设置时间戳格式(-t)0)总览支持的格式及说明如下:
格式
说明
a
绝对时间,抓包的实际时间,不显示日期;
ad
带日期的绝对时间,显示格式为:YYYY-MM-DD;
adoy
年份的绝对天数,显示格式为:YYYY-DAY;
d
delta时间,相对于上一个frame的时间间隔;
dd
delta_displayed时间,相对于上一个已显示的frame的时间间隔;
e
epoch时间/Unix 时间,从1970 年 1 月 1 日 00:00:00(UTC)开始统计的秒数;
r
相对于第一个包的的相对时间;
u
UTC时间,不显示日期;
ud
UTC并且带日期的时间,显示为YYYY-MM-DD;
udoy
UTC时间并且带日期,天数为这一年的绝对天数,显示为:YYYY-DAY。
不指定时默认为r(relative),即相对第一个包的相对时间。
1)当前时区绝对时间(a)以下面这个包为例,以当前时区的绝对时间显示报文,不显示日期:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
4)相对于上一个报文的时间间隔(d)相当于上一个报文的时间间隔,则使用d:
代码语言:shell复制tshark -n -r
比如使用dd显示所有报文的时间:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
通过dd输出的时间,frame 4作为输出的第一个包作为时间参考系,所以时间为0,frame 6显示的时间是相对于frame 4的间隔时间;通过d输出的时间,frame 4的时间是相对于frame 3的间隔时间,frame 6的时间相对于frame 5的间隔时间。所以不难看出,dd的含义是:delta displayed,已经显示了的报文的相对时间。
6)epoch时间/Unix时间(e)epoch时间/Unix 时间,从1970 年 1 月 1 日 00:00:00(UTC)开始统计的秒数:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
8)不显示日期的UTC时间(u)以UTC时间显示,并且不显示日期,则可以使用u:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
上面的一些示例中,其实已经用到了-Y选项来过滤报文,只要你写的过滤表达式符合wireshark语法,就能被正常执行,wireshark语法可以参考官方文档。
1)示例1:通过http.host过滤想过滤到http host为某个值,可以是:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
3)示例3:过滤ARP报文过滤ARP报文,取出特定帧,可以是:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r http-keep-alive.pcap -Y 'tcp.flags.syn==1&&tcp.flags.ack==0'以上只是几个示例,涉及到各个场景的过滤用法,-Y都能完全支持。
10.统计分析报文(-z)使用tshark -z help可以查看支持的统计分析选项。
目前为止有169个统计分析选项,但常用的并不多。
下面将一一举例最常见的一些示例常见,如果你遇到的需要统计分析的场景并不在举例场景中,那么通过-z help去查看相匹配的场景选项即可。
1)统计分析IP会话(conv,ip)会话统计需要用到'conv,'作为前缀,表示的是conversation。
以这一条TCP流为例,统计会话:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -q -r
当然,也可以在统计结果后面来写过滤规则,比如只统计第一条流的结果:
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
当然它也支持过滤选项,比如只统计dns query baidu.com的请求,可以是:
代码语言:shell复制tshark -n -q -r
比如统计IP层,每个IP流入流出流量、包量可以是:
代码语言:shell复制tshark -n -q -r
当然,它也能指定过滤规则,比如只统计涉及到TLS传输的数据:
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
同理,它也支持指定过滤规则,过滤tls或者通信端口为58865、5228的数据可以是:
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
在tshark上的实现则是:
代码语言:shell复制tshark -n -q -r
代码语言:shell复制tshark -n -q -r
过滤警告级别的统计数据,可以是:
代码语言:shell复制tshark -n -q -r
那么在tshark的实现,可以是:
代码语言:shell复制tshark -q -n -r
时间上,wireshark默认是ad形式,如果你想的话,当然可以通过-t ad来指定。
流图形的参数格式为:flow,name,mode[,filter]
flow是固定字段,name取值范围为:
any:所有报文icmp:icmpicmpv6:icmpv6lbm_uim:UIMtcp:TCPmode取值范围为:
standard:所有地址network:网络地址,flter则为具体的过滤规则,符合wireshark语法就行。
再来看一个示例,图形化显示ICMP的交互过程:
代码语言:shell复制tshark -q -n -r
结合前面讲到过的二次分析(two-pass)场景,不妨指定-2参数看看效果:
代码语言:shell复制tshark -q -2 -n -r
当然,再最后面可以指定过滤规则,比如过滤icmp.seq==3:
代码语言:shell复制tshark -q -2 -n -r
10)显示两个节点之间的TCP/UDP流内容(follow)此选项格式为:follow,prot,mode,filter[,range]
follow是固定字段,prot表示传输协议(Protocols),可取范围如下:
取值
含义
tcp
TCP协议
udp
UDP协议
dccp
DCCP协议
tls
TLS 或 SSL 协议
http
HTTP流
http2
http2流
quic
quic流
mode来指定输出格式,取值如下:
取值
含义
ascii
ASCII格式输出,不可打印字符用点表示
ebcdic
EBCDIC格式输出,不可打印字符用点表示
hex
带偏移量的十六进制和ASCII数据
raw
十六进制数据
yaml
YAML格式
filter用来指定要显示的流,有如下三种格式:
格式
含义
ip-addr0:port0,ip-addr1:port1
指定IP地址和TCP、UDP或DCCP端口对(TCP端口用于TLS、HTTP和HTTP2;QUIC不支持地址和端口匹配);
stream-index
指定流索引,用于TCP、UDP、DCCP、TLS和HTTP(TLS和HTTP使用TCP流索引);
stream-index,substream-index
指定流和子流,用于HTTP/2和QUIC,因为它们使用多路复用/长连接(HTTP/2的TCP流和HTTP/2流索引、QUIC连接号和流ID)。
,range用于指定应该显示流的哪些部分。
①示例一:以“十六进制”格式显示第一个TCP流的内容代码语言:shell复制tshark -q -n -r
②示例二:显示IP1:PORT1和IP2:PORT2之间的TCP流的内容代码语言:shell复制tshark -q -n -r
代码语言:shell复制((ip.src eq 192.168.1.3 and tcp.srcport eq 58863) and (ip.dst eq 101.91.37.19 and tcp.dstport eq 443)) or ((ip.src eq 101.91.37.19 and tcp.srcport eq 443) and (ip.dst eq 192.168.1.3 and tcp.dstport eq 58863))③示例三:在第一个TCP连接中显示第一个HTTP的内容代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
此时还是在第一条TCP流中(tcp.stream==0),过滤的第4条HTTP请求的内容。
11)统计分析HTTP状态(http,stat)统计分析HTTP的状态码以及请求方法,可以使用如下命令:
代码语言:shell复制tshark -q -n -r
它自然也支持应用过滤规则,比如只过滤第一条TCP流对应的HTTP状态码和请求方法,可以是:
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
13)统计分析HTTP请求的URI路径(http_req,tree)http_req,tree 只会统计请求涉及到的URI资源路径,不关注响应:
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
17)统计协议层次结构及包量(io,phs)创建协议层次结构统计信息,列出数据包数和字节数:
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
其中io,stat是固定的,interval表示间隔时间,可以指定秒或小数秒或微秒,如果指定为0,将计算所有数据包的统计信息。
统计所有数据包的包量和字节大小:
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
io,stat是固定选项,interval表示间隔时间,其中的COUNT|SUM|MIN|MAX|AVG|LOAD都要基于过滤规则来做统计,比如:
代码语言:shell复制io,stat,0,'MAX(icmp.data_time_relative)icmp.data_time_relative'统计的是icmp响应时间字段,并取最大值MAX,0表示统计所有,不分间隔。
而如果要指定某个过滤规则,在最后面加,比如只统计到某个IP的最大的ICMP响应值情况,完整的命令为:
代码语言:shell复制tshark -q -n -r
又或者,统计第一条TCP连接中,距离它上一个包间隔时间最长的为:
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
再或者,只统计返回了200 OK状态码的http最大响应时间:
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
代码语言:shell复制tshark -q -n -r
21)统计源地址和目标地址占比(ip_srcdst,tree)将源地址和目的地址区分开来,则使用ip_srcdst,tree:
代码语言:shell复制tshark -q -n -r
代码语言:shell复制 tshark -q -n -r
11.完整展开报文(-V)-V参数会完整展开报文的每个字段、头部信息.
比如下面这个示例,将第一次握手的请求展开:
代码语言:shell复制tshark -n -r
比如通过正则来拿到我们想要的直播流URL:
代码语言:shell复制tshark -n -r
12.保存报文(-w)顾名思义,通过tshark处理完原始报文后,需要将过滤出来的报文保存到新的抓包文件,那么此参数就派上用场了。
比如过滤前300个报文,并且IP地址为A或B,或者目的端口为38388的HTTP报文,可以是:
代码语言:shell复制tshark -n -r
代码语言:shell复制tshark -n -r
四、总结tshark作为wireshark的命令行版本,很多功能其实都是一对一息息相关的,但tshark提供了命令行能力,对于自动化脚本分析有很大的帮助,可以轻松实现自动批量化处理抓包文件,并展示分析结果。
通过过滤、分析网络数据包,它为网络管理员、安全专家和开发人员提供了深入了解网络协议的机会。无论是监控网络流量、故障排除、安全审计还是协议分析,tshark都能发挥其巨大作用。从基本的捕获和过滤到高级的Lua定制,它提供了广泛的功能和应用,适用于各种场景。
本文详细讲述了每个参数的用法及使用示例,篇幅原因无法将每种可能写进去,网络协议本身具备多样性和复杂性。通过掌握tshark其用法,再去分析协议特征,通过对协议的理解和对tshark本身的融会贯通,相信对于各大网络排障都能从中受益。
附带PDF版本:
一文读懂网络报文分析神器Tshark: 100+张图、100+个示例轻松掌握.pdf