Wireshark 和 Tcpdump 是最常用的网络抓包和分析工具,更是分析网络性能必不可少的利器。
-
tcpdump 仅支持命令行格式使用,常用在 Linux 服务器中抓取和分析网络包
-
Wireshark 除了可以抓包外,还提供了可视化分析网络包的图形页面,在Window环境下使用
所以,这两者实际上是搭配使用的,先用 tcpdump 命令在 Linux 服务器上抓包,接着把抓包的文件拖出到 Windows 电脑后,用 Wireshark 可视化分析。
一、Wireshark
1 Wireshark简介
Wireshark是使用最广泛的一款开源抓包软件,常用来检测网络问题、攻击溯源、或者分析底层通信机制。
它使用WinPCAP作为接口,直接与网卡进行数据报文交换。
2 Wireshark抓包原理
Wireshark使用的环境大致分为两种,一种是电脑直连互联网的单机环境,另外一种就是应用比较多的互联网环境,也就是连接交换机的情况。
「单机情况」下,Wireshark直接抓取本机网卡的网络流量; 「交换机情况」下,Wireshark通过端口镜像、ARP欺骗等方式获取局域网中的网络流量。
-
端口镜像:利用交换机的接口,将局域网的网络流量转发到指定电脑的网卡上。
-
ARP欺骗:交换机根据MAC地址转发数据,伪装其他终端的MAC地址,从而获取局域网的网络流量。
3 Wireshark使用
3.1 选择网卡
打开 Wireshark 后,会直接进入「网卡选择界面」,WLAN 是我连接无线的网卡,我们抓一下这个网卡的流量,双击网卡名,自动开始抓包。
image.png3.2 停止抓包
image.png3.3 保存数据
点击右上角的「文件」,选择「保存」,可以保存抓包的数据
image.png也可以直接点击工具栏的保存按钮
image.png4 案例1: Wireshark抓MySQL TCP 数据包
我们一直在使用 MySQL,但我们很少会考虑 MySQL Connector Java 是怎么和 MySQL 交互的,实际发送给 MySQL 的 SQL 语句又是怎样的。
这里我们通过一个案例来使用 Wireshark 来观察、分析应用程序与 MySQL 交互的整个流程。
背景:有一个数据导入程序需要导入大量的数据,想到了使用 Spring JdbcTemplate 的批量操作功能进行数据批量导入,但是发现性能非常差,和普通的单条 SQL 执行性能差不多。对于批量操作,我们希望程序可以把多条 insert SQL 语句合并成一条,或至少是一次性提交多条语句到数据库,以减少和 MySQL 交互次数、提高性能。那么,我们的程序是这样运作的吗?
4.1 先启动Wireshark后选择某个需要捕获的网卡。
由于我们连接的是本地的 MySQL,因此选择 loopback 回环网卡:
image.png4.2 Wireshark 捕捉这个网卡的所有网络流量
我们可以在上方的显示过滤栏输入 tcp.port == 6657,来过滤出所有 6657 端口的 TCP 请求(因为我们是通过 6657 端口连接 MySQL 的)。
可以看到,程序运行期间和 MySQL 有大量交互。因为 Wireshark 直接把 TCP 数据包解析为了 MySQL 协议,所以下方窗口可以直接显示 MySQL 请求的 SQL 查询语句。我们看到,testuser 表的每次 insert 操作,插入的都是一行记录:
image.png如果列表中的 Protocol 没有显示 MySQL 的话,你可以手动点击 Analyze 菜单的 Decode As 菜单,然后加一条规则,把 6657 端口设置为 MySQL 协议:
image.png4.3 分析
从上面抓包的数据可以看出,我们的程序并不是在做批量插入操作,和普通的单条循环插入没有区别。
这里原因其实在于 rewriteBatchedStatements 参数。我们修改连接字符串,并将其值设置为 true:
datasource.url=jdbc:mysql://localhost:6657/common_mistakes?characterEncoding=UTF-8&useSSL=false&rewriteBatchedStatements=true
4.4 把rewriteBatchedStatements设置为true,重新抓包
可以看到:
-
这次 insert SQL 语句被拼接成了一条语句(如第二个红框所示);
-
这个 TCP 包因为太大被分割成了 11 个片段传输,#699 请求是最后一个片段,其实际内容是 insert 语句的最后一部分内容(如第一和第三个红框显示)。
4.5 查看整个 TCP 连接的所有数据包
为了查看整个 TCP 连接的所有数据包,你可以在请求上点击右键,选择 Follow->TCP Stream:
image.png打开后可以看到,从 MySQL 认证开始到 insert 语句的所有数据包的内容:
image.png查看最开始的握手数据包可以发现,TCP 的最大分段大小(MSS)是 16344 字节,而我们的 MySQL 超长 insert 的数据一共 138933 字节,因此被分成了 11 段传输,其中最大的一段是 16332 字节,低于 MSS 要求的 16344 字节。
image.png5 案例2:客户端和 MySQL 握手过程
一般而言,客户端和 MySQL 进行认证,认证(握手)过程分为三步。
5.1 首先,服务端给客户端主动发送握手消息:
image.pngWireshark 已经把消息的字段做了解析,你可以对比官方文档的协议格式一起查看。HandshakeV10 消息体的第一个字节是消息版本 0a,见图中红色框标注的部分。前面四个字节是 MySQL 的消息头,其中前三个字节是消息体长度(16 进制 4a=74 字节),最后一个字节是消息序列号。
5.2 然后,客户端给服务端回复的 HandshakeResponse41 消息体,包含了登录的用户名和密码
image.png可以看到,用户名是 string[NUL]类型的,说明字符串以 00 结尾代表字符串结束。关于 MySQL 协议中的字段类型,你可以参考这里。
5.3 最后,服务端回复的 OK 消息,代表握手成功
image.png这样分析下来,我们可以发现使用 Wireshark 观察客户端和 MySQL 的认证过程,非常方便。而如果不借助 Wireshark 工具,我们只能一个字节一个字节地对照协议文档分析内容。
其实,各种 CS 系统定义的通讯协议本身并不深奥,甚至可以说对着协议文档写通讯客户端是体力活。以前做loT开发时,对着各种类型的设备协议文档写通讯客户端确实是就是个体力活,属于会者不难,难着不会,就是刚开始时入门难一些。
这段经历涉及到了netty,见 Netty系列文章
二 Tcpdump
1 Tcpdump简介
Linux作为网络服务器,特别是作为路由器和网关时,数据的采集和分析是不可少的。TcpDump是Linux中强大的网络数据采集分析工具之一。
tcpdump可以根据使用者需求对网络上传输的数据包进行捕获的抓包工具,windows平台有wireshark等工具,tcpdump可以将网络中传输的数据包的“包头”全部捕获过来进行分析,其支持网络层、特定的传输协议、数据发送和接收的主机、网卡和端口的过滤,并提供and、or、not等语句进行逻辑组合捕获数据包或去掉不用的信息。
2 Tcpdump命令选项和捕获主机到主机的数据包
-
-a #将网络地址和广播地址转变成名字
-
-A #以ASCII格式打印出所有分组,并将链路层的头最小化
-
-b #数据链路层上选择协议,包括ip/arp/rarp/ipx都在这一层
-
-c #指定收取数据包的次数,即在收到指定数量的数据包后退出tcpdump
-
-d #将匹配信息包的代码以人们能够理解的汇编格式输出
-
-dd #将匹配信息包的代码以c语言程序段的格式输出
-
-ddd #将匹配信息包的代码以十进制的形式输出
-
-D #打印系统中所有可以监控的网络接口
-
-e #在输出行打印出数据链路层的头部信息
-
-f #将外部的Internet地址以数字的形式打印出来,即不显示主机名
-
-F #从指定的文件中读取表达式,忽略其他的表达式
-
-i #指定监听网络接口
-
-l #使标准输出变为缓冲形式,可以数据导出到文件
-
-L #列出网络接口已知的数据链路
-
-n #不把网络地址转换为名字
-
-N 不输出主机名中的域名部分,例如www.baidu.com只输出www
-
-nn #不进行端口名称的转换
-
-P #不将网络接口设置为混杂模式
-
-q #快速输出,即只输出较少的协议信息
-
-r #从指定的文件中读取数据,一般是-w保存的文件
-
-w #将捕获到的信息保存到文件中,且不分析和打印在屏幕
-
-s #从每个组中读取在开始的snaplen个字节,而不是默认的68个字节
-
-S #将tcp的序列号以绝对值形式输出,而不是相对值
-
-T #将监听到的包直接解析为指定的类型的报文,常见的类型有rpc(远程过程调用)和snmp(简单网络管理协议)
-
-t #在输出的每一行不打印时间戳
-
-tt #在每一行中输出非格式化的时间戳
-
-ttt #输出本行和前面以后之间的时间差
-
-tttt #在每一行中输出data处理的默认格式的时间戳
-
-u #输出未解码的NFS句柄
-
-v #输出稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息
-
-vv#输出相信的保报文信息
3 tcpdump表达式
3.1 关于数据类型的关键字 包括host、port、net:
-
host 192.168.130.1表示一台主机,
-
net 192.168.130.0表示一个网络网段,
-
port 80 指明端口号为80,在这里如果没有指明数据类型,那么默认就是host
3.2 数据传输方向的关键字 包括src、dst、dst or src、dst and src,这些关键字指明了传输的方向,比如
-
src 192.168.130.1说明数据包源地址是192.168.130.1。
-
dst net 192.168.130.0指明目的网络地址是192.168.130.0,
-
默认是监控主机对主机的src和dst,即默认监听本机和目标主机的所有数据。
3.3 协议关键字 包括ip、arp、rarp、udp
-
3.4 其他关键字 运算类型:or、and、not、!
-
辅助功能型:gateway、less、broadcast、greater
4 Tcpdump捕获方式
#tcpdump [协议类型] [源或目标] [主机名称或IP] [or/and/not/!条件组合] [源或目标] [主机名或IP] [or/and/not/!条件组合] [端口] [端口号] …… [or/and/not/!条件组合] [条件]
tcpdump ip dst 192.168.56.1 and src 192.168.56.210 and port 80 and host ! www.baidu.com
4.1 监听指定网卡ens33的所有传输数据包
tcpdump -i ens33
image.png4.2 捕获主机192.168.130.151经过网卡ens33的所有数据包
tcpdump -i ens33 host 192.168.130.151
只检测192.168.130.151这个主机发过来的包,其他的自动过滤
image.png4.3 捕获主机 192.168.130.151 和主机192.168.130.152或192.168.130.153的所有通信数据包
tcpdump host 192.168.130.151 and /(192.168.130.152 or 192.168.130.153/)
4.4 捕获主机node9与其他主机之间(不包括 www.baidu.com)通信的ip数据包
tcpdump ip host node9 and not www.baidu.com
4.5 捕获源主机node10发送的所有的经过ens33网卡的所有数据包
tcpdump -i ens33 src node10
4.6 捕获所有发送到主机www.baidu.com的数据包
tcpdump -i ens33 dst host www.baidu.com
4.7 监听主机192.168.56.1和192.168.56.210之间ip协议的80端口的且排除www.baidu.com通信的所有数据包:
tcpdump ip dst 192.168.56.1 and src 192.168.56.210 and port 80 and host ! baidu.com
也可以写成tcpdump ip dst 192.168.56.1 and src 192.168.56.210 and port 80 and host not www.baidu.com,即not和!都是相同的取反的意思
4.8 捕获主机192.168.56.210接收和发出的tcp协议的ssh的数据包
tcpdump tcp port 22 and host 192.168.56.210
4.9 监听本机udp的53端口的数据包
tcpdump udp port 53
监听本机udp的53端口的数据包,udp是dns协议的端口,这也是一个dns域名解析的完整过程
网友评论