tcp_max_syn_backlog 调到 32768 后仍 SYN flood 的 syn cookies 配合方案

4次阅读

tcp_max_syn_backlog设为32768无效,因其仅为SYN队列软限制,实际容量取min(listen() backlog, somaxconn, tcp_max_syn_backlog);且SYN flood下请求远超队列容量,是否启用SYN cookies取决于tcp_syncookies值及内存压力,而非backlog大小。

tcp_max_syn_backlog 调到 32768 后仍 SYN flood 的 syn cookies 配合方案

tcp_max_syn_backlog 设为 32768 为什么没用

因为 tcp_max_syn_backlog 只控制「未完成三次握手的连接」在 SYN queue 中的最大数量,它不决定是否启用 SYN cookies,也不影响已启用 SYN cookies 后的行为。当队列满时,内核是否丢包、是否 fallback 到 SYN cookies,取决于 net.ipv4.tcp_syncookies 的值和当前内存压力,而不是 backlog 大小。

常见误判是:调大了 tcp_max_syn_backlog 就能扛住 SYN flood —— 实际上,SYN flood 下连接请求远超队列容量,大量请求根本进不了 queue,直接触发丢包或 SYN cookies 判定逻辑。

  • tcp_max_syn_backlog 是软限制,受 net.core.somaxconn 和 listen() 的 backlog 参数共同约束(取三者最小值)
  • 即使设为 32768,若应用调用 listen(sockfd, 128),内核仍可能只分配 128 槽位
  • 该值对内存占用有直接影响:每个 pending SYN 条目约占用 200–300 字节,32768 ≈ 6–10 MB 内存

tcp_syncookies=1 是必须开的,但要注意触发条件

开启 net.ipv4.tcp_syncookies = 1 是应对 SYN flood 的关键,但它不是“一直生效”,而是在特定条件下才激活:

  • 仅当 SYN queue 满 + 内核检测到 low memorynet.ipv4.tcp_abort_on_overflow = 0 时,才会对新 SYN 发送 cookie
  • tcp_abort_on_overflow = 1,则直接丢包、不发 RST,客户端重试,反而加重攻击面
  • tcp_syncookies = 2 表示“无条件启用”(绕过内存检查),但会禁用 TCP 扩展选项(如 SACK、Timestamps),影响性能和兼容性

推荐配置组合:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_abort_on_overflow = 0
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 32768

应用层 listen() 的 backlog 参数必须同步改

内核不会自动把 tcp_max_syn_backlog 映射到每个 socket;它只作为上限参考。真正起作用的是应用调用 listen() 时传入的 backlog 值,内核取 min(backlog, somaxconn, tcp_max_syn_backlog) 作为该 socket 的 SYN queue 容量。

  • go 默认 listen() backlog 是 128;nginx 默认是 511;java Netty 若未显式设置,可能用系统默认(常为 128)
  • 必须在代码或配置中显式加大:例如 Nginx 配置加 listen 80 backlog=32768;,Go 用 net.ListenConfig{Control: ...} 设置 SOMAXCONN
  • 检查当前生效值:ss -lnt | grep :80 看 Recv-Q 列上限(即实际 queue size)

SYN cookies 不是银弹,真实瓶颈常在 conntrack 或网卡中断

开了 SYN cookies 后仍被压垮,大概率问题已溢出协议层面:

  • conntrack 表满(nf_conntrack_count 接近 nf_conntrack_max)会导致新建连接失败,错误日志里会出现 "nf_conntrack: table full"
  • 单核 CPU 处理软中断(softirq)瓶颈:SYN flood 产生大量 NET_RX 中断,若网卡未做 RSS/RPS,所有包都压到一个 CPU 核,top 里能看到 si% 持续 90%+
  • 云环境注意:某些厂商的 SLB 或安全组会在四层前过滤,导致你看到的 SYN 包数远少于真实攻击流量

真正抗住大规模 SYN flood,靠的不是调几个 sysctl,而是:网卡多队列分流 + conntrack 限速 + 前置防火墙规则(如 iptables -A input -p tcp --syn -m limit --limit 100/sec --limit-burst 200 -j ACCEPT)+ 应用层快速 accept() 防止 queue 积压。

text=ZqhQzanResources