引言
SYN Cookie 最初被提出是为了解决 SYN Flood 攻击。在高并发网络扫描中,如何区分属于扫描器的 TCP 包和正常流量是一个重要问题。扫描器(如 Masscan、ZMap)借鉴了 Syncookies 的原理,用于在 不维护大量连接状态的情况下验证响应,从而提升扫描效率和可靠性。本文将结合 Masscan 的实现,讲解 Syncookies 技术在扫描中的应用。
SYN Flood 攻击与 SYN Cookie
在正常的 TCP 三次握手中:
- 客户端发送
SYN - 服务器回复
SYN-ACK,并在内存中分配连接资源 - 客户端回复
ACK,握手完成
如果攻击者伪造大量源 IP 发送 SYN 报文,而不回复最终的 ACK,服务器的 半连接队列(SYN_RECV 状态)就会被耗尽,导致合法用户无法建立连接。这就是 SYN Flood 攻击。
在 Linux 中,可以通过以下命令查看当前处于半连接队列的连接数:
netstat -an | grep :80 | grep SYN_RECV | wc -l
半连接队列大小由 net.ipv4.tcp_max_syn_backlog 控制。
SYN Cookie 的机制 SYN Cookie 的核心思想是:在收到 SYN 报文时不立即分配资源,而是通过算法生成可验证的序列号 (ISN)。
- 收到 SYN
-
不占用半连接队列
-
生成 ISN:
ISN = f(srcIP, srcPort, dstIP, dstPort, secret, timestamp) -
f() 通常是加密哈希函数(如 SipHash)secret 与
-
timestamp 防止伪造
- 回复 SYN-ACK
- 报文序列号设置为 ISN
- 收到 ACK
- 客户端返回的 ack = ISN + 1
- 服务器重新计算 ISN 并验证
- 匹配 → 建立连接
- 不匹配 → 丢弃
这样,服务器就能在 无状态 的情况下抵御大规模 SYN Flood 攻击。
Linux 内核中的 SYN Cookie
Linux 自 2.1.x/2.2.x 起支持 SYN Cookie。 启用方式:
sysctl -w net.ipv4.tcp_syncookies=1
0 → 关闭, 1 → 开启
当半连接队列满时,内核会启动 SYN Cookie 机制,用序列号验证连接合法性。缺点是无法支持部分 TCP 选项(如窗口缩放、时间戳),在高负载下可能导致误判。
Masscan 中的 Syncookies 应用
Masscan 在扫描中 不依赖内核维护连接状态,而是使用 原始套接字(raw socket)或 libpcap 捕获所有 TCP 包。这样做的优势:
- 高效捕获:直接获取经过网卡的 TCP 包
- 灵活处理:可按需解析序列号、确认号等字段
但是带来的问题:如何区分属于 Masscan 的扫描流量和其他程序(如浏览器)的正常流量?
解决方案:借鉴 Syncookies 的思想。
Masscan 的实现思路 Masscan 为每个扫描请求分配一个 唯一序列号 (Seq),并通过 SipHash 算法生成。
输入字段:srcIP, dstIP, srcPort, dstPort
输出值:取低 32 位作为序列号
由于 TCP 协议允许客户端 SYN 报文的序列号为任意值,Masscan 就能利用这一点实现无状态验证。
工作流程 发送阶段:
- hash = SipHash(srcIP, dstIP, srcPort, dstPort)
- seq = hash & 0xffffffff
- 发送 SYN 包,Seq = seq
接收阶段:
- 捕获 TCP 包(raw socket 或 libpcap)
- 重新计算 hash = SipHash(srcIP, dstIP, srcPort, dstPort)
- 判断:
- 若 (hash & 0xffffffff) == TCP包中的 Seq → 属于 Masscan 扫描流量
- 否则 → 属于其他程序流量,丢弃
技术优势 唯一性:同一对 IP/端口在一次扫描中序列号固定,避免混淆
不可预测性:SipHash 难以被攻击者伪造
无状态验证:无需维护大规模连接表,仅需一次哈希运算即可验证
总结
SYN Cookie 技术最初是为防御 SYN Flood 而提出,但它的核心思想: 利用可验证的序列号实现无状态验证, 被 Masscan 借鉴并应用到高性能端口扫描中。这种方法使得扫描器能够在 极高并发 下仍然保持高效、可靠,同时避免误判外部流量。 可以说,SYN Cookie 已经从防御机制演变为网络安全工具中重要的性能优化手段。