直接调大net.ipv4.tcp_max_syn_backlog不能单独扩容SYN队列,必须同步调高net.core.somaxconn并匹配应用层listen()的backlog值,三者取最小值决定实际队列上限;默认值偏低,高并发下易溢出丢包。

直接调大 net.ipv4.tcp_max_syn_backlog 不能单独扩容 SYN 队列深度,它必须和 net.core.somaxconn 同步调高,并匹配应用层 listen() 的 backlog 值,三者缺一不可。否则参数修改形同虚设,队列依然溢出丢包。
必须同步调高两个内核参数
Linux 内核取 tcp_max_syn_backlog 和 somaxconn 的较小值,作为每个监听端口的半连接队列(SYN Queue)实际容量。默认值常为 1024 和 128,高并发下几秒即满。
-
net.ipv4.tcp_max_syn_backlog:控制每个端口的 SYN 队列理论长度,建议设为 4096~65535(如每秒接收 300 个 SYN,可设为 600~1000) -
net.core.somaxconn:系统级上限,同时约束 SYN 队列与 accept 队列,必须 ≥ 前者;生产环境推荐统一设为 65535 - 临时生效命令:
sysctl -w net.ipv4.tcp_max_syn_backlog=65535sysctl -w net.core.somaxconn=65535
务必检查并调整应用层 listen backlog
即使内核参数已调大,若应用代码或配置中 listen(fd, backlog) 传入小值(如 128、511),最终队列仍被该值截断。
- Nginx:在
listen指令后显式加backlog=65535,例如listen 80 backlog=65535; - Redis:配置项
tcp-backlog 65535 - Node.js/Python/Java 服务:需确认框架启动参数(如 Gunicorn 的
--backlog、Tomcat 的acceptCount)是否暴露并设足 - 验证方式:
ss -lnt | grep :端口,观察 Recv-Q 是否长期接近你设定的目标值
验证是否真在丢弃 SYN 包
别只看 ListenOverflows(那是全连接队列溢出),要盯紧半连接丢包指标:
- 执行:
awk '/^TcpExt/ {print $1,$2}' /proc/net/snmp | grep SynsToListen
关注SynsToListenDrops是否持续增长 → 表示内核静默丢弃 SYN - 实时查看当前半连接数:
ss -n state syn-recv | wc -l
对比cat /proc/sys/net/ipv4/tcp_max_syn_backlog,若接近或达到该值,说明已到瓶颈 - 抓包辅助判断:
tcpdump -i any 'tcp[tcpflags] & tcp-syn != 0 and dst port 80'
观察是否有大量 SYN 进来但无对应 SYN+ACK 返回
配合其他策略增强防护能力
扩容队列是基础,但真实攻击场景还需叠加响应机制:
- 启用 SYN Cookies(兜底):
net.ipv4.tcp_syncookies = 1,队列满时启用无状态握手,但会限制部分 TCP 选项 - 减少重传轮次加快释放:
net.ipv4.tcp_synack_retries = 3(默认 5) - 容器环境注意透传:Docker 需用
--sysctl显式传递,如docker run --sysctl net.core.somaxconn=65535 - 永久生效推荐走
/etc/sysctl.d/99-tcp.conf+sysctl --system,避免被系统更新覆盖

















