SYN Cookie机制应对连接队列耗尽,关键是先确认耗尽的是哪一段队列。Linux TCP 建连通常经历 SYN 请求排队和已完成连接等待应用程序 accept 两个阶段;SYN Cookie 主要缓解前者,不能替代应用扩容或解决 accept 队列积压。以下五项建议适用于 Linux TCP 监听服务,参数效果会受内核版本、流量和程序行为影响。
1. 按需启用 SYN Cookie,不要把它当作常态扩容
客户端发送 SYN 后,服务器通常暂存连接请求,再收到 ACK 才完成握手。队列压力过大时,SYN Cookie 可将部分状态编码进 TCP 序列号,减少暂存请求所需的内存。它主要针对 SYN Flood 或突发 SYN 请求导致的 SYN backlog 压力。
先用 sysctl net.ipv4.tcp_syncookies 查看当前值。Linux 上常见设置中,值为 1 表示在 SYN 队列溢出时启用;具体行为应以当前内核文档为准。不要仅为追求“更安全”就改成无条件使用模式:Cookie 会带来握手处理开销,也可能限制部分 TCP 选项协商能力。
2. 分清 SYN backlog 与 accept 队列
抓包看到大量未完成握手,或内核的 Cookie 计数持续增加,才更像 SYN backlog 承压。如果客户端握手已经完成,但服务进程来不及调用 accept,问题更可能在 accept 队列。此时单靠 SYN Cookie不会让应用更快接收连接。
检查监听进程、工作线程、CPU 和文件描述符使用情况;再核对应用传入 listen() 的 backlog,以及系统的 net.core.somaxconn。Linux 内核版本和应用设置会影响实际队列上限,不能只调其中一个参数便认定队列已扩容。
3. 先观测,再调整队列上限
队列容量应结合连接突发规模、应用 accept 速度和内存预算确定,不存在适用于所有服务器的固定值。对普通业务,可先观察高峰时段的溢出计数,再逐步调整;若把容量调得很大但应用长期处理不过来,只会让等待时间和资源占用增加。
- 记录当前设置:执行 sysctl net.ipv4.tcp_syncookies net.ipv4.tcp_max_syn_backlog net.core.somaxconn。
- 观察内核统计:执行 nstat -az,关注 TcpExtSyncookiesSent、TcpExtSyncookiesRecv、TcpExtSyncookiesFailed、TcpExtListenOverflows 和 TcpExtListenDrops。不同发行版工具输出可能略有差异。
- 在流量高峰重复采样,并同时查看监听进程的连接处理能力;结合连续多个观察窗口决定是否调整。
4. 以可回退方式配置并验证
临时验证可用 sudo sysctl -w net.ipv4.tcp_syncookies=1。确认效果后,再将设置写入系统支持的 sysctl 配置文件,例如 /etc/sysctl.d/ 下的独立文件,并按发行版方式加载。修改前记录原值,避免故障时无法恢复。
验证时在受控测试环境或低风险时段进行:确认参数已生效,观察 SYN 队列溢出期间 Cookie 计数是否变化,并检查正常客户端的连接成功率、延迟和 TCP 选项协商。不要在生产环境自行制造大规模 SYN Flood;测试流量应受控,且取得必要授权。
5. 将内核防护与流量处置配合
SYN Cookie机制应对连接队列耗尽只覆盖主机 TCP 握手的一部分。若异常流量压满网络带宽,主机即使启用了 Cookie 也无法恢复链路容量;应联系网络服务提供方评估上游清洗、限流或路由层处置。若确有需要,可评估 Linux 的 SYNPROXY 等防护方案,但部署前须理解防火墙规则、连接跟踪和负载均衡路径,先在测试环境验证,避免误拦正常连接。
常见问题
开启 SYN Cookie 会增加所有连接的延迟吗?
通常是在系统进入相关保护路径时才有额外处理;是否产生可感知影响,要结合内核版本和负载测量,不能一概而论。
看到 SyncookiesSent 增长,是否说明攻击正在发生?
不一定。突发正常流量、队列配置偏小或服务接收不及时也可能引发队列压力,应结合来源分布、ListenOverflows、应用状态和抓包判断。
调大 tcp_max_syn_backlog 就能解决问题吗?
不能保证。它针对未完成握手请求的队列空间;若瓶颈在 accept 队列、应用处理或网络带宽,仍需处理对应环节。
有效的 SYN Cookie机制应对连接队列耗尽方案,应以计数器和连接路径诊断为起点:确认队列类型,再启用并验证 Cookie,按实测调整容量,最后补齐应用或上游流量处置。