队列被打满时的兜底机制
正常握手时内核为每个 SYN 在半连接队列里建一条记录,等第三次握手完成再移入全连接队列。伪造源地址的 SYN 洪水会把这条队列占满,导致真实用户连不上。syncookies 的做法是把连接信息编码进初始序列号,服务器不再为未完成的连接保留状态,从源头上消除了队列被撑满的可能。
基本信息
| 适用平台 | Linux 内核参数 net.ipv4.tcp_syncookies |
|---|---|
| 取值 | 0 关闭、1 在队列溢出时启用、2 无条件启用 |
| 推荐设置 | 保持 1,仅在极端环境用 2 |
| 代价 | 启用期间部分 TCP 选项(如窗口缩放)未必能完整协商 |
| 相关参数 | tcp_max_syn_backlog、tcp_synack_retries、somaxconn |
路径与兜底
| 环节 | 行为 | 观察点 |
|---|---|---|
| 正常路径 | SYN 队列与 Accept 队列两级排队 | ss -lnt 的 Recv-Q 与 Send-Q |
| syncookies | 队列满时改用无状态应答 | TcpExtSyncookiesSent 增长 |
| 溢出统计 | 记录被丢弃的 SYN | TcpExtListenDrops 增长 |
| 升级方案 | 上游清洗加限速加缩短半连接超时 | 攻击流量特征明显时优先用清洗 |
观测与配置
观测与配置
sysctl net.ipv4.tcp_syncookies # 1=队列满时启用(推荐)
ss -tan state syn-recv | wc -l # 当前半连接数量
cat /proc/net/netstat | grep -o 'TcpExtSyncookies[A-Za-z]*' # 确认存在这些计数
netstat -s | grep -i -E 'SYNs to LISTEN|cookies' # 溢出与 cookie 概况
sysctl -w net.ipv4.tcp_syncookies=1 net.ipv4.tcp_max_syn_backlog=65535典型使用场景
- 对外暴露的服务在遭受 SYN 洪水时保持可用
- 排查「大量连接卡在 SYN 收到」:区分是真攻击还是后端 accept 太慢
- 安全加固基线:把 syncookies 与队列参数一起纳入检查项
- 容量评估时对比开启前后的握手成功率与延迟
开启 syncookies 后部分 TCP 选项协商可能受限:正常流量若能完整连通就没有问题,若发现窗口缩放异常再回头检查该参数与中间设备的兼容性。
syncookies 是兜底而不是护城河:它能避免服务器因队列耗尽而拒绝所有新连接,但带宽与吞吐仍会被攻击流量占用,大流量攻击必须在上游做清洗。
对比攻击前后的计数:cookie 发送量与监听队列丢弃数同时抬升说明队列确实被撑满;若只有 cookie 增长而丢弃数没动,应先优化队列参数再看攻击面。