SYN Cookie

mark

SYN 泛洪攻击

SYN 攻击其实就是 Server 收到 Client 的 SYN,Server 向 Client 发送 SYN-ACK 之后未收到 Client 的 ACK 确认报文, 这样服务器就需要维护海量的半开连接 ,等待客户端的 ACK, 最终导致服务器资源耗尽 (sync queue 满) 而丢弃新的连接。 Server 会不断重发 SYN-ACK,Linux 服务器默认直到 63 秒才断开连接!

其中一种防护方式是 SYN Cookie, SYN Cookies 的应用允许服务器当 SYN 队列被填满时避免丢弃连接。相反,服务器会表现得像 SYN 队列扩大了一样。服务器会返回适当的 SYN+ACK 响应,但会丢弃 SYN 队列条目。如果服务器接收到客户端随后的 ACK 响应,服务器能够使用编码在 TCP 序号内的信息重构 SYN 队列条目。

Linux 内核实现

服务器会构造一个 sequence number,根据 TCP 规范,由端点发送的第一个序号可以是由该端点决定的任何值。SYN Cookies 是根据以下规则构造的初始序号:

  • 令 t 为一个缓慢递增的时间戳(通常为 time () >> 6,提供 64 秒的分辨率);
  • 令 m 为服务器会在 SYN 队列条目中存储的最大分段大小(maximum segment size,简称为 MSS);
  • 令 s 为一个加密散列函数对服务器和客户端各自的 IP 地址和端口号以及 t 进行运算的结果。返回得到的数值 s 必须是一个 24 位值,取低 24 位

为了达到最佳的传输效能,TCP 协议在建立连接的时候通常要协商双方的 MSS 值,这个值 TCP 协议在实现的时候往往用 MTU 值代替(需要减去 IP 数据包包头的大小 20Bytes 和 TCP 数据段的包头 20Bytes)所以一般 MSS 值 1460

则初始序列号 n 为:

  • 5 位为 t mod 32(mod 是一种同余运算)
  • 接下来 3 位为 m 的编码值
  • 24 位为 s

下面是具体过程,主要是低 24 位 s 得计算过程,服务器收到一个 SYN 包,计算一个消息摘要 mac。

mac = MAC (A, k);

MAC 是密码学中的一个消息认证码函数,也就是满足某种安全性质的带密钥的 hash 函数,它能够提供 cookie 计算中需要的安全性。在 Linux 实现中,MAC 函数为 SHA1

1
A = SOURCE_IP || SOURCE_PORT || DST_IP || DST_PORT || t || MSSIND

k 为服务器独有的密钥,实际上是一组随机数。t 为系统启动时间,每 60 秒加 1。MSSIND 为 MSS 对应的索引。

其实就是根据源 IP、源端口、目的 IP、目的端口、系统启动时间,MSS 索引通过哈希函数计算出的一个值

SYN Cookie 在 Linux 内核中的实现

如果 SYN Cookie 功能有编译进内核 (CONFIG_SYN_COOKIE),且选项 tcp_syncookies 不为 0,那么可使用 SYN Cookie。同时设置 SYN Flood 标志 (listen_opt->synflood_warned)

mark

mark

SHA1 安全哈希算法 (Secure HASH Algorithm) 主要适用于数字签名。

对于长度小于 2^64 位的消息,SHA1 会产生一个 160 位的消息摘要。当接收到消息的时候,这个消息摘要可以用来
验证数据的完整性。在传输的过程中,数据可能会发生变化,那么这时候就会产生不同的消息摘要。
SHA1 有如下特性:

  • 不可以从消息摘要中复原信息。

  • 两个不同的消息不会产生同样的消息摘要。

当客户端收到此 SYN+ACK 报文后,根据 TCP 标准,它会回复 ACK 报文,且报文中 ack = n + 1,那么在服务器收到它时,将 ack - 1 就可以拿回当初发送的 SYN+ACK 报文中的序号了!服务器巧妙地通过这种方式间接保存了一部分 SYN 报文的信息。 看到这里在回顾一个这个序列号的组成

  • 5 位为 t mod 32(mod 是一种同余运算)
  • 接下来 3 位为 m 的编码值
  • 24 位为 s

接下来,服务器需要对 ack - 1 这个序号进行检查:

  • 将高 5 位表示的 t 与当前之间比较,看其到达地时间是否能接受。
  • 根据 t 和连接元组重新计算 s,看是否和低 24 一致,若不一致,说明这个报文是被伪造的。
  • 解码序号中隐藏的 mss 信息

如果成功匹配, 服务器就会为新的连接创建和初始化一个传输控制块,然后把完成三次握手的 req 和新 sock 关联起来,下面看看验证这段逻辑的代码

mark

SYN Cookie 技术可以让服务器在收到客户端的 SYN 报文时,不分配资源保存客户端信息,而是将这些信息保存在 SYN+ACK 的初始序号和时间戳中。对正常的连接,这些信息会随着 ACK 报文被带回来。

由于 cookie 的计算只涉及到包头部分信息,在建立连接的过程。中不在服务器端保存任何信息,所以失去了协议的许多功能,比如超时重传。此外,由于计算 cookie 有一定的运算量,增加了连接建立的延迟时间,因此,SYN Cookie 技术不能作为高性能服务器的防御手段。一些 SYN 攻击的防火墙也是基于 SYN Cookie,只是把这个功能移动到内核之外的代理服务器上。

参考资料:

https://lwn.net/Articles/277146/

https://zh.wikipedia.org/wiki/SYN_cookie