tcp_syncookies=1不是“开了就万事大吉”,它仅在syn队列溢出时激活,未溢出前仍正常分配内存;启用后tcp_max_syn_backlog被忽略,且禁用sack等选项,需配合调低tcp_synack_retries和iptables限速才有效。

启用 tcp_syncookies=1 是当前最有效、开销最低的内核级缓解手段,但必须配合 tcp_synack_retries 调低和合理 iptables 限速,否则单靠它无法应对持续高强度攻击。
为什么 tcp_syncookies=1 不是“开了就万事大吉”
它本质是兜底机制:只有当半连接队列(SYN Queue)真正溢出时才激活。如果攻击流量还没填满队列,内核仍会照常分配内存保存每个 SYN_RECV 状态,照样吃内存、占 CPU。所以你看到 ss -s 里 synrecv 数量没降,不一定是没生效,而可能是队列还没满——得先让队列更容易“满”,才能触发 cookie 逻辑。
-
tcp_syncookies=1启用后,tcp_max_syn_backlog参数会被忽略,调大它毫无意义 - 它禁用 SACK 和窗口缩放等 TCP 选项,在高丢包链路(如跨境、弱 Wi-Fi)下可能轻微影响吞吐,但对 HTTP/HTTPS、gRPC 等短连接服务基本无感
- 值设为
2(无条件启用)反而更激进,且在某些旧内核(如 2.6.32)上存在兼容问题,1是安全平衡点
tcp_synack_retries 必须调到 2 或 3
默认值 5 意味着服务器最多等待约 63 秒才放弃一个伪造连接(重试间隔:1s, 3s, 7s, 15s, 31s)。攻击者就卡在这个“等待期”里反复发 SYN,把队列卡死。调成 2 后,超时时间压缩到约 3 秒(1s + 3s),能快速释放资源,显著降低 synrecv 峰值。
- 别设为
0:首次SYN+ACK发送失败即丢弃,云厂商 LB、NAT 网关后可能出现建连失败 - 这个参数只影响服务端行为,
tcp_syn_retries是客户端参数,服务器上改它无效 - 验证方式:
sysctl net.ipv4.tcp_synack_retries确认值已写入,再观察ss -s | grep synrecv是否明显回落
iptables 限速必须放在 INPUT 链靠前位置
内核层兜底,网络层过滤。规则若放得太靠后(比如在 -m state --state ESTABLISHED,RELATED -j ACCEPT 之后),大量伪造 SYN 包会直接穿透到协议栈,白白消耗 CPU。
- 推荐规则:
iptables -I INPUT -p tcp --syn -m limit --limit 50/s --limit-burst 10 -j ACCEPT,然后iptables -A INPUT -p tcp --syn -j DROP -
--limit-burst 10是“信用池”,允许突发 10 个包;50/s需按业务正常峰值微调(小 API 服务可压到 20/s) - 避免用
recent模块封 IP:高并发下性能损耗大,且 NAT 后用户易被误伤 - 这条规则必须用
-I插入 INPUT 链首,不能用-A追加到末尾
真正难防的是混合型攻击,单靠 sysctl 不够
当攻击者混用真实慢速 HTTP 请求、随机 User-Agent 扫描和低频 SYN 包时,tcp_syncookies 和 iptables 限速都会失效——因为流量看起来“合法”。这时候必须引入架构层防护:
- 前置反向代理(如 Nginx)承担 TCP 终结,后端服务禁止公网直连
- 云环境直接启用厂商 DDoS 防护(如阿里云 Anti-DDoS、AWS Shield Advanced)
- 关键服务部署熔断器(如 Sentinel、Hystrix),隔离异常节点,防止雪崩
记住:SYN Flood 无法彻底阻止,目标是让服务器不为伪造连接分配任何资源。所有参数调整都围绕这个核心——不是“扛住”,而是“不接”。











