先了解下跟三次握手、四次挥手相关的TCP标志位
-
SYN:同步序号,用来建立连接, SYN=1,ACK=0:连接请求报文段 SYN=1,ACK=1:同意连接 -
ACK:确认序号, ACK=1确认号有效,ACK=0确认号无效 -
Sequence number(seq):顺序号,发送数据中第一个字节的序列号 -
Acknowledge number(ack):确认号,响应前面seq,即seq+1
三次握手
-
第一次握手(发送连接请求报文SYN=1,ACK=0,seq=x),发送完毕后,客户端就进入SYN_SENT 状态 -
第二次握手(发送连接确认报文SYN=1,ACK=1,seq=y,ack=x+1),发送完毕后,服务器端就进入SYN_RCVD状态 -
第三次握手(发出连接确认报文ACK=1,seq=x+1,ack=y+1),发送完毕后,客户端进入ESTABLISHED状态,当服务器接收到,也进入ESTABLISHED状态
为什么是三次握手
- 确认双方的接收、发送是正常的
- 指定自己的初始化序列号,为后面的可靠传送做准备
三次握手是为了满足“在不可靠信道上可靠地传输信息”
确保可靠的通信通道,让双方确认自己的接收和发送能力是正常的。
- 第一次握手:server知道client的发送和自己接收是正常的
- 第二次握手:client知道server的发送和接收与自己的发送和接收是正常的,但server还不知道client的接收和它自己的发送是否正常
- 第三次握手:client回馈,server知道自己的发送和client的接收正常
如果不是三次握手,而是两次握手?
可能会有下列问题:
- client发送连接请求长时间滞留,导致连接释放后的某个时间到达server,server误以为是client发送新的连接请求,于是向client发出同意连接。这时候连接建立了,但client又不会做任何操作,server的许多资源被浪费了
- server发送的同意连接在传输中丢失 : client发送连接请求,server同意连接,认为连接已经成功建立了,但因为应答丢失,client认为连接还没开始,忽略server发来的任何分组
三次握手常见问题
-
为什么要随机初始化序列号 主要是为了处于网络安全的因素着想。如果不是随机初始化序列号,黑客很容易获取到初始化序列号,并伪造序列号进行攻击。 -
什么是半连接队列 server第一次收到client的SYN后,就会处于SYN_RCVD状态,此时双方还没有建立连接,server会把这种状态下的请求放在一个队列里,这就是半连接队列。完成三次握手后,建立起连接的就会放在全连接队列中。 SYN-ACK重传机制 server发完SYN-ACK包后,如果未收到client确认包,server会进行首次重传,等待一段时间后,进行第二次重传,如果重传次数超过系统规定的**最大重传次数,**系统将该连接信息从半连接队列删除。每次重传等待的时间一般是指数增长,如2s、4s、8s… -
三次握手可以携带数据吗? 第三次握手可以携带,第一二次不能。 如果第一次握手可以携带,有人恶意攻击服务器,在第一次握手中SYN报文放大量数据,攻击者疯狂发送SYN报文,会让server花费很多时间、内存来接受这些报文。如果第一次握手可以放数据的话,会让服务器更容易受到攻击 第三次的话,此时客户端已经处于established状态,对于client来说,它已经建立连接了,也知道server的接收、发送是正常的,所以能携带数据也没问题
SYN攻击
-
危害:SYN属于DOS攻击的一种,利用TCP协议缺陷,通过发送大量半连接请求,耗费CPU和内存资源。 -
原理:三次握手中的SYN-ACK重传机制,在短时间内伪造大量不存在的IP地址,向server不断发送SYN包,server回复确认包,并等待client的响应,由于IP是不存在的,服务器需要不断重发至超时,这些伪造的SYN包将长时间占用半连接队列,影响正常client的使用,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。 -
检测:在服务器看到大量半连接状态时,特别是IP地址是随机的,基本就可以断定这是以此SYN攻击 -
防范:
- 通过防火墙、路由器等过滤网关防护
- 加固TCP/IP协议栈防护
SYN攻击不能完全被阻止,要尽可能地减轻SYN攻击的危害
四次挥手
-
第一次挥手:client端发出链接释放报文FIN=1,seq(前面发送数据的最后一个字节序号+1)=u,client端进入FIN-WAIT-1状态 -
第二次挥手:server收到连接释放报文,发送确认报文,ACK=1,seq=v,ack=u+1,server进入CLOSE-WAIT状态。这时候处于半关闭状态,即client已经没有数据要发送了,但server若发送数据,client仍要接收。 client收到server的确认信息后,client进入FIN-WAIT-2状态,接收server发送最后的数据,等待server发送连接释放报文 -
第三次挥手:server将最后数据发送完毕后,发送连接释放报文,FIN=1,seq=w,ack=u+1,server进入LAST-ACK状态 -
第四次挥手:client收到server的连接释放报文,发出确认,ACK=1,seq=u+1,ack=w+1,client进入TIME-WAIT状态。此时TCP连接还没有释放,等待固定时间2MSL(最大报文段寿命)后,进入CLOSED状态。 server接收到client的确认后,也进入CLOSED状态。
为什么要四次挥手?
server可能还会有数据没有发送。如果仍有数据要发送的话,响应报文ACK和结束报文FIN不能同时发送给client。
而四次挥手就能解决这个问题: client发出连接释放通知,server确认收到之后,先回复一个ACK报文(告诉client,你请求连接释放我收到了),server把未发送的数据发送完毕后,发送连接释放通知,client确认后就关闭了。
四次挥手,为什么等待2MSL,才进入CLOSED状态
为了保证client发送的最后一个ACK报文段能够到达服务端 client发送的ACK可能丢失,如果server没有收到ACK,会不断发送FIN,所以client不能立刻关闭,等待2MSL的时间(发送和收到返回的最大时间)。如果再次接收到了FIN,就重发ACK再次等待2MSL。
简述:防止ACK报文丢失,server再次发送FIN报文,一来一回最长时间就是2MSL
如果建立了连接,客户端出故障怎么半?(保活计时器的作用?)
server每收到以此client的数据,就重置保活计时器(一般是两小时),如果两小时后没收到client的数据,就发送一个探测报文段,每隔75s发送一次。连续发送十个仍没响应后,就认为client出了故障,就关闭连接。
|