欢迎光临散文网 会员登陆 & 注册

记录 - 4.30

2023-05-01 09:39 作者:剑离我离  | 我要投稿

什么是SYN攻击? 如何避免SYN 攻击?

攻击者短时间伪造不同ip地址的SYN报文,但不会对服务端的SYN+ACK 报文回复,久而久之,服务端的半连接队列就会被占满,使得服务端收到之后的SYN报文就会丢弃。

避免 SYN 攻击方式,可以有以下四种方法:

  • 调大 netdev_max_backlog;(当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包)

  • 增大 TCP 半连接队列;(增大 net.ipv4.tcp_max_syn_backlog、 listen() 函数中的 backlog、 net.core.somaxconn)

  • 开启 tcp_syncookies; (0 :关闭该功能;1:仅当SYN半连接队列放不下时,再启用;2:无条件开启。)

  • 减少 SYN+ACK 重传次数(最大重传次数由 tcp_synack_retries内核参数决定(默认值是 5 次))

TCP连接断开- 四次挥手

第一次握手丢失了,会发生什么?

触发客户端的重传,重发FIN报文,重发次数由 tcp_orphan_retries 参数控制。超过重传次数后,在等待一段时间(时间为上一次超时时间的 2 倍),如果还是没能收到第二次挥手,那么直接进入到 close 状态。

第二次握手丢失了,会发生什么?

ACK 报文是不会重传的。因此如果第二次挥手丢失,会触发客户端重发FIN报文。

对于 close 函数关闭的连接,由于无法再发送和接收数据,所以FIN_WAIT2 状态不可以持续太久,而 tcp_fin_timeout 控制了这个状态下连接的持续时长,默认值是 60 秒。即如调用close 关闭的连接,如果在60秒后还没有收到FIN报文,客户端(主动关闭方)的连接就会直接关闭。

但是如果主动关闭方使用 shutdown 函数关闭连接,指定了只关闭发送方向,而接收方向并没有关闭,那么意味着主动关闭方还是可以接收数据的。

此时,如果主动关闭方一直没收到第三次挥手,那么主动关闭方的连接将会一直处于 FIN_WAIT2 状态(tcp_fin_timeout 无法控制 shutdown 关闭的连接)。

第三次挥手丢失了,会发生什么?

因为没收到ACK,服务端重发FIN报文,重发次数由 tcp_orphan_retries 参数控制。

为什么TIME_WAIT 等待的时间2MSL?

MSL 是 Maximum Segment Lifetime,报文最大生存时间。

网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间2MSL时长 这其实是相当于至少允许报文丢失一次

如果被动关闭方没有收到断开连接的最后的 ACK 报文,就会触发超时重发 FIN 报文,另一方接收到 FIN 后,会重发 ACK 给被动关闭方, 一来一去正好 2 个 MSL。如果客户端再接收到服务端重传的FIN报文,那么2MSL时间将重新计时。

为什么需要TIME_WAIT 状态?

主动关闭连接的一方,才会有TIME_WAIT 状态

主要是两个原因:

  • 防止历史连接中的数据,被后面相同四元组的连接错误的接收;

2MSL这个时间足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。

  • 保证「被动关闭连接」的一方,能被正确的关闭;

TIME_WAIT 过多有什么危害?

  1. 占用系统资源,比如文件描述符、内存资源、CPU资源、线程资源等。

  2. 占用端口资源,可以通过 net.ipv4.ip_local_port_range参数指定范围。

如果客户端(主动发起关闭连接方)的 TIME_WAIT 状态过多,容易占满端口;

如果服务端(主动发起关闭连接方)的 TIME_WAIT 状态过多,并不会导致端口资源受限,因为服务端只监听一个端口,而且由于一个四元组唯一确定一个 TCP 连接,因此理论上服务端可以建立很多连接,但是 TCP 连接过多,会占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等。

如何优化 TIME_WAIT?

优化 TIME-WAIT 的几个方式,都是有利有弊:

  • 打开 net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps 选项;(复用连接,只对连接发起方有用)

  • net.ipv4.tcp_max_tw_buckets;(当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将后面的 TIME_WAIT 连接状态重置,这个方法比较暴力)

  • 程序中使用 SO_LINGER ,应用强制使用 RST 关闭。

服务器大量出现TIME_WAIT 状态的原因有哪些?

主动方关闭才有TIME_WAIT 状态

  • HTTP 没有使用长连接,是否关闭了HTTP Keep-Alive

  • 无论是客户端还是服务端禁用了Keep-Alive,都会由服务端来关闭连接的。

  • 客户端禁用:本来服务端开启的作用就是要复用连接,那不再重用连接的时机自然是由服务端控制,因此是由服务端来关闭的。

  • 服务端禁用:在服务端主动关闭时,调用一次close()就可以释放连接,剩下的工作由内核TCP 栈进行处理,整个过程只有一次 syscall ;但若客户端关闭,则在写完最后一个 response 之后需要把这个 socket 放入 readable 队列,调用 select / epoll 去等待事件;然后调用一次 read() 才能知道连接已经被关闭,这其中是两次 syscall,多一次用户态程序被激活执行,而且 socket 保持时间也会更长。

  • HTTP 长连接超时,如客户端完成一个HTTP请求后,就不再发起新的请求,此时这个TCP 连接就会一直占用资源。可以通过ngix提供的参数进行控制。

  • HTTP 长连接的请求数量达到上限。

服务器出现大量CLOSE_WAIT 状态的原因有哪些?

CLOSE_WAIT 状态是「被动关闭方」才会有的状态,而且如果「被动关闭方」没有调用 close 函数关闭连接,那么就无法发出 FIN 报文,从而无法使得 CLOSE_WAIT 状态的连接转变为 LAST_ACK 状态。

所以,当服务端出现大量 CLOSE_WAIT 状态的连接的时候,说明服务端的程序没有调用 close 函数关闭连接

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

  1. TCP 保活机制,可以设置保活时间、探测次数和时间间隔。但检测的时间较长。

  1. 如果对端正常工作,收到TCP 保活的探测报文后,保活时间会被重置

  2. 如果对端宕机并重启。收到报文可以响应,但没有该连接的有效信息,会发送RST报文

  1. 在应用层实现心跳检测。

如果已经建立了连接,但服务端的进程崩溃会发生什么?

TCP 的连接信息是由内核维护的,所以当服务端的进程崩溃后,内核需要回收该进程的所有 TCP 连接资源,于是内核会发送第一次挥手 FIN 报文,后续的挥手过程也都是在内核完成,并不需要进程的参与,所以即使服务端的进程退出了,还是能与客户端完成 TCP 四次挥手的过程。

关于accept

Linux内核中会维护两个队列:

  • 半连接队列(SYN 队列):接收到一个 SYN 建立连接请求,处于 SYN_RCVD 状态;

  • 全连接队列(Accpet 队列):已完成 TCP 三次握手过程,处于 ESTABLISHED 状态;

客户端 connect 成功返回是在第二次握手,服务端 accept 成功返回是在三次握手成功之后。

没有accpet,能建立TCP连接吗?

可以的。 accept 系统调用并不参与TCP 三次握手过程。他只是负责从全连接队列取出一个已经建立连接的 socket,用户层通过 accept 系统调用拿到了已经建立连接的 socket,就可以对该 socket 进行读写操作了。

客户端调用close,连接断开的流程是什么?

  • 客户端调用 close,表明客户端没有数据需要发送了,则此时会向服务端发送 FIN 报文,进入 FIN_WAIT_1 状态;

  • 服务端接收到了 FIN 报文,TCP 协议栈会为 FIN 包插入一个文件结束符 EOF 到接收缓冲区中,应用程序可以通过 read 调用来感知这个 FIN 包。这个 EOF 会被放在已排队等候的其他已接收的数据之后,表示在该连接上再无额外数据到达。同时发送ACK,服务端进入 CLOSE_WAIT 状态;

  • 接着,当处理完数据后,自然就会读到 EOF,于是也调用 close 关闭它的套接字,这会使得服务端发出一个 FIN 包,之后处于 LAST_ACK 状态;

  • 客户端接收到服务端的 FIN 包,并发送 ACK 给服务端,此时客户端进入 TIME_WAIT 状态;

  • 服务端收到 ACK 确认包后,就进入了最后的 CLOSE 状态;

  • 客户端经过 2MSL 时间之后,也进入 CLOSE 状态

没有listen ,能建立TCP 连接吗?

答案:可以的

客户端是可以自己连自己的形成连接(TCP自连接),也可以两个客户端同时向对方发出请求建立连接(TCP同时打开),这两个情况都有个共同点,就是没有服务端参与,也就是没有 listen,就能 TCP 建立连接。


记录 - 4.30的评论 (共 条)

分享到微博请遵守国家法律