上週晚上在家中,當我搭起熟悉的ss
梯子時, 發現不可用了T.T。登陸到控制檯查看,發現國內的IP被Block了。
昨天瞎逛,看到一個開源項目:udp2raw-tunnel,他實現的是將一個IP報文僞裝成TCP報文,目的是穿過網絡中UDP防火牆.
哈?!這難道是TCP-In-TCP
? 這玩意兒不是不可用嗎?
很早以前就有人說過了:
Why TCP Over TCP Is A Bad Idea
爲了將問題描述地更清楚,我還是將隧道應用的組網畫出來吧:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Xu2gTwm8-1569850816579)(/img/remote/1460000020427501?w=667&h=164)]
圖中主機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
還是差不多的拓撲:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-toN6zv1v-1569850816580)(/img/remote/1460000020427502?w=639&h=336)]
論文中將傳播延時(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狀態機那一大堆複雜的東西。