Linux中如何通过Tcp-Abort-On-Overflow机制应对攻击引发的队列溢出问题?
- 内容介绍
- 文章标签
- 相关推荐
本文共计943个文字,预计阅读时间需要4分钟。
不能。实现 `1` 不是防御手法,而是让问题更快速、更直接暴露——它把静默默认丢弃变成明确+RST。客户端立刻收到 `Connection reset by peer`,但服务端应丢弃的连接并未丢失,而是仍保留着 `accept()` 或其他占用的资源。
真正被攻击时(比如 SYN Flood 或慢速连接耗尽全连接队列),tcp_abort_on_overflow 只决定内核怎么“善后”,不解决队列满的根本原因。
- 值为
0:客户端发完第三次握手的ACK后,服务端发现全连接队列已满,直接丢弃该ACK,客户端无响应,超时重传,可能卡在ESTABLISHED假象中 - 值为
1:同样队列满,服务端立即回一个RST,客户端秒级报错,日志里容易看到大量reset,但吞吐没提升,反而可能激化重连风暴
查全连接队列是否真被耗尽
别只看 tcp_abort_on_overflow,先确认是不是队列真溢出了。用 ss -lnt 看监听端口的 Recv-Q 和 Send-Q:
ss -lnt | grep :8080 State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 98 100 *:8080 *:*
这里 Recv-Q=98 表示已有 98 个已完成三次握手、等待 accept() 的连接;Send-Q=100 是全连接队列上限。如果 Recv-Q 长期打满(比如稳定在 100),说明应用层处理太慢或线程池堵了。
-
netstat -s | grep "listen.*overflows"查历史溢出次数,数字持续上涨就是铁证 -
ss -s输出里的tcp段会显示orphan、synrecv等计数,辅助判断是半连接还是全连接队列瓶颈
调大全连接队列比改 abort 更治本
攻击场景下,优先扩大队列容量,而非依赖 tcp_abort_on_overflow 的行为切换。关键参数有两个,取最小值生效:
- 系统级上限:
net.core.somaxconn,建议调到4096或更高(需sysctl -w net.core.somaxconn=4096) - 应用层
listen()的backlog参数:Tomcat 默认是100,Spring Boot 内置 Tomcat 可通过server.tomcat.accept-count=4096覆盖;Netty、Golang 的ListenConfig也要显式设大 - 注意:Docker 容器内需在启动时用
--sysctl net.core.somaxconn=4096透传,否则容器里读到的仍是宿主机默认值(常为 128)
为什么不能只靠 tcp_abort_on_overflow=1 应对攻击
因为它的作用域仅限于“队列已满后的单次决策”,不缓解任何资源压力:
- 它不加快
accept()速度,也不扩容队列,更不清理僵尸连接 - 设为
1后,攻击者发 1000 个合法三次握手包,服务端仍只能塞进 100 个,其余 900 个立刻被 RST —— 攻击效果几乎不变,只是失败反馈更快 - 真实防御要组合:SYN Cookie(
net.ipv4.tcp_syncookies=1)、连接速率限制(iptables -m limit)、应用层熔断(如 Sentinel 的 QPS 降级)
最常被忽略的一点:很多服务(如早期 Dubbo)硬编码 backlog=50,根本没读系统 somaxconn,这种情况下调 tcp_abort_on_overflow 完全无效。
本文共计943个文字,预计阅读时间需要4分钟。
不能。实现 `1` 不是防御手法,而是让问题更快速、更直接暴露——它把静默默认丢弃变成明确+RST。客户端立刻收到 `Connection reset by peer`,但服务端应丢弃的连接并未丢失,而是仍保留着 `accept()` 或其他占用的资源。
真正被攻击时(比如 SYN Flood 或慢速连接耗尽全连接队列),tcp_abort_on_overflow 只决定内核怎么“善后”,不解决队列满的根本原因。
- 值为
0:客户端发完第三次握手的ACK后,服务端发现全连接队列已满,直接丢弃该ACK,客户端无响应,超时重传,可能卡在ESTABLISHED假象中 - 值为
1:同样队列满,服务端立即回一个RST,客户端秒级报错,日志里容易看到大量reset,但吞吐没提升,反而可能激化重连风暴
查全连接队列是否真被耗尽
别只看 tcp_abort_on_overflow,先确认是不是队列真溢出了。用 ss -lnt 看监听端口的 Recv-Q 和 Send-Q:
ss -lnt | grep :8080 State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 98 100 *:8080 *:*
这里 Recv-Q=98 表示已有 98 个已完成三次握手、等待 accept() 的连接;Send-Q=100 是全连接队列上限。如果 Recv-Q 长期打满(比如稳定在 100),说明应用层处理太慢或线程池堵了。
-
netstat -s | grep "listen.*overflows"查历史溢出次数,数字持续上涨就是铁证 -
ss -s输出里的tcp段会显示orphan、synrecv等计数,辅助判断是半连接还是全连接队列瓶颈
调大全连接队列比改 abort 更治本
攻击场景下,优先扩大队列容量,而非依赖 tcp_abort_on_overflow 的行为切换。关键参数有两个,取最小值生效:
- 系统级上限:
net.core.somaxconn,建议调到4096或更高(需sysctl -w net.core.somaxconn=4096) - 应用层
listen()的backlog参数:Tomcat 默认是100,Spring Boot 内置 Tomcat 可通过server.tomcat.accept-count=4096覆盖;Netty、Golang 的ListenConfig也要显式设大 - 注意:Docker 容器内需在启动时用
--sysctl net.core.somaxconn=4096透传,否则容器里读到的仍是宿主机默认值(常为 128)
为什么不能只靠 tcp_abort_on_overflow=1 应对攻击
因为它的作用域仅限于“队列已满后的单次决策”,不缓解任何资源压力:
- 它不加快
accept()速度,也不扩容队列,更不清理僵尸连接 - 设为
1后,攻击者发 1000 个合法三次握手包,服务端仍只能塞进 100 个,其余 900 个立刻被 RST —— 攻击效果几乎不变,只是失败反馈更快 - 真实防御要组合:SYN Cookie(
net.ipv4.tcp_syncookies=1)、连接速率限制(iptables -m limit)、应用层熔断(如 Sentinel 的 QPS 降级)
最常被忽略的一点:很多服务(如早期 Dubbo)硬编码 backlog=50,根本没读系统 somaxconn,这种情况下调 tcp_abort_on_overflow 完全无效。

