TCP 中 SYN 攻击是什么?如何防止?
# SYN Flooding简介
拒绝服务攻击(DDoS)从1970 年出现直到今天都依然在作祟
并给全球范围内的各大组织带来了不可估量的损失。
SYN Flood是互联网上最经典的DDoS攻击方式之一,
最早出现于 1999 年左右,雅虎是当时最著名的受害者。
SYN Flood攻击利用了 TCP 三次握手的缺陷,能够以较小代价使目标服务器无法响应,且难以追查。
SYN flood 是一种常见的 DOS(denial of service拒绝服务)和 DDos(distributed denial of serivce 分布式拒绝服务)攻击方式。
这是一种使用TCP协议缺陷,发送大量的伪造的 TCP 连接请求,
使得被攻击方 CPU 或内存资源耗尽,最终导致被攻击方无法提供正常的服务。
# TCP SYN Flood攻击原理
TCP SYN Flood 攻击利用的是 TCP 的三次握手(SYN -> SYN/ACK -> ACK),
假设连接发起方是A,连接接受方是 B,即 B 在某个端口(Port)上监听A发出的连接请求,
过程如下图所示,左边是A,右边是B。
A 首先发送 SYN(Synchronization)消息给 B,要求 B 做好接收数据的准备;
B 收到后反馈 SYN-ACK(Synchronization-Acknowledgement) 消息给A,这个消息的目的有两个:
向 A 确认已做好接收数据的准备
同时要求 A 也做好接收数据的准备,此时 B 已向 A 确认好接收状态,并等待 A 的确认,连接处于半开状态(Half-Open),顾名思义只开了一半;A 收到后再次发送ACK (Acknowledgement) 消息给B,向 B 确认也做好了接收数据的准备,至此三次握手完成,「连接」就建立了,
大家注意到没有,最关键的一点在于双方是否都按对方的要求进入了可以接收消息的状态。而这个状态的确认主要是双方将要使用的消息序号(SquenceNum),TCP 为保证消息按发送顺序抵达接收方的上层应用,需要用消息序号来标记消息的发送先后顺序的。
TCP是「双工」(Duplex)连接,同时支持双向通信,也就是双方同时可向对方发送消息,其中 SYN 和 SYN-ACK 消息开启了A→B的单向通信通道(B 获知了 A 的消息序号);SYN-ACK 和 ACK 消息开启了B→A单向通信通道(A获知了B的消息序号)。
上面讨论的是双方在诚实守信,正常情况下的通信。
但实际情况是,网络可能不稳定会丢包,使握手消息不能抵达对方,也可能是对方故意不按规矩来,故意延迟或不发送握手确认消息。
假设 B 通过某 TCP 端口提供服务,B 在收到 A 的 SYN 消息时,积极的反馈了SYN-ACK 消息,
使连接进入半开状态,因为 B 不确定自己发给 A 的 SYN-ACK 消息或 A 反馈的 ACK 消息是否会丢在半路,
所以会给每个待完成的半开连接都设一个Timer,如果超过时间还没有收到 A 的 ACK 消息,
则重新发送一次 SYN-ACK 消息给A,直到重试超过一定次数时才会放弃。
B 为帮助 A 能顺利连接,需要分配内核资源维护半开连接,那么当 B 面临海量的连接 A 时,如上图所示,SYN Flood 攻击就形成了。攻击方 A 可以控制肉鸡向 B 发送大量 SYN 消息但不响应 ACK 消息,或者干脆伪造 SYN 消息中的 Source IP,使 B 反馈的 SYN-ACK 消息石沉大海,导致 B 被大量注定不能完成的半开连接占据,直到资源耗尽,停止响应正常的连接请求。
# 如何检测SYN攻击
查看服务器上是否能看到大量的半连接状态时,特别时源IP地址时随机的,基本可以断定这是一次SYN攻击
netstat -ntp|grep SYB_RECV
# 常见的防御SYN攻击方法
- 缩短超时(SYN Timeout) 时间
- 增加最大半连接数(SYN队列)
- 过滤网关防护
- SYN cookies技术 (opens new window)
- 减少syn+ack重传次数