TCP专题之三次握手四次挥手
[1] TCP报文的结构
TCP报文是TCP层传输的数据单元,也叫报文段。
1、端口号:用来标识同一台计算机的不同的应用进程。
1)源端口:源端口和IP地址的作用是标识报文的返回地址。
2)目的端口:端口指明接收方计算机上的应用程序接口。
TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接。
2、序号和确认号:是TCP可靠传输的关键部分。序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节一个序号。e.g.一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400。所以序号确保了TCP传输的有序性。确认号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK标志为1时才有效。比如建立连接时,SYN报文的ACK标志位为0。
3、数据偏移/首部长度:4bits。由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何任选字段则长度为20字节,4位首部长度字段所能表示的最大值为1111,转化为10进制为15,15*32/8 = 60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。
4、保留:为将来定义新的用途保留,现在一般置0。
5、控制位:URG ACK PSH RST SYN FIN,共6个,每一个标志位表示一个控制功能。
1)URG:紧急指针标志,为1时表示紧急指针有效,为0则忽略紧急指针。
2)ACK:确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。
3)PSH:push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
4)RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
5)SYN:同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。
6)FIN:finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。
6、窗口:滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小时一个16bit字段,因而窗口大小最大为65535。
7、校验和:奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。
8、紧急指针:只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
9、选项和填充:最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
10、数据部分: TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
SYN,ACK,FIN等详细介绍:
- 同步SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。
- 确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效。
- 终止FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接。
- 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号seq就是这个报文段中的第一个字节的数据编号。
- 确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。
[2] 解释一下TCP三次握手四次挥手
图片来源于微信公众号:码农求职小助手
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tF3N5pyY-1596601232465)(X:\Users\xu\AppData\Roaming\Typora\typora-user-images\image-20200721194128725.png)]
答: 嗯(稍作思考)…
- 三次握手简单来说,在数据传输开始前:
第一次:客户端将SYN标记为置为1,随机产生一个值seq=x,并将数据包发送给服务端表示要请求连接,客户端状态由CLOSE阶段切换到SYN_SENT阶段,并等待服务端回应。
第二次:服务器端接收之后,服务端会将标志位SYN和ACK都置为1,seq=y,ack=x+1,发送给客户端,表示同意连接。服务端从LISTEN状态切换到SYN-RCVD状态。
第三次:客户端收到服务端的确认后,检查ack是否为x+1,若正确则将标志位ACK置为1,ack=y+1,并发送会服务端,此时客户端的状态切换为ESTABLISH状态,完成三次握手。
三次握手完毕后,客户端与服务器才正式开始传送数据。
SYN攻击:
在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:
#netstat -nap | grep SYN_RECV
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9DNz42lX-1596601232467)(X:\Users\xu\AppData\Roaming\Typora\typora-user-images\image-20200721194310325.png)]
- 四次挥手简单来说,在数据传输结束后:
第一次挥手:客户端发送一个FIN包,序号seq=u,用来关闭数据传送,客户端由FIN_WAIT_1状态切换到ESTABLISH状态。
第二次挥手:服务端收到FIN包后,发送一个ACK给服务端,ack=u+1,服务端由ESTABLISH状态切换到CLOSE_WAIT状态。
第三次挥手:服务端发送一个FIN包,seq=w,状态由CLOSE_WAIT状态切换到LAST_ACK状态。
第四次挥手:客户端收到FIN后,发送一个确认包,ack=w+1,并且进入TIME_WAIT状态,等待2MSL(MSL最长报文段寿命)后,进入CLOSE状态。服务端收到确认号直接进入CLOSE阶段
PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。原文链接:link.
[3] 为什么是三次握手,可以是两次吗?
不可以。假如没有第三次握手,服务端在某一时刻突然收到了一个来自被客户端卡了很久已经丢弃的SYN包,此时客户端是不想建立连接的,服务端的操作是返回SYN+ACK并且进入工作状态。客户端收到反馈后,无法告诉服务端这是错误的SYN的包,会造成资源的浪费。
[4] 为什么断开连接需要四次挥手?
答:因为在客户端发送给服务端FIN包后,服务端返回的FIN和ACK包是分开发送的。为什么要分开呢?因为客户端发送给服务端FIN包后,只表示客户端已经没有数据要发送了,但是另一个方向上可能还会有数据传输进来。所以第二次和第三次挥手分开发送,服务端先给出ACK确认信号,表示已经收到FIN请求,然后当自己也可以结束的时候,即真正结束数据传输的时候,再次发送FIN信号。是为了为未传输完毕的数据预留时间,所以需要挥手交互需要四次。
[5] 为什么 TIME-WAIT 状态必须等待 2MSL 的时间呢?
- 为了保证 客户端 发送的最后一个 ACK 报文段能够到达 服务端。 客户端 发送的最后一个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的 服务端收不到对已发送的 FIN + ACK 报文段的确认。服务端 会超时重传这个 FIN报文段,而 客户端 就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN+ACK 报文段。接着客户端重传一次确认,重新启动 2MSL 计时器。最后,客户端 和 服务端 都正常进入到 CLOSED 状态。如果 A 在 TIME-WAIT 状态不等待一段时间,而是在发送完 ACK 报文段后立即释放连接,那么就无法收到 B 重传的 FIN + ACK 报文段,因而也不会再发送一次确认报文段,这样,B 就无法按照正常步骤进入 CLOSED 状态。
- 防止已失效的连接请求报文段出现在本连接中。A 在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。