在
网络编程
中,有两大抓包利器,就是tcpdump
和Wireshark
,它们就好比《倚天屠龙记》里的倚天剑
和屠龙刀
得之者得天下。在网络编程
的世界中,可以说 『得Tcpdump
和Wireshark
, 便可纵览网络协议,看穿一切』。
前两篇文章我们用 Go
语言,实现了 Echo
客户端/服务器交互程序,带大家初步体验了一下网络编程
。
题外话
还没有看的同学,强烈推荐看下,然后再来看这篇文章哦。
但俗话说得好『百闻不如一见』今天我们就要用 tcpdump
和 Wireshark
揭开 『Echo
客户端/服务器交互程序』 的神秘面纱,通过工具一窥网络数据包的交互细节。
那么 tcpdump
和 Wireshark
到底是什么呢?下面我们一一揭晓。
tcpdump
简单来说就是dump traffic on a network
,通过匹配bool表达式
来跟踪网络接口上的网络数据包,并打印出相关的详细内容描述信息。
tcpdump
是一个命令行网络抓包工具,其语法格式是 『 tcpdump 选项 布尔表达式 』。这里所谓的布尔表达式
指的是条件表达式,又称为表达式,英文expression
,它由三部分组成,分别是:
协议 proto
方向 dir
类型 type
关于选项
这一张图片清晰地列出了tcpdump
的语法结构,平时我们在linux
终端,敲下man tcpdump
,首先看到的便是各种各样的option
。
这里我们只讲几个常用的选项,其他选项,大家平时可以用man tcpdump
来查看。
关于表达式
上文我们已经说过,表达式expression由协议proto
,方向dir
,类型type
三部分组成。他们是通过组合语句,只抓取条件为真的网络包,过滤无用的网络包,那么它们具体又是什么呢?
先说协议
协议就是我们所说的ip
, ip6
, arp
, rarp
, decnet
, tcp
, udp
等
协议紧跟在选项之后,同时还受之后的类型影响。
看看常用的组合tcp port 21
, udp portrange 7000-7009
,这里面的 tcp, udp 就是协议。
其次方向
方向定义了一个指定的网络包传输方向。比如src
,dst
,src or dst
,src and dst
等。
src
: 表示发送者
dst
: 表示接收者
src or dst
表示发送者或者接收者
src and dst
表示发送者并且接收者
3. 最后类型
类型限定的是关注哪些网络包,可能的类型有 host
, net
, port
, portrange
常用的组合有 host foo
表示主机名是foo的网络包,port 20
表示端口是20的网络包。
tcpdump -S -nn -i lo ip src host 127.0.0.1 and port 8888
这里的ip src host 127.0.0.1 and port 8888
就是所谓的表达式
,也就是这个条件为真,网络包才会被抓取,否则直接被过滤忽略。
其含义应该一目了然,因为使用src host 127.0.0.1
,所以我们必须指定协议为ip,因为只有ip协议
中有host
,其表示网络包的主机IP地址必须是127.0.0.1
,不用tcp
是因为tcp协议
中只有端口。src
又把范围缩小到必须是 『发送方的地址为127.0.0.1
』。
port 8888
表示网络包的端口必须是8888
。
中间的and
表示这是一个且的关系。
而这里的-S
,-nn
和-i lo
是选项『option』。-nn
表示使用原始的ip地址和端口号,不使用命名方式。-i lo
表示我们捕获的是哪个网络接口的数据包。
那我们的机器又有哪些网络接口呢?
我们使用ip add
便能查看本机网络接口,也就是有几张网卡。
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:8f:10:b9 brd ff:ff:ff:ff:ff:ff
inet 191.168.9.2/20 brd 172.21.31.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5034:ff:fe8f:50a9/64 scope link
valid_lft forever preferred_lft forever
lo 表示这是一个回环地址,它不属于任何一个有类别地址类。它代表设备的本地虚拟接口,所以默认被看作是永远不会宕掉的接口。
eth0 表示这是一个真实的网卡接口。
因为我们的Echo客户端/服务器
交互程序,是使用的ip
地址127.0.0.1
, 所以这里当然要用-i lo
喽,置于-S
, -nn
上边表格已经讲解过喽。
起一个终端,启动我们的
echoServer
程序,在命令行键入./echoServer
。再起一个终端,启动我们的
tcpdump
, 在命令行键入tcpdump -S -nn -i lo src host 127.0.0.1 and port 8888
。再再起一个终端,启动我们的
echoClient
程序,在命令行键入./echoClient
。
这时候我们观察一下tcpdump
所在的终端,会打印出以下信息。
# 三次握手
14:50:19.383814 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [S], seq 3494436218, win 43690, options [mss 65495,sackOK,TS val 2254490385 ecr 0,nop,wscale 7], length 0
14:50:19.383822 IP 127.0.0.1.8888 > 127.0.0.1.34372: Flags [S.], seq 3120187972, ack 3494436219, win 43690, options [mss 65495,sackOK,TS val 2254490385 ecr 2254490385,nop,wscale 7], length 0
14:50:19.383830 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [.], ack 3120187973, win 342, options [nop,nop,TS val 2254490385 ecr 2254490385], length 0
首先我们看一下输出格式:
其中这里的Flags
,表示的是TcpFlag
。枚举如下:
S
: 表示 SYN
F
: 表示 FIN
P
: 表示 PUSH
R
: 表示 RST
U
: 表示 URG
, 紧急数据
W
: 表示 ECN CWR
E
: 表示 ECN-Echo
.
: 表示 ACK
这里大家简单了解一下我们三次握手成功了,协商了发送序列号
和窗口大小
。
下一篇文章会拆解TCP协议
哦,麻烦大家关注,点赞,静待下篇再详细讲解这块。
在客户端所在的终端,键入
hello-echo
,我们再看看tcpdump
输出如下
14:50:22.316984 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [P.], seq 3494436219:3494436229, ack 3120187973, win 342, options [nop,nop,TS val 2254493318 ecr 2254490385], length 10
14:50:22.317044 IP 127.0.0.1.8888 > 127.0.0.1.34372: Flags [.], ack 3494436229, win 342, options [nop,nop,TS val 2254493318 ecr 2254493318], length 0
14:50:22.317059 IP 127.0.0.1.8888 > 127.0.0.1.34372: Flags [P.], seq 3120187973:3120187983, ack 3494436229, win 342, options [nop,nop,TS val 2254493318 ecr 2254493318], length 10
14:50:22.317113 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [.], ack 3120187983, win 342, options [nop,nop,TS val 2254493318 ecr 2254493318], length 0
客户端发送第二次数据,内容为
echo
14:50:24.485114 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [P.], seq 3494436229:3494436233, ack 3120187983, win 342, options [nop,nop,TS val 2254495486 ecr 2254493318], length 4
14:50:24.485246 IP 127.0.0.1.8888 > 127.0.0.1.34372: Flags [P.], seq 3120187983:3120187987, ack 3494436233, win 342, options [nop,nop,TS val 2254495486 ecr 2254495486], length 4
14:50:24.485343 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [.], ack 3120187987, win 342, options [nop,nop,TS val 2254495487 ecr 2254495486], length 0
客户端发送第三次数据,内容为
hello
14:50:26.437130 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [P.], seq 3494436233:3494436238, ack 3120187987, win 342, options [nop,nop,TS val 2254497438 ecr 2254495486], length 5
14:50:26.437198 IP 127.0.0.1.8888 > 127.0.0.1.34372: Flags [P.], seq 3120187987:3120187992, ack 3494436238, win 342, options [nop,nop,TS val 2254497438 ecr 2254497438], length 5
14:50:26.437309 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [.], ack 3120187992, win 342, options [nop,nop,TS val 2254497439 ecr 2254497438], length 0
通过三次数据收发,我们能够看到:
一次数据发送PUSH
, 必须要有一个ACK
下次发送序列号是本次序列号
+数据长度
窗口大小每次都会上报
在客户端所在终端,键入
Ctrl+C
# 四次挥手
14:50:27.607016 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [F.], seq 3494436238, ack 3120187992, win 342, options [nop,nop,TS val 2254498608 ecr 2254497438], length 0
14:50:27.607125 IP 127.0.0.1.8888 > 127.0.0.1.34372: Flags [F.], seq 3120187992, ack 3494436239, win 342, options [nop,nop,TS val 2254498608 ecr 2254498608], length 0
14:50:27.607130 IP 127.0.0.1.34372 > 127.0.0.1.8888: Flags [.], ack 3120187993, win 342, options [nop,nop,TS val 2254498608 ecr 2254498608], length 0
四次挥手,表示一个连接的终止。
第二次的ACK
和第三次的FIN
合并为一个数据包,所以我们看到的好像是三次挥手
。
可是命令行里抓包终究不太直观,我们也没有看到详细的数据是什么样的。所以通常我们需要将tcpdump
抓下来的网络包存储到以.pacp
文件结尾的网络包文件中。然后通过Wireshark
进行网络包的可视化分析。下面我们来看看Wireshark到底怎么用吧。
Wireshark
是一个网络封包分析软件,可以直观的查看网络包的格式和内容,其图标是就是鲨鱼鳞
。
如之前介绍的,我们在命令行启动我们的echoServer程序
。
在tcpdump -S -nn -i lo ip src host 127.0.0.1 and port 8888
命令中加入-w echo.pcap
选项也就是tcpdump -S -nn -w echo.pcap -i lo ip src host 127.0.0.1 and port 8888
。
新起终端,启动客户端程序,./echoClient
。
然后我们发送数据hello-echo
键入Ctrl+C
,结束客户端
在tcpdump
所在终端,Ctrl+C
结束tcpdump
命令,我们就能看到echo.pcap
文件了
将该文件用我们的Wireshark
打开。
这时候我们会看到网络包的详细内容:
通过Wireshark
我们能够清晰得看到echo
客户端程序的交互过程,通过颜色区分不同的数据包,当我们选中一个数据包,该行会变为蓝色背景,起到了集中视觉的效果。
通过包细节,我们可以看到基于网络协议
的网络编程是分层的。当我们的echo
客户端向服务器发送hello-echo
,可以通过tcp segment
看到其中的细节信息,和我们大学学习的TCP
协议格式也是吻合的。
本文我们通过tcpdump
和Wireshark
更加深刻的了解了我们的echo客户端/服务器
交互程序。通过抓包,我们可以看到socket API
和网络协议
是密切相关的,想要学好网络编程,掌握网络协议
也是必要的。之后蛇叔会把TCP
,IP
协议拆解了,一步步带你理解它。为我们看得见的网络编程
专栏打下坚实的理论基础,然后再进行下一步非阻塞
网络编程学习。
有的朋友私信想要echo客户端服务器
程序的源码,蛇叔已经打包源码,扫一扫下边的二维码,关注并回复echo
,就可以得到echo客户端服务器
程序源代码喽~~记得帮忙点下在看,非常感谢,有不足之处,欢迎留言讨论。
《TCP/IP详解 卷1》
《Unix网络编程 卷1》
《计算机网络》
希望大家喜欢,原创文章不易,麻烦大家关注
,在看
,转发
一键三连,谢谢大家。希望通过代码+图片的方式,教大家学看得见的网络编程。做不了火影主角,做个掌握核心科技的“蛇叔”也不错哈🤣。
各位朋友,我们下期再见。