抓包分析TCP三次握手
我们都知道TCP的连接的建立是通过三次握手,连接的断开是通过四次挥手完成。大部分人是从大学网络老师的讲课中得知,或者从baidu或者google搜索学习这一过程。但是这些都是理论的,并且很难被记住。
今天我们就通过抓包的方式,用抓到的实际的包来分析这一过程的建立。
我们所使用的抓包工具是:
Microsoft Network Monitor 3.4.
硬件环境是:
一台笔记本,一台pc.
网络环境是:
笔记本通过无线连接网络, pc通过有线连接网络。
软件环境:
两台都是xp, 有两个简单的测试程序,tcp 的服务器S和客户端C。服务器部署在pc上,客户端部署在笔记本上。
Network Monitor运行在客户端,也就是笔记本上。
服务端IP:192.168.200.128, 监听端口6001
客户端IP:192.168.200.107
好了,我们现在开始。启动抓包工具,start new capture, 在filter中输入, Tcp.SrcPort==6001 || Tcp.DstPort==6001, 然后apply, 接下来我们就可以启动抓包了。
启动服务器S,然后用客户端C去连接。
很快我们就可以看到总共有3个包进出:
184 9:42:45 2011-4-29 22.2968750 TestTCPClient.exe 192.168.200.107 192.168.200.128 TCP TCP:Flags=……S., SrcPort=1086, DstPort=6001, PayloadLen=0, Seq=278035085, Ack=0, Win=16384 ( ) = 16384 {TCP:33,
IPv4:32}
185 9:42:45 2011-4-29 22.2968750 TestTCPClient.exe 192.168.200.128 192.168.200.107 TCP TCP:Flags=…A..S., SrcPort=6001, DstPort=1086, PayloadLen=0, Seq=3353324968, Ack=278035086, Win=65535 ( Scale factor
not supported ) = 65535 {TCP:33, IPv4:32}
186 9:42:45 2011-4-29 22.2968750 TestTCPClient.exe 192.168.200.107 192.168.200.128 TCP TCP:Flags=…A…., SrcPort=1086, DstPort=6001, PayloadLen=0, Seq=278035086, Ack=3353324969, Win=17520 (scale factor 0x0)
= 17520 {TCP:33, IPv4:32}
第一个包是从客户端(192.168.200.107)发出,当然是这样,因为连接的建立肯定是由客户端想服务端发起,目的地址就是我们的服务器所在的pc的ip 地址和端口,服务器的端口是我们事先设定的,而客户端的端口则是tcp协议栈分配的,这里可以看出,客户端通讯端口的分配时在第一次发包时就已经确定好了的,其实这个过程在rfc在有个专门的术语来描述,TCB的建立(transmit control block)。这也就是我们在学校老师讲的第一次握手。
为了更好的分析这个包,我们引入tcp的包结构:
以及整个包的二进制表示:
00 1A A0 C6 BC 79 00 13 02 4A 3A 8A 08 00 45 00 00 30 09 F6 40 00 80 06 DE 94 C0 A8 C8 6B C0 A8 C8 80 04 3E 17 71 10 92 7A 8D 00 00 00 00 70 02 40 00 8A 13 00 00 02 04 05 B4 01 01 04 02
这个包里面其实包含了Ethernet header, IP header, TCP header. 为了更加清晰对这个包分析,我么顺带也把其他两个包的格式列出:
IP包格式
好了有了这些东西我们就分析包里面的东西,我是以图片的形式展示给大家:
(抱歉,可能图片有点丑,因为我是用微软的画图程序画的)
上面的以太网头部分我们只是标出它的位置,并不做详细的分析,IP包头部分我们只看里面的最后8个字节,分别为源IP地址,这里看到正是我们的客户端,也就是笔记本的Ip地址;还有目的IP地址,正是我们的服务端的Ip地址,也就是pc的Ip地址。
纠正一下:上图中端口0186应为1086,属于笔误。
对于TCP的包头结构,我做了详细的分析,只有’Data offset, reserved and flag’这四个字节需要进一步的说明,因为几个部分不是字节对齐的,reserved and flag都是6bit,所以不能简单一眼看出,需要把他们转换成二进制表示:
1100000000000010
红色部分表示偏移量:1010刚好是5,注意这里的5,并不是5个字节,而是5个偏移量单位,而偏移量单位为4个字节,这样总偏移量就刚好是我们tcp包头的大小20个字节。
蓝色部分是保留部分,必须全是0.
绿色部分是标志位,分别代表:
紧急比特URG——当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。 |
确认比特ACK——只有当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。 PSH— |
复位比特RST(Reset) —— 当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。 |
同步比特SYN——同步比特SYN置为1,就表示这是一个连接请求或连接接受报文。 |
终止比特FIN(FINal)—用来释放一个连接。当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。 |
可以看到,第一个请求包,只有SYN标志位是置为1的,其他均为0,表示发起一个连接。
到此第一个包我们就分析完毕。接下来用同样的方法来分析剩下的两个包。
第二个包:
00 1A A0 C6 BC 79 00 13 02 4A 3A 8A 08 00 45 00 00 30 09 F6 40 00 80 06 DE 94 C0 A8 C8 6B C0 A8 C8 80 04 3E 17 71 10 92 7A 8D 00 00 00 00 70 02 40 00 8A 13 00 00 02 04 05 B4 01 01 04 02
源IP变成了192.168.200.128,端口是6001; 而目的IP变成了192.168.200.107,端口是1086.可以看出这是服务器那边的机器发给客户端的包。
然后看flag部分是:
1110000000010010
对照tcp包结构就可以看出这个包中,ACK和SYN均置为1,其余均为0.
也就是服务器回应给发起连接的客户端的包中ACK和SYN均被置位。
第三个包:
1A A0 C6 BC 79 00 13 02 4A 3A 8A 08 00 45 00 00 28 09 F7 40 00 80 06 DE 9B C0 A8 C8 6B C0 A8 C8 80
04 3E 17 71 10 92 7A 8E C7 DF AD A9 50 10 44 70 3C CE 00 00
源IP:192.168.200.107,端口1086;
目的IP:192.168.200.128,端口6001;
flag部分是:
1110000000010000
只有SYN置为1,其余均为0,包括ACK。
这样整个连接就建立了。
下面用图示的方式简单的表示我们上面分析的结果:
到此结束。
版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.
最后一张图画反了吧,应该Server和Client换个位置吧?
回复 jjz2009nsqdzh:
非常谢谢你,你说的对,server和client反了。
回复 huangxiansheng1980:
我已经修改了示意图