Switch-Router

TCP-In-TCP

Published at 2019-09-19 | Last Update 2019-09-19

前天晚上在家中,当我搭起熟悉的ss梯子时, 发现不可用了T.T。登陆到控制台查看,发现国内的IP被Block了。问问身边朋友,也是一样的现象,听说是因为网络安全周?!看来只能寄希望于一周后能恢复吧….

昨天瞎逛,看到一个开源项目:udp2raw-tunnel,他实现的是将一个IP报文伪装成TCP报文,目的是穿过网络中UDP防火墙.

哈?!这难道是TCP-In-TCP? 这玩意儿不是不可用吗?


很早以前就有人说过了: Why TCP Over TCP Is A Bad Idea

为了将问题描述地更清楚,我还是将隧道应用的组网画出来吧:

图中主机A和主机D通过隧道进行End to End的通信,而设备B对原始报文进行加密和封装,设备C做解封装和解密。当然B和C不一定是单独的设备,它们可以就集成在主机A和主机D中。

TCP-In-TCP的问题是: 当隧道报文在网络中丢失时,B上的TCP连接****显然会对报文进行重传,但要知道A上也有一个TCP连接****,所以A如果超时也会进行重传,而从整个网络的角度,这个重传是不必要的。但A不会理会,因为它是TCP。

TCP的设计原则是下层协议和介质是不可靠的,所以我需要自己保证。所以, TCP-In-TCP这样的双保险完全是没有必要的。不仅没必要,还有可能造成网络中重传报文过多而拥塞。


不过也有研究说TCP-In-TCP在一定条件下可以提高网络的有效吞吐率:

论文在此 Understanding TCP over TCP: Effects of TCP Tunneling on End-to-End Throughput and Latency

还是差不多的拓扑:

论文中将传播延时(propagation delay)考虑进来了, 得出的结论是当Ta和Tb都比较大时,使用TCP-In-TCP隧道反而比不使用的有效吞吐量更大。为什么呢? 原因也比较好解释:当Ta和Tb比较大时,显然在A视角里的TCP连接的RTT会比B视角里的大不少,那么如果隧道报文在网络中丢了,B重传隧道报文,而A由于超时时间还没到,就不会重传原始报文。而如果不使用隧道,那么重传的任务就还是A的,显然B重传报文的传播延时要比A重传的大。

看上去有些道理,不过当网络条件实在不好,A的超时时间也到达后,就还是会回到之前更糟糕的情况….

所以我还是认为TCP-In-TCP不是一个好主意..


那么, 本文开头提到的那个开源项目是怎么回事呢? 仔细看了看它的介绍,又下载了它的代码。噢,原来它真的只是伪装成了TCP报文,实际上隧道报文的外层TCP封装都是在用户态自己填充的TCP首部,然后通过raw socket发送;而在接收端,同样使用raw socket(关于这个,详见inet socket 与 packet socket),所以报文会提前进入raw_local_deliver上送,而不会由TCP去接收,这样也就没有了TCP状态机那一大堆复杂的东西。