必须同步调高somaxconn和tcp_max_syn_backlog,二者取最小值作为半连接队列实际容量,且需匹配应用层listen backlog、调整tcp_synack_retries并合理使用tcp_syncookies。

只调 tcp_max_syn_backlog 基本没用。它实际生效值是 min(tcp_max_syn_backlog, somaxconn),且在 tcp_syncookies=1 时完全不参与队列管理——防御半连接泛洪攻击,必须协同调整三个关键点:队列上限、应用层配合、连接生命周期控制。
必须同步调高 somaxconn 和 tcp_max_syn_backlog
Linux 内核取两者最小值作为半连接队列实际容量。默认值(如 128 或 1024)在攻击下几秒就满,建议统一设为:
- net.core.somaxconn = 65535(同时约束全连接队列,必须 ≥ 应用 listen() 的 backlog)
- net.ipv4.tcp_max_syn_backlog = 65535(仅当 syncookies=0 时起主作用;若启用 syncookies,它仅作备用缓冲)
改完后需重载服务(如 systemctl reload nginx),否则新值不生效。容器环境(如 Docker)还需用 --sysctl 显式透传参数。
检查并匹配应用层 listen backlog
即使内核参数调得再大,如果应用代码中写死 listen(fd, 128),内核仍会按 128 截断全连接队列,间接影响半连接处理逻辑:
- 用
ss -lnt查看目标端口的 Recv-Q 是否长期接近你设置的tcp_max_syn_backlog值 - Nginx 默认 backlog 是 511,可通过
listen 80 backlog=65535调整;Tomcat 可在server.xml中配acceptCount - Java 应用若用 Netty,需显式设置
ChannelOption.SO_BACKLOG
缩短半连接存活时间,加速资源释放
默认 tcp_synack_retries=5 意味着最长等待约 31 秒,攻击者伪造 IP 不回 ACK,白白占位。推荐:
- net.ipv4.tcp_synack_retries = 2 → 最长等待约 1.5 秒
- net.ipv4.tcp_syn_retries = 3(客户端侧,辅助识别攻击强度)
- 注意不要设为 0,否则首次 SYN+ACK 丢失即断连,对真实弱网用户不友好
合理使用 tcp_syncookies
SYN Cookie 是兜底机制,不是替代调优的方案:
- 开启后(
net.ipv4.tcp_syncookies = 1),内核绕过半连接队列,用加密序列号隐式建链 - 代价是丢失 TCP 扩展选项(如时间戳、SACK),且握手开销略高
- 生产环境若已调高队列且
SynsToListenDrops为零,可关闭以获得标准 TCP 行为 - 云环境需实测——某些安全组或网络设备会干扰 SYN Cookie 流程,导致握手超时
验证是否真在丢半连接:运行 awk '/^TcpExt/ {print $1,$2}' /proc/net/snmp | grep SynsToListenDrops,持续观察该值是否上升;配合 tcpdump -i any 'tcp[tcpflags] & tcp-syn != 0 and dst port 端口' 看是否有大量 SYN 进来但无响应。











