SYN Flood攻击通过耗尽半连接队列,使服务器无法响应正常连接请求,导致服务不可用的直接原因是内核backlog队列溢出,三次握手无法完成。 攻击者发送大量伪造源IP的SYN包,服务器内核协议栈将每个SYN放入半连接队列并回复SYN-ACK,由于源IP不存在或不可达,服务器永远收不到ACK,半连接队列中的条目持续累积直至满载,一旦队列满,内核会丢弃后续所有SYN包,包括合法用户的连接请求,造成服务中断,据行业共识,这种情况在DDoS攻击中相当常见,尤其针对TCP服务,与UDP Flood不同,SYN Flood利用的是协议本身的漏洞,即使服务器带宽充足,也可能被数百兆的小流量打垮。
半连接队列被占满的成因与机制
什么是SYN Flood和半连接队列
TCP三次握手是建立可靠连接的基础,客户端发送SYN,服务器回复SYN-ACK,客户端回复ACK后连接建立,服务器在收到SYN后,会创建一个半连接条目放入SYN Queue(半连接队列),等待ACK,如果ACK迟迟不到,该条目会超时重传SYN-ACK,最终超时移除,半连接队列的大小由内核参数tcp_max_syn_backlog决定,默认值通常为128到1024不等,视系统内存而定。
SYN Flood攻击正是利用这一点:攻击者发送大量SYN包,但源IP地址是伪造的或不存在的,服务器回复的SYN-ACK永远无法得到ACK,导致半连接队列迅速被这些伪造的条目填满,在DDoS攻击中的SYN Flood是什么?它是最古老的DDoS攻击方式之一,但至今仍广泛使用,因为攻击成本低,且对未防护的服务杀伤力极大。
服务器被SYN Flood攻击的表现
当半连接队列被占满,服务会表现出以下典型症状:
- 端口可达性下降:使用telnet或curl尝试连接服务器端口时,长时间无响应或直接超时。
- 正常连接失败:用户无法访问网站或应用,浏览器显示连接超时。
- 系统资源异常:CPU占用率可能不高,但
netstat -s显示大量SYN_RECV状态的连接,丢包率明显上升。 - 网络带宽正常:攻击流量通常不大,因为SYN包很小,但效果显著,与传统带宽耗尽型DDoS不同。

这些表现可以帮助运维人员快速定位问题,业内专家指出,在服务器性能未明显下降但端口无法连接时,应优先检查半连接队列状态,具体操作:使用ss -lnt查看当前监听端口的队列信息,Recv-Q和Send-Q持续增长,可能表示队列溢出,配合netstat -ant | grep SYN_RECV | wc -l统计半连接数,如果数值持续超过tcp_max_syn_backlog的一半,说明攻击风险高。
半连接队列占满导致服务不可用的深层原因
很多人以为半连接队列满后,服务器只会拒绝新连接,但实际影响不止于此,当队列满时,内核会进入过载状态,即便后续有合法的SYN包也会被直接丢弃,而且如果SYN Cookie未开启,后续的ACK包也无法建立连接,已建立的连接可能因为内核忙于处理超时而受影响,在队列满的情况下,服务器响应时间可能增加数倍,但主要表现还是连接超时,全连接队列(Accept Queue)此时也可能被间接影响,因为半连接队列的溢出会导致全连接队列无法正常接收已完成握手的连接,进一步加剧服务不可用。
SYN Flood攻击防护方法
启用SYN Cookie
SYN Cookie是一种内核级防御机制,当半连接队列接近满载时,内核会启用SYN Cookie,用加密方式将连接信息编码在SYN-ACK的序列号中,从而不占用队列空间,在Linux系统中,可以通过echo 1 > /proc/sys/net/ipv4/tcp_syncookies启用,或写入/etc/sysctl.conf永久生效,多数现代Linux发行版默认开启,但在某些自定义环境中可能关闭,开启后,即使半连接队列被大量伪造SYN淹没,内核仍能通过Cookie验证合法客户端的ACK,维持连接建立能力。
调整内核参数
除了SYN Cookie,还可以调整以下参数,下表对比了常见参数的作用与适用场景:

| 参数 | 作用 | 适用场景 |
|---|---|---|
tcp_max_syn_backlog |
增大半连接队列容量 | 短期流量突增,但非持续攻击 |
tcp_syn_retries |
减少SYN-ACK重试次数,加快条目释放 | 受攻击时快速清理无效条目 |
tcp_abort_on_overflow |
全连接队列满时直接拒绝连接 | 防止全连接队列溢出影响半连接队列 |
这些参数需要根据实际硬件和业务场景调整,不宜盲目增大,将tcp_max_syn_backlog从1024增加到2048,可以短期内承受更多半连接,但如果攻击流量持续,队列仍会满,此时应优先启用SYN Cookie。
半连接队列占满怎么解决
当半连接队列已经占满,服务不可用时,可采取以下紧急措施:
- 检查当前半连接队列大小:使用
ss -lnt或netstat -s查看SYN_RECV状态连接数,对比/proc/sys/net/ipv4/tcp_max_syn_backlog的值。 - 临时启用SYN Cookie:
sysctl -w net.ipv4.tcp_syncookies=1,无需重启服务。 - 限制SYN包速率:使用iptables或云防火墙,对来源IP进行限流,例如
iptables -A INPUT -p tcp --syn -m limit --limit 100/s -j ACCEPT。 - 使用DDoS防护服务:如Cloudflare、简米云高防IP等,这些服务在入口处清洗SYN Flood流量。
多数情况下,这些操作能在几分钟内恢复服务,但根本防护需要结合网络架构和持续监控,如果攻击流量极大,可能需要临时切换IP或黑洞路由,但这属于熔断策略。
Linux半连接队列大小设置
Linux半连接队列大小由net.ipv4.tcp_max_syn_backlog直接控制,但实际生效值还受net.core.somaxconn影响,对于业务高峰期,建议将tcp_max_syn_backlog设置为1024或更高,同时确保net.core.somaxconn至少与之相等,设置方法:

- 临时:
sysctl -w net.ipv4.tcp_max_syn_backlog=2048 - 永久:在
/etc/sysctl.conf中添加net.ipv4.tcp_max_syn_backlog = 2048,执行sysctl -p生效。
注意,如果启用SYN Cookie,tcp_max_syn_backlog参数在某些内核版本中将被忽略,因为SYN Cookie模式下不依赖队列大小,如果你开启了SYN Cookie,调整队列大小可能没有效果,主要依靠Cookie机制。net.core.somaxconn定义了Listening Socket的backlog上限,同样影响半连接队列,对于高并发Web服务,建议将net.core.somaxconn设置为1024或2048,同时修改应用层的backlog参数(如Nginx的listen指令中的backlog值)。
Q&A:SYN Flood半连接队列相关问题
为什么半连接队列占满后服务立刻不可用,而不是缓慢变慢?
因为半连接队列是内核处理新连接请求的必经之路,一旦队列满,内核会立即丢弃所有新SYN包,导致服务从外部看瞬间断连,这与CPU过载或带宽耗尽时的渐进式降级不同,队列溢出是硬性限制。
SYN Cookie有什么缺点,是否适合所有场景?
SYN Cookie会消耗额外CPU资源用于加密计算,且会禁用TCP时间戳、窗口缩放等选项,可能影响大流量下的性能,但在半连接队列面临攻击时,利大于弊,对于高并发正常业务,若不开启SYN Cookie,应确保队列足够大,避免误触发。
如何区分正常业务波动和SYN Flood攻击?
正常业务波动时,半连接队列偶尔增长但不会长时间居高不下,且源IP分散,攻击时,SYN_RECV状态连接数快速上升,源IP随机且大量不可达,同时全连接队列可能正常,使用netstat -s | grep -i "SYN"查看统计信息,如果SYN_ACK重传数量异常高,基本可以确认攻击。
理解SYN Flood攻击的核心原理,就能明白半连接队列的脆弱性,防御的关键在于及时检测和综合防护,而非单一参数调整,合理规划队列大小并启用SYN Cookie,是保障服务稳健的基础。