4.WireShark抓包实战
今天宏哥还是以度娘为例,进行演示WireShark抓包实战,
4.1获取度娘IP
1.首先我们来先看一下百度的IP是多少,想必都知道如何获取吧!方法很多,宏哥就要其中一种最简单的方法来看一下:通过ping命令即可:ping baidu.com,如下图所示:
2.从上图可以看出其中39.156.66.10就是度娘的IP地址,后面需要通过这个IP地址,作为wireshark的过滤条件,方便我们找到对应的报文。
4.2WireShark抓包
1.打开WireShark,并开启抓包模式开始捕获,如下图所示:
2.在命令行输入curl -I baidu.com
来向百度发送一个HTTP请求。如下图所示:
3.停止wireshark抓包。在wireshark的过滤器中,输入ip.addr == 39.156.66.10
来过滤发送给百度的请求。可以得到如下过滤后的报文。如下图所示:
4.从上图我们可以清楚地看到前三条是TCP三次握手建立连接的报文,中间三个是包括一个HTTP请求,一个TCP的确认报文和一个HTTP响应报文,响应报文的TCP确认报文和第一次挥手被放在了同一个报文里。后面的四条是TCP四次挥手断开连接的报文。
4.3三次握手
4.3.1第一次握手
三次握手的第一个报文:SYN报文,也就是第一次握手,如下图所示:
然后在WireShark中查看一下我们抓包抓到的是否正确,如下图所示:
1.根据之前理论知识,我们趁热打铁:首先,来看第一个报文,即三次握手的第一次握手。点击选中第一个TCP即可查看。如下图所示:
2.整个第一次握手的报文消息详细解析,都在上图中右边做了红色标注。我们来看比较重要的几个部分。
①开始是2字节的源端口号和2字节的目的端口号。
②紧接着的四个字节,表示的是客户端传送给服务端的初始序号,这是一个随机值,目的是维护安全。
③注意,再紧接着的四个字节是确认号,不过,在第一次握手的报文中,ACK标志bit位是0,所以,实际上在第一次握手时,确认号是无意义的,因为这时候也没有什么需要确认的。
④再后面的4个bit,表示的是TCP头部长度,也可以理解为数据偏移量。注意,这里是8,而该字段的单位是4字节,所以TCP头部是8*4 = 32字节;
⑤紧接着的是4个保留bit位,和8个特殊标志bit位。这些标志按顺序依次是CWR、ECE、URG、ACK、PSH、RST、SYN、FIN,关注ACK、SYN、FIN即可。这里SYN为1,表示是一个建立连接的报文,ACK为0,表示本报文的确认号无意义。
⑥后面2字节表示接收窗口大小,是用于流量控制的。
⑦再后面,是2字节的校验和,2字节的紧急数据指针。
⑧需要额外指出的是,此报文指出TCP头部有32个字节,而不是一般报文是20字节。这里是因为在选项部分,本报文携带了一些额外的数据,其中包括MSS(Maximum Segment Size): 1460 bytes 等信息。
4.3.2第二次握手
三次握手的第二个报文:SYN+ACK报文,也就是第二次握手,如下图所示:
然后在WireShark中查看一下我们抓包抓到的是否正确,如下图所示:
1.同样的方法:点击选中第二个TCP即可查看。如下图所示:
2.上图中右边红色部分标注了第二次握手的报文详细信息,其大部分都和第一次握手类似。来看比较重要的几个部分
①源端口号和目的端口号正好和第一次握手相反,说明这是服务端响应客户端的报文
②服务端给出了一个自己的初始序号A1 7C 07 91,对应2709260177。
③服务端的ACK bit位是1,说明该报文的确认号是有意义的,确认号对应的值是15 ec 6b df,恰好是第一次握手的报文的序号+1,表示在该数字之前的字节都已经收到,期望下一次收到的报文的序号是这个数
④这里TCP头部也有32字节,选项部分同样说明了自己的MSS等信息,这里的MSS给的值是1412字节。
总体上来说,第二次握手的报文和第一次握手的报文的区别在ACK bit位是1,并且确认号是第一次握手报文的序号+1,此外,两个报文都包括了额外的选项部分,并且头部都有32个字节。
4.3.3第三次握手
三次握手的第三个报文:ACK报文,也就是第三次握手,如下图所示:
然后在WireShark中查看一下我们抓包抓到的是否正确,如下图所示:
1.同样的方法:点击选中第三个TCP即可查看。如下图所示:
2.上图中右边红色部分标注了第三次握手的报文详细信息,第三次握手的大部分内容也都是类似的,挑出重点部分。
①第三次握手的序号是第二次的确认号。确认号是第二次的序号+1。
②首部长度是20字节,头部没有了选项部分。
③SYN字段是0。这里是因为,第一次握手时客户端请求连接,第二次握手时服务器确认并接受连接,第三次握手实际连接已经成功建立。实际上,第三次握手是可以携带应用数据的,不过没见过这样做的。
④接收窗口的值一直在变化,这是流量控制的一部分,报文发送方发送自己的窗口大小,接收方根据对方窗口大小,调节报文发送速率。
到这里,TCP三次握手结束,连接成功建立。
从上面的过程可以发现第三次握手是可以携带数据的,前两次握手是不可以携带数据的,这也是面试常问的题。
一旦完成三次握手,双方都处于 ESTABLISHED
状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。
4.4数据传输
4.4.1HTTP请求
客户端向服务端发送第三次握手的报文之后,连接建立成功后,紧接着会发送数据传输的信息。在这里是HTTP请求。来看这个请求对应的报文的信息。
1.同样的方法:点击选中HTTP请求即可查看。如下图所示:
2.首先,跟随宏哥来看HTTP层协议,将该部分翻译过来,就是图中的HTTP部分标注(左边红色部分)。包含了请求行、请求头、空行。注意,这里的HTTP部分有73个字节,也是就说,TCP数据部分有73个字节。
实际上,程序通过
IP层的数据总长度-IP头长度-TCP头长度
来计算数据长度。
3.然后再来看TCP协议部分(右边红色部分),主要有以下几点。
①该报文的头长度也是20字节
②该报文的确认号、序号都和第三次握手的一样。
③其中PSH bit为是1。这里是因为这个报文只有这一个分组,整个报文传输完毕,无需等待其他分组,通知接收方应当立即将报文交给应用程序,而不需要缓存起来等待足够的数据再交付给上层。
因为HTTP是基于TCP的协议,所以每一个HTTP请求,即使只有一个分组,也至少涉及到两个TCP报文的传输,因为接收方会发送一个确认报文给发送方。下面,来看这个http请求对应的TCP确认报文。
4.4.2TCP确认报文
1.同样的方法:点击选中HTTP请求后TCP的确认报文即可查看。如下图所示:
这个报文内(右边红色部分),有以下几点需要注意。
①上一个HTTP请求的http部分有73个字节,所以本确认报文的确认号,就应当是上一个请求的序号+73。
②因为接收方直到目前没有传输数据给发送方,所以序号目前只是建立连接时确定的初始序号+1。
③这里PSH标志位的值没有置1,可以理解为只有携带了数据的报文的最后一个分组,才会将PSH标志位置为1。
也就是说,这个HTTP请求报文,涉及一次HTTP数据报文和一次TCP确认报文。如果数据量较大,需要分组传输的话,涉及的传输更多。
4.4.3HTTP响应报文
接下来的,就轮到HTTP响应的报文了,也就是服务端响应给客户端的HTTP报文。
1.同样的方法:点击选中HTTP响应即可查看。如下图所示:
2.这里和之前的没有太大区别(左边和右边红色部分),不过这一次,报文由服务端发送,并且携带了数据,这里携带了305字节的数据,所以,客户端接收后发送的确认报文的确认号,将会是本报文的序号+305。
3.接着看HTTP响应对应的TCP确认报文,实际上,这个也是第一次挥手的报文。
4.5四次挥手
4.5.1第一次挥手
HTTP响应对应的TCP确认报文,实际上,这个也是第一次挥手的报文。第一次挥手和HTTP响应的确认报文是同一个报文,和其他的报文相比,除了FIN bit位被置为1,并没有什么其他区别。如下图所示:
1.同样的方法:点击选中第一次挥手的TCP即可查看。如下图所示:
HTTP响应对应的TCP确认报文(左边红色部分):
①因为响应携带了305字节的数据,所以本次确认报文的确认号是之前的确认号/接收到报文的序号+305。
②这里ACK为1,表示确认号有意义,FIN为1,表示这是一个断开连接的报文,所以,这也是第一次挥手的报文。
4.5.2第二次挥手
1.同样的方法:点击选中第二次挥手的TCP即可查看。如下图所示:
2.第二次挥手的报文,由服务端发出,对第一次挥手的报文进行了确认。并且其中FIN是0(从上图可以看到),因为该报文只是接收方对发送方的第一次挥手报文的确认。
4.5.3第三次挥手
服务端准备断开连接,准备好后,服务端发出FIN报文。也就是第三次挥手。
1.同样的方法:点击选中第三次挥手的TCP即可查看。如下图所示:
注意,这里FIN是1,这是由服务端发出的FIN报文,表示服务端准备好断开连接。服务器发送该报文后,进入LAST_ACK阶段。
4.5.4第四次挥手
当客户端接收到此报文(第三次挥手)时,会返回最后一条确认报文给服务端。也就是第四次挥手。
1.同样的方法:点击选中第四次挥手的TCP即可查看。如下图所示:
2.服务端接收到这条确认消息后,并不会再发送报文,而是将连接关闭,进入CLOSED状态。
5.小结
前边理论加后边的实践,想必小伙伴或者童鞋们对TCP包有了进一步的认识了吧,宏哥觉得说清楚了,如果有想了解更清楚地,可以查一些资料。好了,今天时间也不早了,就到这里!感谢您耐心的阅读~~