TCP比看起来更难

2022-02-21 08:54:23

理论上是';它很容易编写在包级别处理TCP的软件,无论是';它是一个完整的TCP堆栈,或者只是一个需要TCP感知的包处理应用程序。主要的RFC有';非常长或者非常复杂,并且非常详细地描述事物。虽然新的扩展经常出现,但在初始握手期间的选项协商确保您可以选择支持哪些扩展。(当然,一些扩展实际上是强制性的——不支持选择性确认或窗口缩放的TCP堆栈将非常糟糕。)如果你想做的只是加载谷歌的frontpage,那么编写一个TCP堆栈可能是一个下午的黑客攻击。即使范围更大,如果只需要连接到同一内部网络上运行Linux、BSD或Windows的任意机器,也可以相当快地验证互操作性和性能。但由于TCP看起来很容易实现,所以有很多实现。一些完整的TCP堆栈,一些TCP管理中间盒,还有一些只是试图跟踪TCP连接(如防火墙)的状态。在工作中,我们的TCP堆栈没有';t只需要与数量有限的顶级操作系统进行互操作。我们每天处理数百TB的流量,流量组合为';它不在我们的控制之下。在实践中';它是完全任意的流量,处理任何可能连接到蜂窝网络的设备或任何可能具有公共IP的设备。在这种情况下,你基本上必须与一切兼容。那里';这是一些公认的民间传说,关于哪些区域在其他系统中容易出现故障,因此你需要特别注意。例如,TCP选项排序和对齐是此类问题的常见来源,在某种程度上,你也可以使用与Linuxor Windows相同的选项位置,前提是即使是最邋遢的防火墙供应商也至少已经针对这些系统进行了测试!Zero windows是另一个经常令人悲伤的来源,它的长度如此之长,以至于在多家移动运营商中,技术人员对我们使用Zero windows进行了大量有用的测试。我不';我不太清楚为什么zerowindows会有这样的名声,但我们肯定偶尔会在野外看到这类问题(例如,几年前的FreeBSD问题非常恼人)。但在这里';这是我们最近看到的一个新的例子,对于一个令人困惑的下午来说很好,这是一个我没有看到的例子';我没听说过任何关于他的恐怖故事。一位客户报告说,在使用我们的TCP实施时,某个网站出现故障,但在使用标准实施时,该网站成功。尽管如此,还是有多个不同的失败/成功案例。有时,我们看到握手之后,联系就挂了;SYNACK将完全没有选项设置(一个大红旗),通告零窗口,服务器将永远不会回复任何零窗口探测或以其他方式打开任何窗口空间:19:53:40.384444 IP 10.0.1.110.34098>;x、 x.x.x.443:Flags[S],seq 2054608140,win 29200,选项[mss 1460,nop,nop,sackOK,nop,wscale 7],长度019:53:40.779236 IP x.x.x.443>;10.0.1.110.34098:Flags[S.],seq 3403190647,ack 2054608141,win 0,length 019:53:40.885177 IP 10.0.1.110.34098>;x、 x.x.x.443:Flags[S],seq 2054608140,win 29200,选项[mss 1460,nop,nop,sackOK,nop,wscale 7],长度019:53:41.189576 IP 10.0.1.110.34098>;x、 x.x.x.443:旗帜[.],ack 1,win 29200,长度019:53:41.189576 IP 10.0.1.110.34098>;x、 x.x.x.443:旗帜[.],ack 1,win 29200,长度019:53:42.189892 IP 10.0.1.110.34098>;x、 x.x.x.443:旗帜[.],ack 1,win 64000,长度019:53:43.391186 IP 10.0.1.110.34098>;x、 x.x.x.443:旗帜[.],ack 1,win 64000,长度019:53:44.832112 IP 10.0.1.110.34098>;x、 x.x.x.443:旗帜[.],确认1,赢64000,长度0

其他时候,SYNACK的外观会更加合理,连接也会正常工作:19:29:16.457114 IP 10.0.1.110.33842>;x、 x.x.x.443:Flags[S],seq 1336309505,win 29200,选项[mss 1460,nop,nop,sackOK,nop,wscale 7],长度019:29:17.26447 IP x.x.x.443>;10.0.1.110.33842:Flags[S.],seq 2619514903,ack 1336309506,win 14600,选项[mss 1460,nop,nop,sackOK,nop,wscale 6],长度019:29:17.264556 IP 10.0.1.110.33842>;x、 x.x.x.443:旗帜[.],ack 1,win 229,长度019:29:17.265665 IP 10.0.1.110.33842>;x、 x.x.x.443:Flags[P],seq 1:305,ack 1,win 229,长度30419:29:18.059278 IP x.x.x.x.443>;10.0.1.110.33842:旗帜[.],ack 305,win 995,长度019:29:18.087425 IP x.x.x.443>;10.0.1.110.33842:旗帜[.],序列1:1461,确认305,赢1000,长度1460

还有一些时候我们';d返回两个序列号不同的synack,当然没有';t总是工作得很好:19:37:41.677890 IP 10.0.1.110.33933>;x、 x.x.x.443:Flags[S],seq 2689636737,win 29200,选项[mss 1460,nop,nop,sackOK,nop,wscale 7],长度019:37:41.877046 IP 10.0.1.110.33933>;x、 x.x.x.443:Flags[S],seq 2689636737,win 29200,选项[mss 1460,nop,nop,sackOK,nop,wscale 7],长度019:37:42.076611 IP x.x.x.443>;10.0.1.110.33933:Flags[S],seq 3107565270,ack 2689636738,win 0,长度019:37:42.275471 IP x.x.x.443>;10.0.1.110.33933:旗帜[S],序列3109157454,确认2689636738,胜利0,长度0

你可能仅仅从上面的轨迹就能猜到问题,但实际上验证它需要多次尝试,并稍微调整参数,才能找到边界条件。谁知道周围有系统可以';无法处理接收重复的SYN?这三种不同的行为似乎与未重新传输SYN、在项目发出SYNACK之前到达中间盒的重新传输以及在中间盒发出SYNACK之后到达的重新传输相对应。中间包位于澳大利亚,但最有可能的是,IP只是一个负载平衡器、透明的反向代理,或某种类似形式的流量重定向,其真正的最终目的地位于美国某地。从欧洲访问时,这导致RTTof总量约为450-550ms。我们的TCP实现有一个可变的BASE SYN重新传输timout,在本例中大约是500毫秒。大多数情况下,我们的TCP堆栈会导致页面加载失败,但如果是一个现成的堆栈,其SYN重新传输超时为1秒,页面加载就会成功。(我在上面说过,我没有听过任何关于这方面的可怕故事,当然这并不意味着那些可怕的故事不存在。在找出根本原因后,很容易找到更多关于SYN重新传输导致连接中断的报告,例如这篇涉及卫星的报道)。它';It’很容易看出,这一未知的流量重定向工具包的开发人员在这一点的功能中漏掉了一个bug。除了2G蜂窝连接、卫星通信或遭受极端缓冲区膨胀的网络之外,它';SRT可以看到足够长的RTT来触发SYN重传。见鬼,在这种情况下,我们最有可能谈论的是环绕世界的包裹。但在我看来,这是一个特别恼人的错误。从定义上讲,它是在我们在连接的另一端获得任何信息之前触发的,因此';我们不可能仅针对处于风险中的主机有条件地禁用有问题的功能。选项是要么告诉客户一些流量赢了';t工作(这通常是不可接受的,即使根本原因不可否认是在另一端),或者稍微淡化一个有用的功能,至少不比";竞争";做它';这是一堆慢慢累积起来的案例,这使得在实践中很难处理TCP,无论它看起来有多简单。