我们知道,TCP 协议是一个可靠的、面向连接的协议。因此,使用 TCP 方式进行网络通信前,首先要进行建立连接。
三次握手过程
TCP 三次握手建立连接的过程如下:
客户端发送一个 SYN 同步报文给服务器端,该报文中包含了本端的初始化序列号,同时设置本段的连接状态为 SYN-SENT。
服务器端收到同步报文后,给客户端回应 SYN+ACK 报文,该报文中包含本段的初始化序列号。同时设置本端连接状态为 SYN-RCVD。
客户端收到服务器端的 SYN+ACK 后,向服务器端发送 ACK 报文进行确认,同时设置本端连接状态为 ESTABLISHED 状态。
服务器端收到 ACK 报文后设置本端连接状态为 ESTABLISHED。
三次握手的完成标志着一个TCP连接的成功建立。
SYN Flood 攻击原理
当客户端向服务器端发送 SYN 包后,对服务器端回应的 SYN+ACK 包不进行处理,会出现什么结果呢?
如下图:
服务器端发送完 SYN+ACK 报文后,会建立一个半连接状态的socket套接口,同时会启动一个定时器,若在超时时间内未收到对方回应的ACK报文,服务器端会进行超时重传 SYN+ACK 报文给客户端,默认重传次数为5次,(重试会经历 1、2、4、8、16 秒,最后一次重试后要等待 32 秒,若仍收不到 ACK 报文,才会关闭连接,故共需等待 63 秒)。
因此,我们知道,若客户端不停的发送 SYN 报文并对服务端回应的报文置之不理,会导致服务器端不停的创建半连接状态的 socket 而耗尽资源,从而服务器端无法处理正常的客户端的连接请求,这就是所谓的 SYN Flood 攻击。
SYN Flood(SYN 泛洪) 攻击是一种广为人知的 DoS (Denial of Service 拒绝服务)攻击。这是一种利用 TCP 协议缺陷,传送大量伪造的 TCP 连接请求,从而使对方 TCP 资源耗尽,停止响应正常的 TCP 连接请求。
SYN Flood 攻击实验
从上面原理知道,SYN Flood 攻击就是客户端发送大量的 SYN 报文个服务端。因此本实验的目的就是构造大量的 SYN 包发向对端。
对于构造 SYN 报文,报文中我们需要构造 TCP 首部 和 IP 首部。
TCP 首部格式如下:
根据首部格式我们定义 TCP 首部格式如下:
在构建 TCP 首部时,由于是构建 SYN 报文,因此需要设置 SYN 标志位为 1 。
对于源端口号和序列号,我们可以设置成随机数,目的的端口设置为被攻击对象的端口号。
由于是第一个同步报文,我们不知道对方的确认号,因此确认号设置为 0。
窗口大小我们也可以随便设置,但尽量不要太小。
校验和检验的范围包括首部和数据两部分,在计算校验和时,要在 TCP 报文段前面加上 12 字节的伪首部。 伪首部的格式如下:
伪首部共占用 12 个字节。包括 32 位源 IP 地址,32 位目的 IP 地址,8 位的保留字节(填充0),8 位的传输层协议号(TCP 为 6,UDP 为 17),16 位的 TCP 报文长度(TCP首部 + 数据)。
紧急指针不关心,可以设置为 0。
根据首部格式,定义伪首部结构如下:
对于校验和的计算,我们可以直接从网上找到一个封装好的函数。
由于相同的 IP 地址可以被对方识别从而进行过滤,因此我们需要定义 IP 首部。这样我们在攻击的时候可以设置不同的 IP 地址。
IP 首部格式如下:
根据 IP 首部格式定义 IP 首部结构如下:
TCP 头部初始化
通过 initTcpHeader 函数完成 TCP 首部的初始化
TCP 伪首部的初始化
IP 头部初始化
SYN 包的构建
由于 SYN 报文没有实际的数据,因此生成的整个 SYN 包结构如下:
创建原始套接字
由于我们是自定义 TCP/IP 数据包,因此我们需要使用原始套接字进行发送数据。
发送 SYN 数据包
主函数
主函数的作用就是不停的构造并发送SYN数据包。
对程序进行编译
运行程序
对 本机 上的 8090 端口进行 SYN 攻击。
我们可以使用如下命令来查看 TCP 的连接状态。
从上面的结果来看,服务器端生成了很多半连接的 socket,因此我们的攻击时成功的。
总结
本文介绍了 SYN Flood 攻击的原理,通过实验我们可以对 SYN Flood 攻击有了进一步的理解。本文的主要目的只是探讨技术,同时对网络的一种学习。
原作者: Linux码农