Linux_三次握手、四次挥手

Linux_三次握手、四次挥手_第1张图片

三次握手:
第一次握手:客户端发送syn包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1)(确认号:数值等于发送方的发送序号+1(即接收方期望接收的下一个序列号)),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
Linux_三次握手、四次挥手_第2张图片

相关问题
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

三次握手发生在什么时候?
发生在传输层,在传递数据前使用三次握手机制确保建立了稳定可靠的连接,然后开始传递数据。

为什么是三次握手?
假设主机A为客户端,主机B为服务器端。
1、TCP的三次握手过程:主机A向B发送连接请求;主机B对收到的主机A的报文段进行确认;主机A再次对主机B的确认进行确认。
2、采用三次握手是为了防止失效的连接请求报文段突然又传送到主机B,因而产生错误,导致资源浪费。
失效的连接请求报文段是指:主机A发出的连接请求没有收到主机B的确认,于是经过一段时间后,主机A又重新向主机B发送连接请求,且建立成功,顺序完成数据传输。考虑这样一种特殊情况,主机A第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到主机B,主机B以为是主机A又发起的新连接,于是主机B同意连接,并向主机A发回确认,但是此时主机A根本不会理会,主机B就一直在等待主机A发送数据,导致主机B的资源浪费。
3、采用两次握手不行,原因就是上面说的失效的连接请求的特殊情况,因此采用三次握手刚刚好,两次可能出现失效,四次握手则没有必要。

那个阶段容易受到攻击?
每一个阶段都有可能收到攻击, 只是在受到攻击后,损失可能大小不同
第一阶段受到攻击:第一次握手发送的请求连接信息丢失,超时重传机制,损失较小
第二阶段受到攻击:第二次握手回复的请求连接信息丢失,则客户端存在认为第一次握手的请求数据丢失,从而重新发送,而服务器已经回复过信息,存在可能认为客户端放弃了第一次发起的连接,而重新回复信息,进行第二次连接确认,损失较大,更易受到攻击,SYN攻击
第三阶段受到攻击:第三次握手确认建立,超时重传,损失较小

SYN攻击
在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态.
Syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
Syn攻击是一个典型的DDos攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击
在Linux下可以如下命令检测是否被Syn攻击:netstat -n -p TCP | grep SYN_RECV

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
 

四次挥手
第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接受数据。随后主动关闭方进入FIN_WAIT_1状态
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1。进入CLOSE_WAIT状态,主动关闭方进入FIN_WAIT_2状态
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。进入LAST_ACK状态,主动关闭方进入TIME_WAIT状态,
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。
Linux_三次握手、四次挥手_第3张图片

四次挥手发生在什么时候?
发生在数据传输层,由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

挥手中可能遇到的攻击
第一次挥手:存在遇到攻击的可能、损失小
第二次挥手:存在遇到攻击的可能、损失大
第三次挥手:存在遇到攻击的可能、损失最大
第四次挥手:存在遇到攻击的可能、损失小

为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文(三次挥手)。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到Server端所有的报文都发送完了,才会去关闭SOCKET,才发送FIN报文,因此不能一起发送。故需要四步握手。

TIME_WAIT 状态存在的意义
所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

TIME_WAIT状态由两个存在的理由。
1、可靠的实现TCP全双工链接的终止。保证可靠的终止TCP链接

网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。
2、允许老的重复的分节在网络中消逝。保证迟来的数据能被识别并丢弃
假设在192.168.168.255的6000端口和192.168.168.254的5999端口之间有一个TCP连接。我们关闭这个链接,过一段时间后在相同的IP地址和端口建立另一个连接。后一个链接成为前一个的化身。因为它们的IP地址和端口号都相同。TCP必须防止来自某一个连接的老的重复分组在连接已经终止后再现,从而被误解成属于同一链接的某一个某一个新的化身。为做到这一点,TCP将不给处于TIME_WAIT状态的链接发起新的化身。既然 TIME_WAIT状态的持续时间是MSL的2倍,这就足以让某个方向上的分组最多存活msl秒即被丢弃,另一个方向上的应答最多存活msl秒也被丢弃。 通过实施这个规则,我们就能保证每成功建立一个TCP连接时。来自该链接先前化身的重复分组都已经在网络中消逝了。

TIME_WAIT时程序关闭,端口号被占用处理方式
1、等待2min,占用的端口号将会被释放 
2、socket选项设置,int SO_REUSEADDR  重用本地地址

你可能感兴趣的:(Linux)