连接—三次握手:
流程图:
过程详解:
客户端(connect)连接服务器(listen)
- Client将标志位SYN置为1,随机产生一个值seq=x, 并将该数据包发送给Server, Client进入SYN_ SENT状态,等待Server确认。
- Server收到数据包后由标志位SYN=1知道Client请求建立连接, Server将标志位SYN和ACK都置为1, ack=x+1, 随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求, Server进入SYN_ RCVD状态。
- Client收到确认后,检查ack是否为x+1, ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将该数据包发送给Server;
Server检查ack是否为y+1, ACK是否为1,如果正确则连接建立成功,Client 和Server进入ESTABLISHED状态, 完成三次握手,随后Client与Server之 间可以开始传输数据了。
断开—四次挥手:
流程图:
断连详解:
首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
- 数据传输结束后,Cli的应用进程发出连接释放报文段FIN,并停止发送数据,客户端进入FIN WAIT 1状态,此时客户端依然可以接收服务器发送来的数据。
- 服务器接收到FIN后,发送一个ACK给客户端, 确认序号ack=收到的序号+1,服务器进入CLOSE WAIT状态。客户端收到服务器的ACK后进入FIN WAIT_2状态。
- 当服务器完成了自己的发送工作后没有数据要发送时,服务器发送一个FIN报文, 此时服务器进入LAST_ ACK状态,等待客户端的确认
- 客户端收到服务器的FIN报文后,给服务器发送一个ACK报文, ack=收到的序号+1。此时客户端进入TIME_ WAIT状态,等待2MSL (MSL: 报文段最大生存时间),然后关闭连接。
断连原理:
TCP是全双工,每个方向都需要单独关闭,一方完成了自己的发送任务后,主动发送终止报文FIN结束此方向连接,代表从此刻开始这个方向不会再发送除了断连工作的必要报文外一切信息数据,直至对面方向也发送了FIN结束报文。
1. 三次握手容易出现的攻击---syn泛洪攻击
泛洪攻击、syn溢出攻击,DoS(拒绝服务攻击)的一种形式。
- 出现在第二次握手阶段
- 流程:攻击者伪造大量不存在的IP地址,一时间发送大量的第一次握手的同步报文,导致服务器需要在短时间内完成对客户端信息的保存并发送确认和自己的同步报文信息,为每一个建立连接的客户端开辟内存空间,而洪范攻击无第三次握手即第三次确认报文,服务器最终会连接失败,在判断识别失败需要的时间内,服务器就会因为短时间内的大量syn报文导致资源耗尽,正常的客户端连接需求亦无法得到满足。
- Land攻击:
在这种攻击中,攻击者发送一个SYN包,其源地址和目标地址都是受害服务器的IP地址。当服务器回复SYN+ACK包时,这个包实际上又被发送回服务器自己。这种攻击可能导致服务器资源耗尽,因为它不断地处理自己发送的包。
- Connection Flood攻击:
攻击者利用真实的IP地址向服务器发起大量的连接请求,建立连接后长时间不释放,并定期发送垃圾数据包以保持连接活性。这会导致服务器上残余连接(WAI-time状态)过多,效率降低,甚至资源耗尽,无法正常响应其他客户的连接请求。
2. 为了防范这些攻击,可以采取以下措施:
- 限制每个源IP的连接数:防止单个IP地址建立过多的连接。
- 对恶意连接的IP进行封禁:一旦发现某个IP地址在进行异常行为,可以将其封禁。
- 降低SYN timeout时间:使得服务器尽快释放半连接的占用,减少资源消耗。
- 采用SYN cookie技术:如果短时间内连续收到某个IP的重复SYN请求,则视为攻击,并丢弃后续请求。
- 在网关处设置过滤:拒绝将源IP地址不属于其来源子网的包进行路由。
请注意,这些防范措施并非绝对安全,应结合实际情况和安全需求进行选择和部署
3. 两次握手可以吗?
不可以
举反例以证实三次不可或缺
失效的连接报文请求:
客户端发出的SYN同步报文在传输过程中未及时到达服务器,在网络结点停滞到客户端与服务器连接、已经断联2MSL以后才到达。
在此情况下,若只有两次握手便可以达成连接,服务器则同意连接发送同步、确认报文。
客户端收到服务器发来的报文以无效处理,并不会给服务器发送信息,也不会主动断连,而服务器将会在等待中白白浪费内存资源
若有客户端第三次确认连接则不会发生以上问题
Dos攻击无法防范:
黑客会伪造大量SYN请求发送给服务器,服务器立即确认并建立连接,分配资源,但是这一系列连接并不是真实存在的, 这大大浪费了服务器的资源并且阻塞了正常用户的连接,这种也叫SYN洪泛攻击。
第二种是服务器返回给客户端的ACK数据包可能会在传输的过程中丢失
而客户端没有收到该ACK数据包而拒绝接收服务器接下来发送的数据,于是服务器因TCP可靠传输的超时重发和确认应答机制一直重复发送,客户端一直在拒绝, 形成死锁。
反之三次握手就可以解决以上问题.
4. 四次挥手可以变为三次挥手吗?
- 不能,四次挥手是必要的:
TCP全双工通信,所以各个方向都需要进行关闭连接,在主动断开放完成发送任务后向连接端发送结束FIN报文后,表示此方向已不会再发送信息数据(不排除TCP断连报文),而被动断开方接收到FIN结束报文后,首先确认发送ACK确认报文,以免主动断开放误以为FIN结束报文发送失败重新发送,然而被动断开方仍需处理自己的发送工作内容,直至完成后才向主动断开方再发送FIN报文,来表示现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的,这也是为什么释放连接时需要交换四次报文了。
- 偶尔,当客户端与服务器同时选择断开连接时,即代表双方都没有需要发送的数据信息后,即可以合并ACK 和 FIN 报文,变成三次挥手
5. 三次握手第二个阶段的异常
第二阶段:
服务器的端口号未打开,会回复 RST 复位报文,握手失败
服务器listen异常,监听队列达到上限,也可能失败
6. TCP三次握手第一次产生的SEQ
由ISN算法得到的。
seq=C + H (源IP地址,目的IP地址,源端口,目的端口)
C 计时器,每隔一段时间值就会变大;
H 消息摘要算法,输入是一个四元组(源IP地址,目的IP地址, 源端口,目的端口)
7. TCP的同时握手与同时挥手
同时打开连接是指通信的双方在接收到对方的SYN包之前,都进行了主动打开的操作并发出了自己的
SYN包。如之前所说一个四元组标识一个TCP连接,因此如果一个TCP连接要同时打开需要通信的双方知
晓对方的IP和端口信息才行,这种场景在实际情况中很少发生(NAT穿透中可能会多一些)。 同时打开的流
程如下图:
注意上图中,TCP连接同时打开的时候与三次握手的主要区别如下
1)我们同时称呼A和B为Client,他们都执行主动J开的操作(Active Opener)。
2)同时两端的状态变化都是由CLOSED->SYN SENT->SYN _RCVD->ESTABLISHED。
3)建立连接的时候需要四个数据包的交换,并且每个数据包中都携带有SYN标识,直到收到SYN的ACK为止同时关闭连接.
相对于四次握手过程基本类似,注意两者状态转换的区别,同时关闭的状态变化是:
ESTABLISHED->FIN_WAIT 1->CLOSING->TIME WAIT->CLOSED
8. TCP第三次握手携带数据
第三次携带,当客户端最后一次握手后发送确认报文后,对客户端来说已经建立连接,已经明确服务器的接收发送能力
第一次不能,客户端以确认报文中夹杂恶意信息,频繁发送SYN ,服务器将浪费大量时间、空间接收处理
第二次不能,服务器并不确认客户端是否真实有效,不是虚拟的恶意连接、或攻击,在大量连接请求时,携带数据会使得服务器更快的资源耗尽
9. TIME_WAIT 状态存在的意义
TIME_WAIT 指第四次挥手时,发送完确认报文后
- 保证在接收FIN报文后一切迟来报文被识别并丢弃
- TCP可靠连接的保证,使得对方成功接收ACK 报文,若ACK丢失对方会重发FIN报文并重新期待收到ACK
- TIME_WAIT 时间在2MSL (报文的最大传输时间1MSL:2分钟)
10. 在 Linux 系统上,一个TCP端口无法短时间建立两个或以上连接
TCP 在连接后释放处于TIME_WAIT 状态时,无法使用占用端口建立连接
强制进程立即使用处于 TIME_WAIT 状态的连接所占用的端口,可以通过 setsockopt()方法设置 socket 选项 SO_REUSEADDR 来完成。
11. TIME_WAIT 和 CLOSE_WAIT的区别
CLOSE_WAIT:第二次挥手,已发送对对方FIN 的确认ACK 报文
等待自己发送工作完成,未关闭
TIME_WAIT :第四次挥手,已发送最后的ACK确认报文
保证ACK 报文可靠传输,识别并丢弃迟来的报文信息,避免快速的经行下次连接而将以往无效报文接收
12. 服务器端出现大量的CLOSE_WAIT
第二次挥手阶段:已收到FIN 并回复ACK
总原因:服务器未完成工作内容且时间过长,没有发送FIN完成第三次挥手
- 服务器内部业务处理占用了过多时间,都没能处理完业务;
- 或者还有数据需要发送
- 或者服务器的业务逻辑有问题,没有执行close()方法
- 服务器的父进程派生出子进程,子进程继承了socket,收到FIN的时候子进程处理但父进程没有处理该信号,导致socket的引用不为0无法回收
处理方法:
- 停止应用程序
- 修改程序里的bug
13. TIME_ WAIT期间收到数据包
要根据包的情况,做出很多种的判断
RST 包
序列号是下一个要接受的序列号
立即释放time_ wait传输控制块,丢掉RST包。
不是下一个要接受的序列号:
丢弃
ACK 包
序列号是下一个要接受的序列号:
启动TIME WAIT定时器,丢弃ACK。
不是下一个要接受的序列号:
启动TIME WAIT定时器,然后给对端发送ACK。
SYN 包
上一个结束序列号大
可以接受,并建立新的连接
是上次结束前序列号
不会启动TIME _WAIT定时器,只会给对端发送ACK,告诉对端已经收到SYN包,避免重传,但连接应该不会继续建立。
14. 什么是RST?
tcp报头:
复位RST (ReSeT)当 RST= 1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。RST置1还用来拒绝一个非法的报文段或拒绝打开一一个连接。RST也可称为重建位或重置位。