udp協議怎麼穿透Symmetric NAT?

如題:
udp打洞時,如果兩台處於內網的電腦,至少有一台處於內網,屬於對稱結構(Symmetric),那麼怎麼為他們點對點建立通道?
除了猜測連接外網的埠(比如有的會是剛用過埠的下幾個埠),還有其他辦法嗎?

相關內容參考:
http://blog.csdn.net/jq0123/article/details/840302
NAT大致分為下面四類
1) Full Cone
這種NAT內部的機器A連接過外網機器C後,NAT會打開一個埠.然後外網的任何發到這個打開的埠的UDP數據報都可以到達A.不管是不是C發過來的.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -&> NAT(202.100.100.100 : 8000) -&> C(292.88.88.88:2000)
任何發送到 NAT(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)

2) Restricted Cone
這種NAT內部的機器A連接過外網的機器C後,NAT打開一個埠.然後C可以用任何埠和A通信.其他的外網機器不行.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -&> NAT(202.100.100.100 : 8000) -&> C(292.88.88.88:2000)
任何從C發送到 NAT(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)

3) Port Restricted Cone
這種NAT內部的機器A連接過外網的機器C後,NAT打開一個埠.然後C可以用原來的埠和A通信.其他的外網機器不行.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -&> NAT(202.100.100.100 : 8000) -&> C(292.88.88.88:2000)
C(202.88.88.88:2000)發送到 NAT(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)
以上三種NAT通稱Cone NAT.我們只能用這種NAT進行UDP打洞.

4) Symmetic
對於這種NAT.連接不同的外部目標.原來NAT打開的埠會變化.而Cone NAT不會.雖然可以用埠猜測.但是成功的概率很小.因此放棄這種NAT的UDP打洞.


正好,我們已經對UDP打洞問題研究了近一個月,對於兩方都是對稱nat的情況,至少從可以了解的途徑上(比如google,相關論壇)都沒找到解決方案,我們自己也進行過測試,不行。

但是對於一端是對稱nat,一端是埠限制性Cone nat的情況是可以打洞成功的,特別是我們實驗的對稱nat的埠變化還是有規律的(加1),我們使用埠猜測的方法進行打洞成功率還是非常高的。對於埠變化無規律的對稱nat,這個猜測還是靠演算法的設計,你可以看看
A New Method for Symmetric NAT Traversal in UDP and TCP (http://www.goto.info.waseda.ac.jp/~wei/file/wei-apan-v10.pdf)

另外如果你是做應用的話建議不要始終把自己局限於一定要打洞成功的思路上,對於一些路由器是可以通過配置支持穿透的,比如upnp;對於實在打洞不成功的情況你可以通過設計一個中轉伺服器來完成自己的應用;


把4種類型分別標為1234,有兩台主機A:portA和B:portB(port都為外網埠,是與打洞伺服器通信的埠),以及打洞伺服器S,情景是B拿到了A:portA的信息,要與A通信。
(1)、A為類型1;無論B為哪種類型,都可以直接與A:portA tcp連接;

(2)、A為類型2;無論B為哪種類型,在A知道B之前都無法直接連接,B給S發一個打洞請求,S轉發該請求到A。若B的類型為1,則A:portA可直接tcp連接到B:portB;若B的類型為2或3,則A:portA和B:portB各自向對方發送一個一位元組的udp包,分別在自己的路由器上打洞,從此A:portA和B:portB可進行udp通信;若B為類型4,則portB在與不同的ip:port通信時會不一樣,所以A:portA先向B發送一個一位元組的udp包,在路由器上打洞,然後等待B:portB先發送數據,A:portA接收到B:portB的數據後,即知道portB,也可互通數據了;

(3)、A為類型3;無論B為哪種類型,在A知道B之前都無法直接連接,B給S發一個打洞請求,S轉發該請求到A。若B的類型為1,則A:portA可直接tcp連接到B:portB;若B的類型為2或3,則A:portA和B:portB各自向對方發送一個一位元組的udp包,分別在自己的路由器上打下洞,從此A:portA和B:portB可進行udp通信;若B為類型4,則portB在與不同的ip:port通信時會不一樣,而A又要求知道portB的才可讓B:portB連進來,所以這種情況A只能猜測與A:portA通信的portB,通信概率小;

(4)、A為類型4;無論B為哪種類型,在A知道B之前都無法直接連接,B給S發一個打洞請求,S轉發該請求到A。若B的類型為1,則A:portA可直接tcp連接到B:portB;若B的類型為2,則B:portB先向A發送一個一位元組的udp包,在路由器上打洞,然後等待A:portA先發送數據,B:portB接收到A:portA的數據後,即知道portA,也可互通數據了;若B的類型為3,見(3)中B為類型4的描述;若B為4,雙方無法知道對方的埠,無法通信。

ps:純手打,根據工作中的理解整理。


關於UDP/TCP打洞的原理可以參考這篇paper:
USENIX "05 ? Technical Paper, General Track
最近也在研究P2P網路中的NAT穿透,看到有說用ICE(STUN+TURN)的方式基本上可以解決所有的NAT問題,僅供參考:
STUN :RFC 5389 - Session Traversal Utilities for (NAT) (STUN)
ICE:RFC 5245 - Interactive Connectivity Establishment (ICE): A Methodology for Network Address Translator (NAT) Traversal for Offer/Answer Protocols


要做到高成功率,還是需要有伺服器進行配合,你可以參考一下webrtc的p2p連接建立的過程


不知道你要做的是怎麼樣一個應用。。。
是不是一定要自動打洞?
能否讓用戶自己配置埠映射或者用UPNP?如某些P2P下載工具,能實現這一條的用戶可獲得更多資源(多了內網資源),而無法實現者只能分享外網資源。


請參考我於 http://www.zhihu.com/question/20034397 回答的問題:
對於您的問題補充:

  1. STUN不能解決Symmetric NAT的問題
  2. 用TURN也就是Relay Server的話,就要求提前兩個要聊天的host都彼此於這個server上留下了一個開開的port,但是這個就會增加management的複雜度,以及用中間電腦來傳輸的話,速度也會受影響。

如果兩台處於內網的電腦,至少有一台處於內網
這句看的混身難受


我研究這個問題研究了很久無解,目前只能通過挖洞,建立反向隧道暫時頂一下。

PS:有篇論文叫做pwnat,如果上級路由沒有屏蔽icmp,那麼可以不用第三方伺服器。


Symmetric需要猜測的

請借鑒

去中心化的網路設計 ― P2P的實現 - 自強不息 厚德載物 - 51CTO技術博客


大姚介紹的對稱 NAT 的穿透方法,我找到了具體實現的源碼。

看了下源碼,就是用了埠預測還有生日攻擊演算法。

https://github.com/jflyup/nat_traversal

我下載後進行了測試,但源碼只實現了兩個對稱 nat 之間的打洞。

而我的環境,一個是 symmetric NAT,另外一個是 port-restricted cone。用以上的代碼測試沒有成功。

看哪位大牛再能修改完善下,再做成一個庫,那就完美了


美國有家公司號稱能做到成功率95%以上,埠預測用的是生日攻擊演算法


本人已實測成功,生日攻擊演算法確實可以解決對稱型與埠限制型之間的穿透,而且可以達到100%,現在就剩對稱型與對稱型之間沒想到好辦法。


打洞的一方 Peer 向 Symmetric NAT 網路後端的 Peer,及另外一個外網 Server,依次、連續發出 3 包數據,就有可能看到與 Symmetric NAT 打洞的【IP:Port】


推薦閱讀:

黑馬程序員有傳說中的那麼好嗎?
為什麼計算機網路話題的關注數明顯不如編程類?
「部隊里的通信兵的編程能力能爆市面上的大多數程序員」是真的嗎?
GitHub 或者其他的開源平台中是否有一些適合初學者的 C++ 項目?
如何用c操作圖片?

TAG:編程 | P2P | UDP | 計算機網路 | 計算機科學 | 網路傳輸協議 | 網路編程 | TCPIP | 對等網路P2P |