SYN攻击/ACK攻击/半/全连接队列

本文详细解释了半连接队列(SYN队列)和全连接队列(accept队列)在TCP协议中的作用,以及它们的数据结构。讨论了SYN攻击如何导致半连接队列满及防范措施,包括增大队列容量、减少重传次数和使用syncookies。最后分析了syncookies的优缺点,指出其在实际应用中的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要讲述:

  • 半/全连接队列是什么,有什么作用?
  • 半/全连接队列的数据结构是什么?
  • SYN攻击导致半连接队列满了怎么办?
  • 如何避免SYN攻击?
  • 为什么不使用syncookies取代半连接队列与ACK攻击?

一:半/全连接队列是什么,有什么作用?

在 TCP 三次握手调用了listen函数的时候,Linux 内核会创建并维护两个队列,分别是:

  • 半连接队列,也称 SYN 队列;
  • 全连接队列,也称 accept 队列;

服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到半连接队列,并向客户端响应 SYN+ACK,接着客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列,等待进程调用 accept 函数时把连接取出来。

所以半连接队列的作用是存放三次握手期间的半连接socket,全连接队列是用来存储建立了完整连接的连接,等待accept函数取出。

二: 半/全连接队列的数据结构是什么?

半连接队列和全连接队列虽然叫做队列,但是数据结构不是队列。

  • 半连接队列:哈希表
  • 全连接队列:链表 

(1)半连接队列为什么是哈希表

 半连接队列之所以选择哈希表作为数据结构是因为,半连接队列里面的连接都是不完整的,都在等待着第三次握手的到来,不同四元组连接第三次握手ACK到来的顺序和时间都不一定。可能后建立的连接,第三次握手先来。如果使用链表这样的线性逻辑表,每次第三次握手ACK到来,都需要从头到尾去逐个遍历半连接是不是这个ACK的连接。时间复杂度为On效率太低了,而使用哈希表来存储,那么查找时间复杂度为O1。

(2)全连接队列为什么是链表

 全连接队列选着使用链表,是因为全连接队列里面存储的都是完整的连接,不同四元组的完整连接之间没有顺序而言,因为accept函数都会取出然后执行下一步。所以先取出谁后取出谁没有关系,使用链表刚刚合适,我们只需要每一次取出头结点就可以了。

三:SYN攻击导致半连接队列满了怎么办?

 当服务器收到SYN请求的时候,即第一次握手时,会把连接放入半连接队列里面,同时回复SYN_ACK确认报文,在收到第三次握手的ACK后,又会将连接从半连接队列里面取出,然后创建一个新的连接放入全连接队列,等待accept函数调用返回。TCP在建立连接时系统会维护半连接队列和全连接队列,这两个队列都是有大小的。

 SYN攻击就是将目标服务器的半连接队列打满,导致真正的用户连接的SYN报文无法接收而被丢弃。 

四:如何避免SYN攻击?

想要避免SYN攻击,不单单只是考虑半连接队列大小的情况,即使半连接队列足够,全连接队列太小也不行。Linux内核对于全连接队列的处理动作由内核参数tcp_abort_on_overflow控制。

 tcp_abort_on_overflow:

  • 设置为0:如果全连接队列满了,服务器丢弃客户端ACK,(客户端可以重传)
  • 设置为1:如果全连接队列满了,服务器发送RST包给客户端,表示废弃这个握手过程和这个连接。

避免SYN攻击有四种办法:

  •  增大TCP的半连接队列。
  •  增大netdev_max_backlog。
  •  减少SYN+ACK的重传次数。
  •  使用tcp_syncookies

  a.增大TCP的半连接队列

        增大TCP的半连接队列需要同时增大内核的三个参数:只单单增大tcp_max_syn_backlog是无效的。

  • 增大net.ipv4.tcp_max_syn_backlog。
  • 增大listen()函数的backlog参数。
  • 增大net.core.somaxconn。

 b.增大netdev_max_backlog

网卡接收数据包也会有一个队列先把数据缓存起来, 等待内核处理,我们可以调大这个队列,使得该队列能够多存一些SYN包,等待内核慢慢处理。这个队列由内核参数netdev_max_backlog控制,默认1000。

 c.减少SYN+ACK的重传次数

当服务器受到SYN攻击时,服务器有大量的半连接,服务器出现大量的SYN_RECV状态,因为SYN攻击不会给服务器回复第三次握手,所以处于SYN_RECV状态的服务器收不到ACK就会重传第二次握手即SYN+ACK包,如果我们把SYN+ACK包的最大重传次数改小一点,由内核参数tcp_synack_retries决定,默认为5。那么就能更快断开连接。 

 d.使用tcp_syncookies

        开启了cookies可以在不使用半连接队列的情况下建立连接,也就没有半连接队列满一说。

  net.ipv4.tcp_syncookies参数有三个值:

  • 0:表示关闭该功能。
  • 1:表示半连接队列满了,装不下时再启用它。
  • 2:无条件启用它。

         cookies=1时,半连接队列满了处理如下:

   具体过程:

  • 当SYN队列满了,服务器再收到SYN包,不会丢弃。根据哈希算法计算出一个cookie值,将这个cookie值放入第二次握手的报文的序列号里,然后发送第二次报文给客户端。
  • 然后第三次握手客户端的ACK带着这个cookie值一起发送,服务器接收到了会验证cookie的合法性,如果合法就把该连接放入全连接队列,等待accept函数取走。

五: 为什么不使用syncookies取代半连接队列与ACK攻击?

前面说使用cookies就不怕SYN攻击了而且还能节约空间,不怕半连接队列满的情况,那为什么还要有半连接队列呢?直接用cookies模式不就好了。

虽然使用cookies模式可以节省一个半连接队列的空间,还可以防止SYN攻击,但是cookies的生成和验证是需要算法支持的,为了确保cookies的唯一性,不可被轻易防止,所以使用的算法都比较复杂。频繁的进行cookies验证和生成,计算量很大非常耗费CPU,而且服务器在没有解析cookie之前根本不知道该cookie是不是合法的,所以可以编造很多带上不合法cookies值的第三次握手ACK让CPU解析,如果解析完发现不合法,等于做了很多无用功消耗掉CPU资源,这就是ACK攻击。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值