大量SYN_RECV堆积说明服务器已发SYN-ACK但未收到ACK,连接卡在半开状态,占用syn队列;常见原因包括SYN洪水攻击、半连接队列溢出、客户端网络异常、应用accept慢或中间设备干扰。

大量 SYN_RECV 状态连接堆积,说明服务器已收到客户端 SYN 包、发送了 SYN-ACK,但迟迟未收到 ACK 完成三次握手。此时连接卡在半开状态,占用内核连接队列(尤其是 syn queue),若持续积压,会丢弃新 SYN、引发服务不可用。防火墙无显式拦截规则,并不意味着网络路径畅通——根因往往藏在更底层或外围环节。
TCP SYN 队列溢出(最常见)
Linux 内核为每个监听端口维护两个队列:
– syn queue(未完成队列):存放处于 SYN_RECV 的连接;
– accept queue(已完成队列):存放三次握手完成、等待应用调用 accept() 的连接。
当 syn queue 满(默认由 net.ipv4.tcp_max_syn_backlog 控制,通常 128~2048),内核会直接丢弃新 SYN 包(不回 RST),但部分系统会启用 tcp_syncookies=1 缓解。若未启用且突发 SYN 暴增(如扫描、攻击、客户端异常重传),就会看到大量 SYN_RECV 却无后续进展。
- 检查当前 syn queue 使用情况:
ss -lnt | grep :端口查看Recv-Q是否接近Send-Q(即 backlog 值) - 查看内核参数:
sysctl net.ipv4.tcp_max_syn_backlog net.ipv4.tcp_syncookies - 临时扩容(需匹配应用负载):
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
客户端无法返回 ACK(网络层中断)
服务器发出了 SYN-ACK,但客户端没收到,或收到了却因路由、MTU、中间设备策略等原因无法发出 ACK 回包。此时服务器一直等 ACK 超时(默认约 3 分钟),连接就挂在 SYN_RECV。
- 典型场景:客户端位于 NAT 后且 NAT 设备老化/过载,丢弃了非对称流量;或存在双向 ACL、运营商级 CGNAT 限制
- 抓包验证:在客户端侧抓包看是否收到 SYN-ACK;在服务器侧抓包(
tcpdump -i any 'port XXXX and tcp[tcpflags] & (tcp-syn|tcp-ack) != 0')确认 SYN-ACK 发出但无对应 ACK - 检查路径 MTU:若 SYN-ACK 被分片且某跳禁用 ICMP 或丢弃分片包,会导致 ACK 无法返回
服务进程 accept() 慢或阻塞
即使三次握手完成,连接进入 accept queue,若应用进程长期不调用 accept()(如单线程阻塞、GC 暂停、死锁、高 CPU 占用),accept queue 溢出后,内核可能拒绝后续握手完成的连接,间接导致更多连接滞留在 SYN_RECV(尤其开启 tcp_abort_on_overflow=0 时)。
- 用
ss -lnt观察监听端口的Recv-Q(accept queue 当前长度)是否持续非零且增长 - 检查应用日志和资源使用(CPU、线程数、GC 时间),确认是否处理能力不足
- 设置
net.ipv4.tcp_abort_on_overflow=1可让内核在 accept queue 满时发送 RST 终止握手,避免 SYN_RECV 积压(但会丢连接)
中间设备干扰(非防火墙但起类似作用)
负载均衡器(如 SLB、F5)、WAF、云平台安全组、甚至某些交换机/路由器,可能在 TCP 层做连接跟踪或限速,未明确配置“拦截”,却因会话表满、健康检查失败、源 IP 限频、SYN Flood 防御策略等静默丢弃 ACK 或重置连接。
- 排查路径中所有中间网元:查看其连接数、会话表利用率、安全策略日志
- 云环境重点查:安全组是否放行 *全部* 方向(不仅是入方向,出方向 ACK 也要能回)、SLB 的空闲超时设置是否过短(如 60s)、是否开启“TCP 监听优化”类功能
- 对比直连测试:绕过 LB/WAF 直连后是否仍复现,可快速定位干扰点










