SYN 半连接短时升高,不一定就是攻击:客户端网络不稳、服务刚启动或访问量突增,也会造成连接等待。判断时要把连接状态、队列溢出和业务表现放在一起看。本文围绕 SYN半连接耗尽攻击的识别与防护配置,给出可执行的排查顺序和调参原则。
先确认异常发生在哪一段
TCP 建连时,服务器收到 SYN 后会回复 SYN-ACK,并等待客户端最后的 ACK。等待期间,连接处于半开状态,在 Linux 上通常可从 SYN_RECV 状态观察。若最后的 ACK 长时间未到,半连接可能占用监听队列;若应用接受连接不够快,已完成握手的连接还可能堆在另一条 accept 队列。两类问题都可能表现为新连接失败,处理方法却不同。
- 在故障主机运行 ss -ant state syn-recv,查看相关监听服务是否出现大量 SYN_RECV。连续采样几次,比较趋势,不要仅凭单次结果下结论。
- 用 ss -lnt 查看监听套接字的 Recv-Q、Send-Q。对监听端口而言,Recv-Q 持续接近 Send-Q,提示已完成连接的队列可能积压;它不能单独证明半连接队列已满。
- 检查 /proc/net/netstat 中的 TcpExt 计数器,如 ListenOverflows、ListenDrops 和 SyncookiesSent。对照故障前后的增量;不同内核版本展示方式可能略有差异。
- 核对服务日志、CPU、网卡丢包和新建连接失败情况。若 SYN_RECV 激增、队列溢出计数同步上升,且业务建连失败,才更支持队列耗尽的判断。
按队列类型调整容量
半连接队列与已完成连接队列不要混为一谈
Linux 的 net.ipv4.tcp_max_syn_backlog 影响等待握手的请求容量;net.core.somaxconn 则限制应用通过 listen() 请求的已完成连接队列上限,应用自身设置的 backlog 也会影响最终值。提高一个参数,不代表另一条队列自动扩容。
- 先记录当前配置:检查 sysctl net.ipv4.tcp_max_syn_backlog、sysctl net.core.somaxconn,并确认服务实际传入的 backlog。
- 若证据指向半连接队列压力,可小幅提高 tcp_max_syn_backlog;若 Recv-Q 接近上限且应用接受速度不足,则评估 somaxconn 与应用 backlog。每次改动后重新观察计数器和延迟。
- 容量应结合内存、连接到达速率、握手等待时间及应用处理能力确定。不要照搬固定数值;扩大队列只能争取处理时间,不能修复应用卡顿或持续过量流量。
启用防护并验证效果
SYN cookies 可在队列承压时减少为半连接保留的状态,Linux 常见开关为 net.ipv4.tcp_syncookies。先用 sysctl 读取现值,再按发行版的持久化配置方式启用;确认 SyncookiesSent 是否仅在压力时增加,并检查应用握手兼容性。它是缓解手段,不会增加带宽,也不能替代队列和应用容量评估。
若流量来自大量伪造源地址,且本机防火墙或网络设备支持,可评估 SYN proxy:设备先完成握手验证,再将有效连接交给后端。它能减轻后端半连接压力,但会增加设备配置复杂度,且必须确认回程流量经过相应设备。使用 nftables 等规则限速时,应按服务正常连接模式设定阈值并先监测,过严可能误伤合法客户端。
完成调整后,在低风险时段复查 SYN_RECV、队列长度、ListenOverflows、SyncookiesSent 和应用建连成功率;同时保留回滚配置。这样才能验证 SYN半连接耗尽攻击的识别与防护配置是否解决了实际瓶颈,而不是只让计数暂时变化。
常见问题
看到 SYN_RECV 很多就能确认遭到攻击吗?
不能。还要结合持续时间、队列溢出计数、连接失败和流量来源特征判断。
只开启 SYN cookies 可以解决问题吗?
不一定。它主要缓解半连接状态压力,无法处理应用接受连接过慢、带宽不足等问题。
队列参数应设置多大?
没有适用于所有主机的固定值。依据实际连接峰值、内存、应用 backlog 和监控结果逐步调整,并在每次改动后验证。