启用SYN Cookie后,服务器收到TCP SYN报文时不再为每个连接分配半连接队列条目,而是用源/目的IP、端口、时间等参数计算一个Cookie塞进SYN-ACK的序列号;只有收到合法ACK后,才分配全连接资源。 这就是跳过半连接存储的本质,在Linux上把net.ipv4.tcp_syncookies设为1或2即可启用,但两种模式跳过存储的时机不同。
SYN Cookie跳过半连接存储的核心机制
传统半连接队列到底存了什么
TCP三次握手不是“收到SYN就直接建好连接”,服务器先回SYN-ACK,再等客户端ACK,中间这段时间,连接处于SYN_RECV状态,传统内核会为每个SYN创建一个request_sock结构,挂到半连接队列里。
这个队列里通常保存:
- 源IP、源端口、目的IP、目的端口
- 客户端初始序列号、服务器初始序列号
- SYN重传定时器
- MSS、窗口缩放、SACK等TCP选项协商信息
- 连接状态和引用计数
半连接队列长度受net.ipv4.tcp_max_syn_backlog限制,当SYN Flood把队列打满,新来的合法SYN也可能被丢弃,近年来,云上业务遭遇SYN Flood的案例并不少见,据统计,多数中小站点在未开启SYN Cookie时,半连接队列被打满后会直接表现为新连接超时。
SYN Cookie如何把状态编码进序列号
SYN Cookie的思路很直接:不存状态,改存“数学指纹”,服务器收到SYN后,用哈希函数把源IP、目的IP、源端口、目的端口、服务器密钥、时间计数器等参数算成一个Cookie,放进SYN-ACK的序列号字段。
RFC 4987对SYN Cookie机制有明确定义,Linux内核文档也说明,tcp_syncookies=1表示半连接队列满时启用Cookie,tcp_syncookies=2表示无条件使用Cookie。
具体流程可以拆成几步:
- 收到SYN,检查半连接队列,模式1下队列未满仍分配
request_sock;模式2下直接计算Cookie。 - 计算Cookie,把它作为SYN-ACK的初始序列号发回去。
- 不分配
request_sock,不挂半连接队列。 - 收到客户端ACK后,用ACK中的确认序列号减1,结合四元组和时间槽重新计算并校验Cookie。
- 校验通过才创建全连接,进入ESTABLISHED;校验失败直接丢弃。
这意味着,攻击者伪造大量SYN时,服务器只是做哈希计算和发包,内存里不会堆积半连接条目。用计算换存储,是SYN Cookie最核心的取舍。
三次握手流程对比:开启前后差异
| 对比项 | 未启用SYN Cookie | tcp_syncookies=1 |
tcp_syncookies=2 |
|---|---|---|---|
| 半连接队列条目 | 每个SYN分配request_sock |
队列满后才不分配 | 基本不分配 |
| 内存占用 | 随SYN数量增长 | 队列满后保持稳定 | 基本恒定 |
| SYN Flood影响 | 队列满丢新SYN | 队列满转Cookie | 直接走Cookie |
| 序列号用途 | 随机ISN | 队列满时编码Cookie | 编码Cookie |
| 收到ACK后 | 查半连接队列 | 查队列或校验Cookie | 校验Cookie |
| TCP选项协商 | 完整 | 队列未满时完整 | 可能不完整 |
表格里最关键的一行是半连接队列条目,模式2下,服务器对新建连接基本跳过半连接存储;模式1下,队列仍参与,只是满了以后用Cookie兜底。
高并发网站SYN Cookie配置实操步骤
检查当前内核参数与队列状态
先别急着改参数,登录服务器,把当前状态看清楚,常用命令:
sysctl net.ipv4.tcp_syncookies:查看SYN Cookie模式,0关闭,1队列满启用,2无条件启用。sysctl net.ipv4.tcp_max_syn_backlog:查看半连接队列上限。sysctl net.core.somaxconn:查看listen backlog上限。ss -lnt:看监听端口的Send-Q,判断backlog是否被应用层限制。nstat -az | grep -i syncookie:查看SyncookiesSent、SyncookiesRecv等计数器。cat /proc/net/netstat | grep -i syncookie:另一种查看Cookie统计的方式。
如果SyncookiesSent持续增长,说明服务器已经在发Cookie,此时要判断是攻击流量导致,还是队列设置过小导致正常业务过早进入Cookie模式。
Linux服务器开启SYN Cookie后半连接队列还需要调大吗
这是很多人配置时容易绕进去的问题,答案要分模式看。
tcp_syncookies=1时,半连接队列仍然是“触发器”,队列没满,正常握手走完整队列;队列满了,才发Cookie,此时tcp_max_syn_backlog不能设得太小,否则正常SYN峰值一来就过早切到Cookie模式,TCP选项协商可能不完整,长肥管道吞吐受影响。
tcp_syncookies=2时,服务器基本无条件跳过半连接存储。tcp_max_syn_backlog对新建连接的作用弱化,但仍建议保留合理值,便于监控、兼容内核其他路径,也避免极端情况下参数过小带来副作用。
业内专家指出,SYN Cookie是SYN Flood防御手段,不是队列调优的替代品,实操上可以这样写配置:
# 常规Web服务器:队列满时启用Cookie net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 net.core.somaxconn = 1024 # 极端攻击场景或短连接服务:可评估无条件Cookie # net.ipv4.tcp_syncookies = 2
写入/etc/sysctl.conf后执行sysctl -p生效,队列值按业务SYN峰值估算,常见范围在1024到8192之间,不要照搬。
验证SYN Cookie是否生效
改完参数要做验证,不要只看配置文件。
- 用
nstat -az | grep -i syncookie观察SyncookiesSent是否增长。 - 用
ss -s看SYN-RECV数量是否在攻击或压测下保持稳定。 - 用
netstat -s | grep -i "SYNs to LISTEN"看是否有大量SYN被丢弃。 - 在隔离测试环境用合法压测工具制造SYN排队,观察半连接队列是否不再膨胀。
- 抓包看SYN-ACK序列号是否呈现Cookie特征,但不要在生产环境长时间抓包。
验证时重点关注:半连接队列条目是否停止增长,Cookie校验是否正常放行合法ACK,如果合法用户大量失败,优先检查时间同步、四元组变化和中间NAT设备。
DDoS攻击下SYN Cookie防御效果怎么样
云服务器与物理机配置差异
物理机上SYN直接打到内核,tcp_syncookies配置相对直接,云服务器要多看一层:安全组、SLB、NAT网关可能先处理SYN,如果负载均衡层已经代理了三次握手,后端服务器看到的不是原始SYN,SYN Cookie的作用点会变化。
云服务器SYN Cookie功能是否额外收费?多数云厂商的SYN Cookie属于操作系统内核能力,不单独收费;高防IP、DDoS清洗、带宽扩容才按防护能力或带宽计费,选购时要问清楚清洗层是否透传SYN,以及后端是否还需要开Cookie。
北京地区高防服务器SYN Cookie配置价格
北京地区高防服务器SYN Cookie配置价格通常不是单独报价项,SYN Cookie是系统层功能,配置本身不产生额外授权费,价格差异主要来自清洗带宽、防护峰值、线路质量和机房资源,行业共识认为,把SYN Cookie当成高防套餐的“赠品”更合理,真正要比较的是清洗能力和误杀控制。
如果业务以短连接Web服务为主,tcp_syncookies=2加高防清洗可以扛住较大SYN压力;如果业务依赖大窗口、长距离传输,tcp_syncookies=1配合合理半连接队列更稳妥,避免Cookie模式牺牲TCP选项协商。
Q&A:SYN Cookie与半连接存储常见疑问
Q1:启用SYN Cookie后,半连接队列长度设为0可以吗?
不建议。tcp_syncookies=1时,半连接队列仍用于判断何时进入Cookie模式,设为0或极小会让所有SYN都走Cookie路径,丢失部分TCP选项协商。tcp_syncookies=2可无条件跳过半连接存储,但tcp_max_syn_backlog仍应保留合理值,便于监控和兼容内核其他路径。
Q2:SYN Cookie和tcp_max_syn_backlog是什么关系?
前者是用计算换存储的防御机制,后者是半连接队列容量。tcp_syncookies=1时,队列是“触发器”;tcp_syncookies=2时,队列基本不参与新建连接,但参数仍存在,高并发网站可先按SYN峰值调大队列,再开Cookie作为兜底。
Q3:SYN Cookie开启后会影响正常用户连接吗?
多数情况下影响有限,代价是TCP选项协商可能不完整,比如窗口缩放、SACK等,在长距离高带宽链路可能降低吞吐,对普通Web短连接影响较小;若业务依赖大窗口传输,tcp_syncookies=1比tcp_syncookies=2更稳妥。
SYN Cookie用“算力换存储”的思路,把半连接状态从内存队列挪到序列号里,真正要完全跳过半连接存储,Linux下应使用tcp_syncookies=2;常规防御用tcp_syncookies=1并配合合理队列长度,兼顾兼容性和抗SYN Flood能力。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/786859.html


