引言

SYN Cookie 最初被提出是为了解决 SYN Flood 攻击。在高并发网络扫描中,如何区分属于扫描器的 TCP 包和正常流量是一个重要问题。扫描器(如 MasscanZMap)借鉴了 Syncookies 的原理,用于在 不维护大量连接状态的情况下验证响应,从而提升扫描效率和可靠性。本文将结合 Masscan 的实现,讲解 Syncookies 技术在扫描中的应用。


在正常的 TCP 三次握手中:

  1. 客户端发送 SYN
  2. 服务器回复 SYN-ACK,并在内存中分配连接资源
  3. 客户端回复 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)。

  1. 收到 SYN
  • 不占用半连接队列

  • 生成 ISN:

    ISN = f(srcIP, srcPort, dstIP, dstPort, secret, timestamp)
    
  • f() 通常是加密哈希函数(如 SipHash)secret 与

  • timestamp 防止伪造

  1. 回复 SYN-ACK
  • 报文序列号设置为 ISN
  1. 收到 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 包。这样做的优势:

  1. 高效捕获:直接获取经过网卡的 TCP 包
  2. 灵活处理:可按需解析序列号、确认号等字段

但是带来的问题:如何区分属于 Masscan 的扫描流量和其他程序(如浏览器)的正常流量?

解决方案:借鉴 Syncookies 的思想。

Masscan 的实现思路 Masscan 为每个扫描请求分配一个 唯一序列号 (Seq),并通过 SipHash 算法生成。

输入字段:srcIP, dstIP, srcPort, dstPort

输出值:取低 32 位作为序列号

由于 TCP 协议允许客户端 SYN 报文的序列号为任意值,Masscan 就能利用这一点实现无状态验证。

工作流程 发送阶段:

  1. hash = SipHash(srcIP, dstIP, srcPort, dstPort)
  2. seq = hash & 0xffffffff
  3. 发送 SYN 包,Seq = seq

接收阶段:

  1. 捕获 TCP 包(raw socket 或 libpcap)
  2. 重新计算 hash = SipHash(srcIP, dstIP, srcPort, dstPort)
  3. 判断:
    • 若 (hash & 0xffffffff) == TCP包中的 Seq → 属于 Masscan 扫描流量
    • 否则 → 属于其他程序流量,丢弃
flowchart TD A[开始扫描] --> B["计算 SipHash(srcIP, dstIP, srcPort, dstPort)"] B --> C["取低32位作为序列号 Seq"] C --> D["发送 SYN 包,Seq=hash结果"] D --> E["捕获 TCP 包(raw socket/libpcap)"] E --> F["重新计算 SipHash(srcIP, dstIP, srcPort, dstPort)"] F --> G["取低32位作为验证值"] G --> H{"验证: Seq 是否匹配?"} H -->|是| I["属于 Masscan 流量 → 继续处理"] H -->|否| J["属于其他流量 → 丢弃"]

技术优势 唯一性:同一对 IP/端口在一次扫描中序列号固定,避免混淆

不可预测性:SipHash 难以被攻击者伪造

无状态验证:无需维护大规模连接表,仅需一次哈希运算即可验证


总结

SYN Cookie 技术最初是为防御 SYN Flood 而提出,但它的核心思想: 利用可验证的序列号实现无状态验证, 被 Masscan 借鉴并应用到高性能端口扫描中。这种方法使得扫描器能够在 极高并发 下仍然保持高效、可靠,同时避免误判外部流量。 可以说,SYN Cookie 已经从防御机制演变为网络安全工具中重要的性能优化手段。