本文目录导读:

net.ipv4.tcp_syncookies 是一种操作系统内核层面的防御机制,专门用来应对 SYN Flood(SYN洪水攻击)。
下面详细解释它的工作原理和优缺点。
核心问题:SYN Flood 攻击为何有效?
SYN Flood 攻击利用了 TCP 三次握手的漏洞,攻击者发送大量伪造源 IP 地址的 SYN 请求,但从不回复 ACK。
受害服务器在收到 SYN 后,会:
- 分配内存和数据结构(称为
tcp_request_sock,约 256 字节)用于记录这个“半连接”。 - 回复 SYN+ACK。
- 进入
SYN_RECV状态,并等待 ACK。
由于源 IP 是伪造的,服务器永远不会收到 ACK,这些半连接会一直占用内存,直到超时(默认约 60-120 秒),当半连接队列(syn backlog)被填满后,新的正常连接请求就会被丢弃,导致正常用户无法访问服务。
攻击者通过消耗服务器有限的内存资源(半连接队列),实现拒绝服务。
核心原理:用“计算”代替“存储”
tcp_syncookies 的核心思想是:服务器不再为每一个收到的 SYN 包分配内存并存储状态,而是将连接状态信息编码(加密/哈希)进 SYN+ACK 包的序列号(Sequence Number)中,然后直接丢弃该 SYN 包对应的内存记录。
这个编码后的序列号被称为 Cookie。
工作流程详解
当 tcp_syncookies 开启时(通常在 SYN 队列快满时自动激活),流程如下:
第一步:收到 SYN 包 服务器收到一个 SYN 包。
第二步:不分配内存,生成 Cookie
服务器不会在内存中创建 tcp_request_sock 结构,而是根据以下信息计算一个无法伪造的、有时间限制的哈希值:
- 源 IP 地址和端口
- 目标 IP 地址和端口
- 一个服务器端保密的密钥(定期更换)
- 一个精细的时间戳(通常以 64 秒为一个周期)
这个哈希值就是 Cookie,它被作为 SYN+ACK 包的初始序列号(seq) 发送给客户端。
第三步:收到客户端的 ACK 包(真正的握手完成)
如果客户端是真实的,它会回复 ACK 包,其中包含 确认号(ack) = Cookie + 1。
第四步:验证 Cookie 服务器收到该 ACK 包后:
- 提取 Cookie:从
ack - 1得到 Cookie。 - 重新计算:用当前的时间、服务器密钥以及客户端 IP/端口,重新计算哈希。
- 比对:
- 匹配:如果计算出的哈希值与 ACK 包中的 Cookie 一致,说明这个连接是合法的(因为只有收到我们 SYN+ACK 的客户端才能计算出正确的
ack值),这时,服务器才真正分配内存,建立起完整的 TCP 连接(ESTABLISHED状态)。 - 不匹配:如果哈希值不对(客户端伪造了
ack或 Cookie 已过期),服务器直接丢弃该 ACK 包,不分配任何资源。
- 匹配:如果计算出的哈希值与 ACK 包中的 Cookie 一致,说明这个连接是合法的(因为只有收到我们 SYN+ACK 的客户端才能计算出正确的
示意图对比
无 syncookies:
攻击者 (伪造IP) 服务器
|--- SYN ----------->| [#1] 分配内存,加入SYN队列
|<-- SYN+ACK --------| [#2] 内存被占用 (满)
| |
|--- SYN ----------->| [#3] 队列已满,拒绝
| |
正常用户 |
|--- SYN ----------->| [#4] 连接被拒绝,无法访问
启用 syncookies:
攻击者 (伪造IP) 服务器
|--- SYN ----------->| [#1] 不分配内存,只计算Cookie
|<-- SYN+ACK (seq=Cookie) | [#2] 发送Cookie后无状态
| | (攻击者不回复ACK,资源完全没被占用)
| |
正常用户 |
|--- SYN ----------->| [#3] 同样不分配内存,只计算Cookie
|<-- SYN+ACK (seq=Cookie) | [#4]
|--- ACK (ack=Cookie+1) ->| [#5] 收到ACK,验证Cookie
| | [#6] 验证通过!分配内存,建立连接
|<-- 正常数据通信 ---| [#7] 开始传输数据
优点与缺点
| 优点 | 缺点 |
|---|---|
| 极其有效:能完全防御普通 SYN Flood 攻击,特别是消耗内存型的攻击。 | 破坏 TCP 选项:Cookie 中能够编码的信息非常有限(32位),大部分 TCP 时间戳(TCP Timestamps)、选择性确认(SACK)、窗口缩放(Window Scaling) 等优化选项的信息无法被编码进去。这会导致高延迟、长距离连接的性能显著下降,甚至无法利用到宽带网络的最佳性能。 |
| 资源零消耗:在 SYN 洪水期间,服务器几乎不消耗内存,CPU 仅用于计算哈希。 | 轻微计算开销:虽然哈希计算很快,但在极端情况下(每秒数百万个 SYN 包),CPU 本身也可能成为瓶颈。 |
| 自动开启:通常内置于 Linux 内核中,无需额外安装软件。 | 无法防御所有变种:主要防御的是消耗内存的普通 SYN Flood,对于其他变种(如消耗 CPU 的 SSL 握手洪水),syncookies 无效。 |
| 设计简单健壮:基于“无状态”思想,非常可靠。 | Cookie 有有效期:ACK 包延迟超过时间窗口(64 秒),Cookie 会失效,导致正常用户连接失败,通常认为这不是主要问题。 |
如何配置与检查
-
查看当前状态:
sysctl net.ipv4.tcp_syncookies
返回值:
1:表示开启(通常默认开启)。0:表示关闭。
-
临时开启:
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
或
sysctl -w net.ipv4.tcp_syncookies=1
-
永久开启:编辑
/etc/sysctl.conf文件,添加或修改:net.ipv4.tcp_syncookies = 1然后执行
sysctl -p使其生效。
最佳实践建议
- 默认保持开启:对于大多数面向公网的服务器,建议保持
tcp_syncookies为1(开启),作为最后一道防线。 - 不要只依赖它:它是在 SYN 队列溢出时才自动启用的救急手段,对于生产环境,更好的做法是:
- 增大 SYN Backlog 队列:
net.core.somaxconn和net.ipv4.tcp_max_syn_backlog。 - 开启
tcp_tw_reuse和tcp_tw_recycle(注意:tcp_tw_recycle在 NAT 环境下有问题,已在新内核中移除)。 - 使用专业的 DDoS 防护设备/服务(如 Cloudflare、AWS Shield、阿里云盾等),它们能在流量到达你的服务器之前就进行清洗。
- 增大 SYN Backlog 队列:
- 监控 SYN 包异常:如果发现
tcp_syncookies频繁被触发,说明你的服务器正在遭受 SYN Flood 攻击,需要立即采取措施。
tcp_syncookies 就像一个“紧急备用钥匙”——它能保证在服务器被 SYN 洪水塞爆时,依然能保证正常用户的连接,但它降低了连接性能(破坏 TCP 优化选项),所以它是“生存”而非“性能优化”的机制。
标签: SYN攻击