目录
攻击方法1:SYN 泛洪
SYN 泛洪是一种 TCP 拒绝服务攻击,在这种攻击中一个或多个恶意的客户端产生一系列 TCP 连接尝试( SYN 报文段),并将它们发送给一台服务器,它们通常采用 "伪造" 的源 IP 地址。服务器会为每一条 TCP 连接分配一定数量的连接资源。由于连接尚未完全建立,服务器为了维护大量的半打开连接会在耗尽自身内存后拒绝为后续的合法连接请求服务。
因为区分合法的连接尝试与 SYN 泛洪并不是一件容易的事情,所以抵御上述攻击存在一定的难度。一种针对此问题的机制被称作SYN cookies [RFC4987]。SYN cookies 的主要思想是:当一个 SYN 到达时,这条连接存储的大部分信息都会被编码并保存在SYN + ACK 报文段(第二次握手)的序列号字段。采用 SYN cookies 的目标主机不需要为进入的连接请求分配任何存储资源——只有当 SYN + ACK 报文段本身被确认后(并且已返回初始序列号)才会分配真正的内存。在这种情况下,所有重要的连接参数都能够重新获得,同时连接也能够被设置为 ESTABLISHED 状态。
在执行 SYN cookies 过程中需要服务器仔细地选择 TCP 初始序列号。本质上,服务器必须将任何必要的状态编码并存于 SYN + ACK 报文段的序列号字段。这样一个合法的客户端会将其值作为报文段的 ACK 号字段返回给服务器。很多方法都能够完成这项工作,下面将具体介绍 Linux 系统所采用的技术。
服务器在接收到一个 SYN 后会采用下面的方法设置初始序列号的数值:首 5 位是 t 模 32 的结果,其中 t 是一个 32 位的计数器,每隔 64 秒增 1;接着 3 位是对服务器最大段大小的编码值;剩余的 24 位保存了 4 元组与 t 值的散列值。该数值是根据服务器选定的散列加密算法计算得到的。
在采用 SYN cookies 方法时,服务器总是以一个 SYN + ACK 报文段作为响应(符合任何典型的 TCP 连接建立过程)。在接收到 ACK 后,如果根据其中的 t 值可以计算出与加密的散列值相同的结果,那么服务器才会为该 SYN 重新构建队列。这种方法至少有两个缺陷。首先,由于需要对最大段大小进行编码,这种方法禁止使用任意大小的报文段。其次,由于计数器会回绕,连接建立过程会因周期非常长(长于64秒)而无法正常工作。基于上述原因,这一功能并未作为默认设置。
攻击方法2:影响路径最大传输单元
另一种攻击方法与路径最大传输单元发现过程相关。在这种攻击中,攻击者伪造一个 ICMP PTB 消息(需要进行分片但设置了不分片位)。该消息包含了一个非常小的 MTU 值(例如,68字节)。这样就迫使受害的 TCP 尝试采用非常小的数据包来填充数据,从而大大降低了它的性能。
最强力的攻击方法是简单地禁用主机的路径最大传输单元发现功能。当接收到的 ICMP PTB 消息的下一跳最大传输单元小于 576字节时,其他选项会禁用路径最大传输单元发现功能。Linux 的一个系统的选项,例如:ifconfig ppp0 mtu 288。该选项会保持最小的数据包大小(为了 TCP 的大数据包)。如果该选项被固定为某一数值,那么较大的数据包则不能将 IPv4 的 DF 位置位。这种方法虽然比完全禁用路径最大传输单元发现功能更具攻击性。
TCP的路径最大传输单元发现
路径最大传输单元(MTU)是指经过两台主机之间路径的所有网络报文段中最大传输单元的最小值。知道路径最大传输单元后能够有助于一些协议(比如 TCP )避免分片。有兴趣的可以看看基于 ICMP 消息的路径最大传输单元发现(PMTUD)过程,但由于应用程序已经指定了尺寸(即非传输层协议), UDP 协议一般不会采用上述发现过程获得的数据报大小。TCP 在支持字节流抽象的实现过程中能够决定使用多大的报文段,因此它很大程度上控制了最后生成的IP数据包。
TCP 常规的路径最大传输单元发现过程如下:在一个连接建立时,TCP 使用对外接口的最大传输单元的最小值,或者根据通信对方声明的最大段大小来选择发送方的最大段大小(SMSS)。路径最大传输单元发现不允许 TCP 发送方有超过另一方所声明的最大段大小的行为。如果对方没有指明最大段大小的数值,发送方将假设采用默认的 536 字节,但是这种情况比较少见。如果为每一个目的地保存对应的路径最大传输单元,那么就能方便地对段大小进行选择。值得注意的是,一条连接的两个方向的路径最大传输单元是不同的。
一旦为发送方的最大段大小选定了初始值, TCP 通过这条连接发送的所有 IPv4 数据报都会对 DF 位字段进行设置。TCP/IP 没有 DF 位字段,因此只需要假设所有的数据报都已经设置了该字段而不必进行实际操作。如果接收到 PTB 消息, TCP 就会减少段的大小,然后用修改过的段大小进行重传。如果在 PTB 消息中已包含了下一跳推荐的最大传输单元,段大小的数值可以设置为下一跳最大传输单元的数值减去 IPv4 (或IPv6 )与 TCP 头部的大小。如果下一跳最大传输单元的数值不存在(例如,一个之前的 ICMP 错误被返回时会缺乏这一信息),发现者可能需要尝试多个数值(例如,采用二分搜索法选择一个可用的数值)。这也会影响到 TCP 的拥塞控制管理。对于分组层路径最大传输单元发现而言,除了 PTB 的消息不被使用以外其他情况基本类似。相反,执行路径最大传输单元发现的协议必须能够快速地检测消息丢弃并调整自已的数据报大小。
由于路由是动态变化的,在减少段大小的数值一段时间后需要尝试一个更大的数值(接近初始的发送方最大段大小)。根据 [RFCl191] 与 [RFC1981] 的指导意见,该时间间隔大约为 10 分钟。
在互联网环境中,由于防火墙阻塞 PTB 消息 [RFC2923] ,路径最大传输单元发现过程会存在一些问题。在各种操作问题中,黑洞问题的情况虽有所好转(在[LSlO]中,80%被调查的系统都能够正确地处理 PTB 消息),但仍悬而未决。在 TCP 实现依靠传输 ICMP 消息来调整它的段大小的情况下,如果 TCP 从未接收到任何 ICMP 消息,那么在路径最大传输单元发现过程中就会造成黑洞问题。这种情况可能由多方面的原因造成,其中包括了防火墙或 NAT 配置为禁止转发 ICMP 消息。其后果在于一旦 TCP 使用了更大的数据包将不能被正确处理。由于只是不能转发大数据包,所以诊断出这一问题是十分困难的。那些较小的数据包(比如用于建立连接的 SYN 与 SYN +ACK 数据包)是能够成功处理的。一些 TCP 实现具有 "黑洞探测" 功能。当一个报文段在反复重传数次后,将会尝试发送一个较小的报文段。
攻击方法3:破坏现有的TCP连接
另一种类型的攻击涉及破坏现有的 TCP 连接,甚至可能将其劫持(hijacking)。这一类攻击通常包含的第一步是使两个之前正在通信的 TCP 节点 "失去同步" 。这样它们将使用不正确的序列号。它们是序列号攻击的典型例子 [RFC1948] 。至少有两种方法能实现上述攻击:在连接建立过程中引发不正确的状态传输,在 ESTABLISHED 状态下产生额外的数据。一旦两端不能再进行通信(但却认为它们间拥有一个打开的连接),攻击者就能够在连接中注入新的流量,而且这些注入的流量会被 TCP 认为是正确的。
攻击方法4:欺骗攻击
有一类攻击被称作欺骗攻击。这类攻击所涉及的 TCP 报文段是由攻击者精心定制的,目的在于破坏或改变现有 TCP 连接的行为。在 [RFC4953] 中大量讨论了此类攻击及它们的防治技术。攻击者可以生成一个伪造的重置报文段并将其发送给一个 TCP 通信节点。假定与连接相关的 4 元组以及校验和都是正确的,序列号也处在正确的范围。这样就会造成连接的任意一端失败。随着互联网变得更快,为了维持性能被认为 "处于窗口" 的序列号范围也在不断地扩大,上述攻击也受到越来越多的关注。欺骗攻击还存在于其他类型的报文段(SYN,甚至 ACK )中(有时会与泛洪攻击结合使用),引发大量的问题。相关的防御技术包括:认证每一个报文段(例如,使用 TCP-AO 选项) ;要求重置报文段拥有一个特殊的序列号以代替处于某一范围的序列号;要求时间戳选项具有特定的数值;使用其他形式的 cookie 文件,让非关键的数据依赖于更加准确的连接信息或一个秘密数值。
欺骗攻击虽然不是 TCP 协议的一部分,但是能够影响 TCP 的运行。例如, ICMP 协议能够被用于修改路径最大传输单元的发现行为。它也能够被用于指出一个端口号或一台主机已失效,从而终止一个 TCP 连接。 [RFC5927] 介绍了大量的此类攻击,并且还提出了一些防御 ICMP 欺骗消息、提高鲁棒性的方法。这些建议不仅局限于验证 ICMP 消息,而且还涉及其可能包含的 TCP 报文段。例如,包含的报文段应该拥有正确的 4 元组与序列号。