Tcpdump会让你在网络方面自由飞翔( 二 )


文章插图
 
step1. 由客户端向服务器端发起TCP连接请求 。Client发送:同步序列编号SYN置为1 , 发送序号Seq为一个随机数 , 这里假设为X , 确认序号ACK置为0;
step2. 服务器端接收到连接请求 。Server响应:同步序列编号SYN置为1 , 并将确认序号ACK置为X+1 , 然后生成一个随机数Y作为发送序号Seq(因为所确认的数据报的确认序号未初始化);
step3. 客户端对接收到的确认进行确认 。Client发送:将确认序号ACK置为Y+1 , 然后将发送序号Seq置为X+1(即为接收到的数据报的确认序号);
为什么是三次握手而不是两次对于step3的作用 , 假设一种情况 , 客户端A向服务器B发送一个连接请求数据报 , 然后这个数据报在网络中滞留导致其迟到了 , 虽然迟到了 , 但是服务器仍然会接收并发回一个确认数据报 。但是A却因为久久收不到B的确认而将发送的请求连接置为失效 , 等到一段时间后 , 接到B发送过来的确认 , A认为自己现在没有发送连接 , 而B却一直以为连接成功了 , 于是一直在等待A的动作 , 而A将不会有任何的动作了 。这会导致服务器资源白白浪费掉了 , 因此 , 两次握手是不行的 , 因此需要再加上一次 , 对B发过来的确认再进行一次确认 , 即确认这次连接是有效的 , 从而建立连接 。
对于双方 , 发送序号的初始化为何值有的系统中是显式的初始化序号是0 , 但是这种已知的初始化值是非常危险的 , 因为这会使得一些黑客钻漏洞 , 发送一些数据报来破坏连接 。因此 , 初始化序号因为取随机数会更好一些 , 并且是越随机越安全 。
tcpdump抓TCP三次握手抓包分析:
sudotcpdump-n-S-ilo0host10.37.63.3andtcpport8080
# 接着再运行:
curlhttp://10.37.63.3:8080/atbg/doc
【Tcpdump会让你在网络方面自由飞翔】控制台输出:

Tcpdump会让你在网络方面自由飞翔

文章插图
 
每一行中间都有这个包所携带的标志:
S=SYN , 发起连接标志 。
P=PUSH , 传送数据标志 。
F=FIN , 关闭连接标志 。
ack , 表示确认包 。
RST=RESET , 异常关闭连接 。
. , 表示没有任何标志 。
第1行:16:00:13.486776 , 从10.37.63.3(client)的临时端口61725向10.37.63.3(server)的8080监听端口发起连接 , client初始包序号seq为1944916150 , 滑动窗口大小为65535字节(滑动窗口即tcp接收缓冲区的大小 , 用于tcp拥塞控制) , mss大小为16344(即可接收的最大包长度 , 通常为MTU减40字节 , IP头和TCP头各20字节) 。【seq=1944916150 , ack=0 , syn=1】
第2行:16:00:13.486850 , server响应连接 , 同时带上第一个包的ack信息 , 为client端的初始包序号seq加1 , 即1944916151 , 即server端下次等待接受这个包序号的包 , 用于tcp字节流的顺序控制 。Server端的初始包序号seq为1119565918 , mss也是16344 。【seq=1119565918 , ack=1944916151 , syn=1】
第3行:15:46:13.084161 , client再次发送确认连接 , tcp连接三次握手完成 , 等待传输数据包 。【ack=1119565919 , seq=1944916151】
2、四次挥手
连接双方在完成数据传输之后就需要断开连接 。由于TCP连接是属于全双工的 , 即连接双方可以在一条TCP连接上互相传输数据 , 因此在断开时存在一个半关闭状态 , 即有有一方失去发送数据的能力 , 却还能接收数据 。因此 , 断开连接需要分为四次 。主要过程如下:
Tcpdump会让你在网络方面自由飞翔

文章插图
 
step1. 主机A向主机B发起断开连接请求 , 之后主机A进入FIN-WAIT-1状态;
step2. 主机B收到主机A的请求后 , 向主机A发回确认 , 然后进入CLOSE-WAIT状态;
step3. 主机A收到B的确认之后 , 进入FIN-WAIT-2状态 , 此时便是半关闭状态 , 即主机A失去发送能力 , 但是主机B却还能向A发送数据 , 并且A可以接收数据 。此时主机B占主导位置了 , 如果需要继续关闭则需要主机B来操作了;


推荐阅读