syn flood攻击绕过worker_connections限制,因该参数仅控制已建立的established连接数,而syn flood通过海量伪造syn包填满内核半连接队列(tcp_max_syn_backlog)和全连接队列(somaxconn),导致合法连接无法完成三次握手,nginx worker进程根本收不到新连接请求。

当Nginx在高并发场景下突然出现大量连接超时、502/504错误,或netstat -an | grep :80 | wc -l显示 ESTABLISHED 连接数远低于 worker_connections 配置值,但请求却持续失败——这往往不是连接池耗尽,而是 SYN Flood 攻击正在绕过连接建立阶段,直接冲击内核 TCP 协议栈与 Nginx 的 accept 队列,造成“连接数未满,服务已瘫”的假象。
SYN Flood 如何绕过 worker_connections 限制?
worker_connections 控制的是每个 worker 进程**已成功完成三次握手、进入 ESTABLISHED 状态**的连接上限。而 SYN Flood 发送海量伪造源 IP 的 SYN 包,导致:
- 内核半连接队列(
net.ipv4.tcp_max_syn_backlog)迅速填满,新合法 SYN 被丢弃 - 全连接队列(
net.core.somaxconn)无法被 accept() 及时消费,积压后触发内核丢包 - Nginx worker 进程根本拿不到新连接,
worker_connections始终“空闲”,但用户请求无法抵达
关键指标排查顺序(不看 nginx 日志,先查系统层)
执行以下命令快速定位瓶颈环节:
-
检查半连接堆积:
netstat -s | grep -i "syn"—— 若 “SYNs to LISTEN sockets dropped” 持续增长,说明tcp_max_syn_backlog不足或遭受攻击 -
检查全连接队列溢出:
ss -lnt查看 Recv-Q 列是否长期 > 0(尤其接近somaxconn值),表示 accept() 处理不过来 -
确认 Nginx 实际监听队列长度:
ss -lntp | grep :80中的sk_wmem_queued和sk_rmem_alloc可辅助判断内核套接字缓冲区压力 -
观察 TIME_WAIT 是否异常激增:
netstat -an | grep TIME_WAIT | wc -l—— 若远超正常并发量,可能是攻击者快速断连制造的假连接
防御与调优:从内核到 Nginx 的协同配置
单纯调大 worker_connections 无效,必须分层加固:
-
启用 SYN Cookie(临时缓解):
echo 1 > /proc/sys/net/ipv4/tcp_syncookies,让内核在半连接队列满时用加密 cookie 应答 SYN+ACK,避免丢包(注意:仅适用于无状态攻击,对源 IP 真实的慢速攻击效果有限) -
增大内核队列容量:
sysctl -w net.core.somaxconn=65535,sysctl -w net.ipv4.tcp_max_syn_backlog=65535,并写入/etc/sysctl.conf -
优化 Nginx accept 行为:在
events块中启用use epoll;(Linux)、multi_accept on;(让单次事件循环尽可能 accept 多个连接)、accept_mutex off;(高并发下减少锁竞争,需配合epoll) - 前置防护不可少:在负载均衡器或云防火墙侧开启 SYN Flood 防护策略(如限速、指纹识别、源验证),把攻击拦截在到达 Nginx 之前
验证是否真为 SYN Flood:一个简易复现与对比方法
用 hping3 模拟攻击(仅测试环境):
- 正常压测(完成握手):
hping3 -c 1000 -d 100 -S -w 64 -p 80 --flood --rand-source <your_ip></your_ip>→ 观察 ESTABLISHED 连接增长及 Nginx 错误日志 - 纯 SYN 洪水(不完成握手):
hping3 -c 10000 -d 100 -S -w 64 -p 80 --flood --rand-source <your_ip></your_ip>→ 此时ss -lntRecv-Q 快速堆积,netstat -s显示 SYN drop 上升,但worker_connections使用率几乎为 0
两种模式下的现象差异,就是区分真实连接耗尽与 SYN Flood 击穿的关键证据。











