面试冲刺:04---TCP的序列号(seq)、初始序列号(ISN)、确认号(ACK)

面试冲刺:04---TCP的序列号(seq)、初始序列号(ISN)、确认号(ACK)_第1张图片

一、序列号(seq)

  • 序列号(Sequence Number)字段标识了TCP发送端到TCP接收端的数据流的一个字节,该字节代表着包含该序列号的报文段的数据中的第一个字节
  • 如果我们考虑在两个应用程序之间的一个方向上流动的数据流,TCP给每个字节赋予一个序列号。这个序列号是一 个32位的无符号数,到达2^{32}-1后再循环回到0

二、初始化序列号(ISN)

  • 当建立一个新连接时,从客户机发送至服务器的第一个报文段的SYN位字段被启用。 这样的报文段称为SYN报文段,或简单地称为SYN。然后序列号字段包含了在本次连接的这个方向上要使用的第一个序列号,后续序列号和返回的ACK号也在这个方向上(回想一 下,连接都是双向的)。注意这个数字不是0和1,而是另一个数字,经常是随机选择的,称为初始序列号(ISN)。ISN不是0和1,是因为这是一种安全措施(在后面“TCP连接管理”中介绍)。发送在本次连接的这个方向上的数据的第一个字节的序列号是ISN加1,因为SYN位字段会消耗一个序列号。正如我们稍后将见到的,消耗一个序列号也意味着使用重传进行可靠传输。因此,SYN和应用程序字节(还有FIN,稍后我们将会见到)是被可靠传输的。不消耗序列号的ACK则不是

为什么要用序列号

  • 当一个连接打开时,任何拥有合适的IP地址、端口号、符合逻辑的序列号(即在窗口中)以及正确校验和的报文段都将被对方接收。然而,这也引人了另一个问题。在一个连接中,TCP报文段在经过网络路由后可能会存在延迟抵达与排序混乱的情况。为了解决这一问题,需要仔细选择初始序列号
  • 在发送用于建立连接的SYN之前,通信双方会选择一个初始序列号。初始序列号会随时间而改变,因此每一个连接都拥有不同的初始序列号
  • [RFCO793]指出初始序列号可被视为一个32位的计数器。该计数器的数值每4微秒加1。此举的目的在于为一个连接的报文段 安排序列号,以防止出现与其他连接的序列号重叠的情况。尤其对于同一连接的两个不同实例而言,新的序列号也不能出现重叠的情况

序列号重叠问题

  • 由于一个TCP连接是被一对端点所唯一标识的,其中包括由2个IP地址与2个端口号构成的4元组,因此即便是同一个连接也会出现不同的实例。如果连接由于某个报文段的长时间延迟而被关闭,然后又以相同的4元组被重新打开,那么可以相信延迟的报文段又会被视为有效数据重新进入新连接的数据流中
  • 上述情况会令人十分烦恼。通过采取一些步骤来避免连接实例间的序列号重叠问题,能够将风险降至最低。即便如此,一个对数据完整性有较高要求的应用程序也可以在应用层利用CRC或校验和保证所需数据在传输过程中没有出现任何错误。在任何情况下这都是一种很好的方法,并已普遍用于大文件的传输

序列号带来的攻击

  • 如前文所述,一个TCP报文段只有同时具备连接的4元组与当前活动窗口的序列号,才会在通信过程中被对方认为是正确的。然而,这也从另一个侧面反映了TCP的脆弱性:如果选择合适的序列号、 IP地址以及端口号,那么任何人都能伪造出一个TCP报文段,从而打断TCP的正常连接[RFC5961]
  • 一种抵御上述行为的方法是使初始序列号(或者临时端口号)变得相对难以被猜出,而另一种方法则是加密

不同系统对序列号的实现

  • 现代系统通常采用半随机的方法选择初始序列号。证书报告CA-2001-09 [CERTISN]讨论了这一方法的具体实现细节
  • Linux系统采用一个相对复杂的过程来选择它的初始序列号。 它采用基于时钟的方案,并且针对每一个连接为时钟设置随机的偏移量。随机偏移量是在连接标识(即4元组)的基础上利用加密散列函数得到的。散列函数的输人每隔5分钟就会改变一次。在32位的初始序列号中,最高的8位是一个保密的序列号,而剩余的备位则由散列函数生成。上述方法所生成的序列号很难被猜出,但依然会随着时间而逐步增加
  • 据报告显示,Windows系统使用了一种基于RC4[S94]的类似方案

三、确认号(ACK)

  • 通过序列号我们知道每个被交换的字节都已编号,确认号字段(也简称ACK号或ACK字段)包含的值是该确认号的发送方期待接收的下一个序列号。即最后被成功接收的数据字节的序列号加1
  • 这个字段只有在ACK位字段被启用的情况下才有效,这个ACK位字段通常用于除了初始和末尾报文段之外的所有报文段。发送一个ACK与发送任何一个TCP报文段的开销是一样的,因为那个32位的ACK号字段一直都是头部的一部分,ACK位字段也一样

你可能感兴趣的:(面试冲刺)